我的数据库包含三个表,分别称为
Object_Table
、Data_Table
和 Link_Table
。链接表只包含两列,对象记录的标识和数据记录的标识。
我想从链接到一个给定对象标识的
DATA_TABLE
复制数据,并将相应的记录插入 Data_Table
和 Link_Table
以获得不同的给定对象标识。
我可以通过选择表变量并循环为每次迭代执行两次插入来做到这一点。
这是最好的方法吗?
编辑:我想避免循环有两个原因,第一个是我很懒,循环/临时表需要更多代码,更多代码意味着更多地方会犯错误,第二个原因是担心性能。
我可以复制一次插入中的所有数据,但如何让链接表链接到新的数据记录,其中每条记录都有一个新的 id?
在一份声明中:不。
在一笔交易中:是
START TRANSACTION;
INSERT INTO DataTable (Column1 ...) VALUES (....);
INSERT INTO LinkTable VALUES (@ObjectID, LAST_INSERT_ID());
COMMIT;
好消息是,上述代码也保证是“原子的”,并且可以在单个函数调用中使用一个 sql 字符串从客户端应用程序发送到服务器,就好像它是一条语句一样。您还可以将触发器应用于一个表以获得单个插入的效果。但是,它最终仍然是两个语句,您可能不想为 every 插入运行触发器。
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
临时表,然后完成正常插入。所以我可以避免循环,但无法避免临时表。
SET XACT_ABORT ON;
对于具有多个sql语句的MSSQL事务。
请参阅:
https://msdn.microsoft.com/en-us/library/ms188792.aspxSET XACT_ABORT ON;
BEGIN TRANSACTION
DECLARE @DataID int;
INSERT INTO DataTable (Column1 ...) VALUES (....);
SELECT @DataID = scope_identity();
INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT
我的建议是使用存储过程来管理事务。当您想要插入到对象或数据表时执行插入,获取新 ID 并将它们插入到链接表中。
这允许您的所有逻辑保持封装在一个易于调用的存储过程中。
我不知道您需要循环遍历表变量 - 难道您不能只使用批量插入到一个表中,然后批量插入到另一个表中吗?
顺便说一下 - 我猜你的意思是从 Object_Table 复制数据;否则这个问题就没有意义。
$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 张桌子都用过这个。