是否可以同时插入两个表?

问题描述 投票:0回答:11

我的数据库包含三个表,分别称为

Object_Table
Data_Table
Link_Table
。链接表只包含两列,对象记录的标识和数据记录的标识。

我想从链接到一个给定对象标识的

DATA_TABLE
复制数据,并将相应的记录插入
Data_Table
Link_Table
以获得不同的给定对象标识。

可以通过选择表变量并循环为每次迭代执行两次插入来做到这一点。

这是最好的方法吗?

编辑:我想避免循环有两个原因,第一个是我很懒,循环/临时表需要更多代码,更多代码意味着更多地方会犯错误,第二个原因是担心性能。

我可以复制一次插入中的所有数据,但如何让链接表链接到新的数据记录,其中每条记录都有一个新的 id?

sql sql-server insert temp-tables
11个回答
277
投票

在一份声明中:不。

在一笔交易中:是

START TRANSACTION;
   INSERT INTO DataTable (Column1 ...) VALUES (....);
   INSERT INTO LinkTable VALUES (@ObjectID, LAST_INSERT_ID());
COMMIT;

好消息是,上述代码也保证是“原子的”,并且可以在单个函数调用中使用一个 sql 字符串从客户端应用程序发送到服务器,就好像它是一条语句一样。您还可以将触发器应用于一个表以获得单个插入的效果。但是,它最终仍然是两个语句,您可能不想为 every 插入运行触发器。


40
投票
INSERT

语句,但听起来您想从第一个插入中获取

IDENTITY
并在第二个插入中使用它,在这种情况下,您可能需要查看
OUTPUT
OUTPUT INTO
http://msdn.microsoft.com/en-us/library/ms177564.aspx


23
投票

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

临时表,然后完成正常插入。所以我可以避免循环,但无法避免临时表。

    


19
投票

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



6
投票

我的建议是使用存储过程来管理事务。当您想要插入到对象或数据表时执行插入,获取新 ID 并将它们插入到链接表中。

这允许您的所有逻辑保持封装在一个易于调用的存储过程中。


4
投票


4
投票


3
投票


2
投票

我不知道您需要循环遍历表变量 - 难道您不能只使用批量插入到一个表中,然后批量插入到另一个表中吗?

顺便说一下 - 我猜你的意思是从 Object_Table 复制数据;否则这个问题就没有意义。


-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);


//或者如果您想插入表一的某些部分

$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 张桌子都用过这个。


-3
投票
© www.soinside.com 2019 - 2024. All rights reserved.