簡體   English   中英

SQL 服務器:是否可以同時插入兩個表?

[英]SQL Server: Is it possible to insert into two tables at the same time?

我的數據庫包含三個名為Object_TableData_TableLink_Table的表。 鏈接表只包含兩列,一個 object 記錄的標識和一個數據記錄的標識。

我想從DATA_TABLE復制數據,其中它鏈接到一個給定的 object 身份,並將相應的記錄插入Data_TableLink_Table以獲得不同的給定 object 身份。

可以通過選擇一個表變量並通過為每次迭代執行兩次插入循環來做到這一點。

這是最好的方法嗎?

編輯:我想避免循環有兩個原因,第一個是我很懶,循環/臨時表需要更多的代碼,更多的代碼意味着更多的地方出錯,第二個原因是擔心性能。

我可以在一次插入中復制所有數據,但是如何讓鏈接表鏈接到每條記錄都有一個新 ID 的新數據記錄?

在一個陳述中 :不。

一筆交易 :是

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

好消息是,上述代碼也保證是原子的 ,並且可以在單個函數調用中使用一個sql字符串從客戶端應用程序將其發送到服務器,就好像它是一條語句一樣。 您也可以將觸發器應用於一個表以獲得單個插入的效果。 但是,最終仍然是兩個語句,您可能不想為每個插入運行觸發器。

您仍然需要兩個INSERT語句,但這聽起來像您想從第一個插入中獲取IDENTITY並在第二個插入中使用它,在這種情況下,您可能想要查看OUTPUTOUTPUT INTOhttp : //msdn.microsoft .com / zh-CN / library / ms177564.aspx

下面使用表變量設置我遇到的情況。

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一個臨時表,然后完成正常插入。 因此,我可以避免循環,但無法避免臨時表。

聽起來鏈接表捕獲了Object表和Data表之間的many:many關系。

我的建議是使用存儲過程來管理事務。 當您想插入到對象或數據表中時,請執行插入操作,獲取新的ID並將其插入到鏈接表中。

這使您所有的邏輯都可以封裝在一個易於調用的sproc中。

如果您希望這些動作或多或少是原子的,那么請確保將它們包裝在事務中。 這樣,您可以確保根據需要同時發生或未發生。

您可以創建一個視圖,選擇您的插入語句所需的列名,添加一個INSTEAD OF INSERT觸發器,然后插入到該視圖中。

我想強調使用

SET XACT_ABORT ON;

用於具有多個sql語句的MSSQL事務。

請參閱: https : //msdn.microsoft.com/zh-cn/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

插入一次只能在一張桌子上操作。 多個插入必須具有多個語句。

我不知道您需要遍歷一個表變量-您不能只在一個表中使用大容量插入,然后在另一個表中使用大容量插入嗎?

順便說一句-我猜你的意思是從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);

//我知道它看起來太好了,但是沒用,但是您可以繼續添加查詢,只需更改

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

我有17張桌子一直在工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM