170

Object_Table私のデータベースには、、、Data_Tableと呼ばれる3つのテーブルが含まれていますLink_Table。リンクテーブルには、オブジェクトレコードのIDとデータレコードのIDの2つの列が含まれています。

ある特定のオブジェクトIDにリンクされている場所からデータをコピーし、対応するレコードを別の特定のオブジェクトIDDATA_TABLEに挿入したいと思います。Data_TableLink_Table

これを行うに、テーブル変数を選択し、反復ごとに2つの挿入を実行してループします。

これはそれを行うための最良の方法ですか?

編集:2つの理由でループを避けたいと思います。1つは怠惰でループ/一時テーブルに必要なコードが多いこと、コードが多いほど間違いを犯す場所が多いこと、2つ目はパフォーマンスに関する懸念です。

1回の挿入ですべてのデータをコピーできますが、各レコードが新しいIDを持つ新しいデータレコードにリンクテーブルをリンクするにはどうすればよいですか?

4

11 に答える 11

258

1つのステートメントで:いいえ。

1つのトランザクションで:はい

BEGIN TRANSACTION
   DECLARE @DataID int;
   INSERT INTO DataTable (Column1 ...) VALUES (....);
   SELECT @DataID = scope_identity();
   INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT

幸いなことに、上記のコードもアトミックであることが保証されており、1つのステートメントであるかのように1回の関数呼び出しで1つのSQL文字列を使用してクライアントアプリケーションからサーバーに送信できます。1つのテーブルにトリガーを適用して、単一の挿入の効果を取得することもできます。ただし、最終的には2つのステートメントであり、挿入ごとにトリガーを実行する必要はないでしょう。

于 2008-10-06T16:49:35.730 に答える
39

まだ2つのINSERTステートメントが必要ですがIDENTITY、最初の挿入からを取得して2番目の挿入で使用したいようです。その場合は、OUTPUTまたはhttp://msdn.microsoft.com/en-OUTPUT INTOを調べてください。 us / library / ms177564.aspx

于 2008-10-06T16:49:21.860 に答える
20

以下は、テーブル変数を使用して、私が持っていた状況を設定します。

DECLARE @Object_Table TABLE
(
    Id INT NOT NULL PRIMARY KEY
)

DECLARE @Link_Table TABLE
(
    ObjectId INT NOT NULL,
    DataId INT NOT NULL
)

DECLARE @Data_Table TABLE
(
    Id INT NOT NULL Identity(1,1),
    Data VARCHAR(50) NOT NULL
)

-- create two objects '1' and '2'
INSERT INTO @Object_Table (Id) VALUES (1)
INSERT INTO @Object_Table (Id) VALUES (2)

-- create some data
INSERT INTO @Data_Table (Data) VALUES ('Data One')
INSERT INTO @Data_Table (Data) VALUES ('Data Two')

-- link all data to first object
INSERT INTO @Link_Table (ObjectId, DataId)
SELECT Objects.Id, Data.Id
FROM @Object_Table AS Objects, @Data_Table AS Data
WHERE Objects.Id = 1

OUTPUT 句を指摘してくれた別の回答のおかげで、解決策を示すことができます。

-- now I want to copy the data from from object 1 to object 2 without looping
INSERT INTO @Data_Table (Data)
OUTPUT 2, INSERTED.Id INTO @Link_Table (ObjectId, DataId)
SELECT Data.Data
FROM @Data_Table AS Data INNER JOIN @Link_Table AS Link ON Data.Id = Link.DataId
                INNER JOIN @Object_Table AS Objects ON Link.ObjectId = Objects.Id 
WHERE Objects.Id = 1

ただし、次のエラーのため、実際にはそれほど単純ではないことがわかります

OUTPUT INTO 句は、(主キー、外部キー) 関係のどちら側にも置くことはできません

まだOUTPUT INTO一時テーブルを作成してから、通常の挿入で終了できます。したがって、ループは回避できますが、一時テーブルは回避できません。

于 2008-10-06T19:16:38.383 に答える
6

リンクテーブルは、オブジェクトテーブルとデータテーブルの間のmany:many関係をキャプチャしているように聞こえます。

私の提案は、トランザクションを管理するためにストアドプロシージャを使用することです。オブジェクトまたはデータテーブルに挿入する場合は、挿入を実行し、新しいIDを取得してリンクテーブルに挿入します。

これにより、すべてのロジックを1つの簡単に呼び出すことができるsprocにカプセル化したままにすることができます。

于 2008-10-06T16:50:33.013 に答える
4

アクションを多かれ少なかれアトミックにしたい場合は、それらをトランザクションでラップするようにします。そうすれば、必要に応じて両方が発生したか、両方が発生しなかったかを確認できます。

于 2008-10-06T16:42:25.137 に答える
4

挿入ステートメントに必要な列名を選択するビューを作成し、INSTEAD OF INSERT トリガーを追加して、このビューに挿入することができます。

于 2008-10-06T16:53:26.237 に答える
3

Oracle で複数テーブルの挿入を実行できるようになる前に、INSTEAD OF トリガーが定義されているビューへの挿入を含むトリックを使用して、挿入を実行できます。これは SQL Server で実行できますか?

于 2008-10-06T17:25:59.493 に答える
2

Insert は、一度に 1 つのテーブルに対してのみ操作できます。複数の挿入には複数のステートメントが必要です。

テーブル変数をループする必要があるかどうかはわかりません.1つのテーブルに大量挿入を使用してから、もう1つのテーブルに大量挿入を使用することはできませんか?

ところで、Object_Table からデータをコピーするという意味だと思います。そうでなければ、質問は意味がありません。

于 2008-10-06T16:42:51.813 に答える
-3

//最初のテーブルと同じものを挿入する場合

$qry = "INSERT INTO table (one, two, three) VALUES('$one','$two','$three')";

$result = @mysql_query($qry);

$qry2 = "INSERT INTO table2 (one,two, three) VVALUES('$one','$two','$three')";

$result = @mysql_query($qry2);

//またはテーブル1の特定の部分を挿入する場合

 $qry = "INSERT INTO table (one, two, three) VALUES('$one','$two','$three')";


  $result = @mysql_query($qry);

 $qry2 = "INSERT INTO table2 (two) VALUES('$two')";

 $result = @mysql_query($qry2);

//見た目が良すぎて正しくないことはわかっていますが、機能し、クエリを追加し続けることができます。

    "$qry"-number and number in @mysql_query($qry"")

私はこれが働いた17のテーブルを持っています。

于 2011-03-31T23:10:30.923 に答える