SQL Server:2つのテーブルに同時に挿入できますか?
-
05-07-2019 - |
質問
私のデータベースには、 Object_Table
、 Data_Table
、および Link_Table
という3つのテーブルが含まれています。リンクテーブルには、オブジェクトレコードのIDとデータレコードのIDの2つの列が含まれています。
特定のオブジェクトIDにリンクされている DATA_TABLE
からデータをコピーし、対応するレコードを Data_Table
および Link_Table
に挿入したい異なる特定のオブジェクトID。
テーブル変数を選択し、反復ごとに2回挿入することでループすることにより、これをできます。
これが最善の方法ですか?
編集:ループを避けたい理由は2つあります。1つ目は、怠け者で、ループ/一時テーブルに多くのコードが必要なためです。 2番目の理由はパフォーマンスに関する懸念です。
1回の挿入ですべてのデータをコピーできますが、各レコードに新しいIDがある新しいデータレコードにリンクテーブルをリンクするにはどうすればよいですか?
解決 3
以下は、テーブル変数を使用して、私が持っていた状況を設定します。
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
して、通常の挿入で終了できます。したがって、ループを回避できますが、一時テーブルは回避できません。
他のヒント
1つのステートメント:いいえ。
1つのトランザクション:はい
BEGIN TRANSACTION
DECLARE @DataID int;
INSERT INTO DataTable (Column1 ...) VALUES (....);
SELECT @DataID = scope_identity();
INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT
良いニュースは、上記のコードも atomic であることが保証されており、1つの関数呼び出しで1つのsql文字列を含むクライアントアプリケーションからサーバーに送信できることです。ステートメント。また、1つのテーブルにトリガーを適用して、単一の挿入の効果を得ることができます。ただし、最終的にはまだ2つのステートメントであり、おそらく every 挿入のトリガーを実行したくないでしょう。
まだ2つの INSERT
ステートメントが必要ですが、最初の挿入から IDENTITY
を取得し、2番目の挿入で使用したいようです。その場合、 OUTPUT
または OUTPUT INTO
を調べてください: http://msdn.microsoft.com/en-us/library/ms177564.aspx
Linkテーブルは、ObjectテーブルとDataテーブル間のmany:many関係をキャプチャしているようです。
私の提案は、ストアドプロシージャを使用してトランザクションを管理することです。オブジェクトまたはデータテーブルに挿入する場合は、挿入を実行し、新しいIDを取得してリンクテーブルに挿入します。
これにより、すべてのロジックが1つの簡単なsprocにカプセル化されたままになります。
アクションを多少アトミックにしたい場合は、必ずトランザクションでラップするようにします。そうすれば、必要に応じて両方が発生したか、両方が発生しなかったかを確認できます。
挿入ステートメントに必要な列名を選択するビューを作成し、INSTEAD OF INSERTトリガーを追加して、このビューに挿入します。
使用について強調したい
SET XACT_ABORT ON;
複数のSQLステートメントを含むMSSQLトランザクションの場合。
参照: https://msdn.microsoft.com/en-us/ library / ms188792.aspx 非常に良い例です。
したがって、最終的なコードは次のようになります。
SET XACT_ABORT ON;
BEGIN TRANSACTION
DECLARE @DataID int;
INSERT INTO DataTable (Column1 ...) VALUES (....);
SELECT @DataID = scope_identity();
INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT
挿入は、一度に1つのテーブルに対してのみ操作できます。複数の挿入には複数のステートメントが必要です。
テーブル変数をループ処理する必要があることはわかりません-あるテーブルに一括挿入を使用してから、別のテーブルに一括挿入を使用することはできませんか?
ところで-Object_Tableからデータをコピーするつもりだと思います。そうでない場合、質問は意味がありません。
Oracleでマルチテーブル挿入を実行する前に、挿入を実行するINSTEAD OFトリガーが定義されたビューへの挿入を含むトリックを使用できます。これはSQL Serverで実行できますか?
-- ================================================
-- Template generated from Template Explorer using:
-- Create Procedure (New Menu).SQL
--
-- Use the Specify Values for Template Parameters
-- command (Ctrl-Shift-M) to fill in the parameter
-- values below.
--
-- This block of comments will not be included in
-- the definition of the procedure.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE InsetIntoTwoTable
(
@name nvarchar(50),
@Email nvarchar(50)
)
AS
BEGIN
SET NOCOUNT ON;
insert into dbo.info(name) values (@name)
insert into dbo.login(Email) values (@Email)
END
GO
//最初のテーブルと同じものを挿入する場合
$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);
//表の特定の部分を挿入する場合
$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);
// iは、見栄えが良すぎますが、機能し、クエリの追加を続けるだけで変更できます
"$qry"-number and number in @mysql_query($qry"")
これで機能した17個のテーブルがあります。