0

FORESTTREE (s) が含まれ、TREE (s) にBRANCH (es)がある次の不自然な例を考えてみましょう。さらに、 FLOCK (s) にはBIRD ( s) が含まれ、 BIRD (s) はBRANCHにある場合とない場合があります。

CREATE TABLE 'FOREST' (
forest_id INT(11) NOT NULL AUTO_INCREMENT,
'name'    VARCHAR(45) NOT NULL,
...
)

CREATE TABLE 'TREE' (
'tree_id'    INT(11) NOT NULL AUTO_INCREMENT,
'forest_id'  INT(11) NOT NULL ,
'tree_loc_x' INT NOT NULL,
'tree_loc_y' INT NOT NULL,
...
CONSTRAINT 'fk_tree_forest'
    FOREIGN KEY ('forest_id' )
    REFERENCES `FOREST` ('forest_id' )
)

CREATE TABLE 'BRANCH' (
'branch_id' INT(11) NOT NULL AUTO_INCREMENT,
'tree_id'   INT(11) NOT NULL,
'br_loc_x'  INT NOT NULL,
'br_loc_y'  INT NOT NULL,
'br_loc_z'  INT NOT NULL,
...
CONSTRAINT 'fk_branch_tree'
   FOREIGN KEY ('tree_id' )
   REFERENCES `TREE` ('tree_id' )
)

CREATE  TABLE 'FLOCK' (
  'flock_id' INT NOT NULL AUTO_INCREMENT ,
  'name'     VARCHAR(45) NOT NULL
...
)

CREATE  TABLE 'BIRD' (
  'bird_id'   INT(11) NOT NULL AUTO_INCREMENT ,
  'flock_id'  INT(11) NOT NULL ,
  'branch_id' INT(11) NULL ,
  'bird_tag'  VARCHAR(45) NOT NULL ,
...
  CONSTRAINT 'fk_bird_flock'
    FOREIGN KEY ('flock_id' )
    REFERENCES 'FLOCK' ('flock_id' )
  CONSTRAINT 'fk_bird_branch'
    FOREIGN KEY ('branch_id' )
    REFERENCES 'BRANCH' ('branch_id' )
 )

C++ アプリケーションから一括タイプのロード (マルチ挿入ステートメントまたは LOAD DATA INFILE のいずれか) を使用して、各テーブルをロードしたいと考えています。

データベースに割り当てられたauto_increment値を取得して、後続の各テーブルロードの外部キーとして使用する最良の方法は何ですか.

テーブルは必ずしもカスケード方式でロードできるとは限らないことに注意してください (つまり、BIRDS は BRANCHES の直後ではなく FLOCKS の後にロードされるため、BRANCHES に関して BIRDS をロードする場合、「LAST_INSERT_ID」は役に立ちません)。

各テーブルには自然キーの候補がありますが、それらを主キーまたは外部キーとして使用しないようにしています。

4

1 に答える 1

0

LOAD DATA INFILE (または INSERT...SELECT などの他の複数行の INSERT) を使用すると、その後の LAST_INSERT_ID() の呼び出しでは、生成された最初のID 値のみが返されます。しかし、InnoDB は id を連続したブロックとして割り当てるため、1000 行を挿入し、LAST_INSERT_ID() が 1234 を報告した場合、データ ロードで 1234 から 2233 までの id が使用されたことがわかります。

(auto_incrment_increment = 1 と仮定します。そうでない場合、データ ロードでは次の 1000 個の連続した ID が使用されると言う方が正確です。)

しかし、ツリーの後にブランチを一括ロードすると、各ブランチがどのツリーに属しているかがわからないという問題があります。枝が 1 つしかない木もあれば、6 つある木もあります。1000 本の木と 1000 本の枝があるからといって、必ずしも均等に分布するとは限りません。枝に鳥がいる場合などは、さらに複雑になります。

最終的に、データを複数のテーブルに一括ロードし、対応する生成された ID をすべて保持することは実用的ではありません。すべての入力ファイルを自分で 1 行ずつループするコードを作成し、LAST_INSERT_ID() を行ごとにキャプチャして依存行で使用する必要があります。私はより良い解決策を見つけていません。

鳥がそれぞれの枝と群れの両方への外部キーを持っているというより複雑なケースでは、各枝の挿入 ID を追跡し、それを自然キーにマップすることを試みることができます。そのマッピングをメモリに保持することは非現実的になります。特定のスケールでは、枝または群れのいずれかを挿入するときに鳥を挿入することを選択できますが、両方を挿入することはできません (枝と群れの間には多対多の関係があり、それらが適切に分類されるとは想定できないため)。 . したがって、鳥を挿入するには、枝または群れのいずれかを NULL のままにしておく必要があり、後で不足しているデータを UPDATE で埋める必要があります。

于 2013-07-10T00:19:44.200 に答える