我的数据库包含三个表叫Object_Table,Data_Table和Link_Table。链接表仅包含两列,即对象记录的标识和数据记录的标识。
Object_Table
Data_Table
Link_Table
我想从DATA_TABLE链接到一个给定对象标识的位置复制数据,Data_Table并Link_Table在不同的给定对象标识中插入相应的记录。
DATA_TABLE
我 可以 通过选择一个表变量,并为每次迭代进行两次插入来循环执行此操作。
这是最好的方法吗?
编辑 :我想避免循环的原因有两个,第一个是我很懒,并且循环/临时表需要更多的代码,更多的代码意味着有更多的地方出错,第二个原因是对性能的关注。
我可以在一个插入中复制所有数据,但是如何获得链接表以链接到新数据记录,其中每个记录都有一个新的ID?
下面使用表变量设置我遇到的情况。
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使用临时表,然后以正常插入结束。因此,我可以避免循环,但无法避免临时表。
OUTPUT INTO
In one statement: No.
In one transaction: Yes
BEGIN TRANSACTION DECLARE @DataID int; INSERT INTO DataTable (Column1 ...) VALUES (....); SELECT @DataID = scope_identity(); INSERT INTO LinkTable VALUES (@ObjectID, @DataID); COMMIT
好消息是,上述代码也保证是原子的,并且可以在单个函数调用中使用一个sql字符串从客户端应用程序将其发送到服务器,就好像它是一条语句一样。您还可以将触发器应用于一个表以获得单个插入的效果。但是,最终仍然是两个语句,您可能不想为每个插入都运行触发器。