我有一个带有'id'列和其他各个列的表。每行数据将具有唯一的“ id”。此“ id”在另一个表中引用,该表也具有带有唯一“ id”的行。每一个都在另一个表中引用。
我们将表称为“ items”,“ item_options”和“ sub_options”。我想复制“项目”中的一行,还复制“ item_options”中与其ID关联的所有内容,以及“ item_options”中与ID关联的“ sub_options”中的所有内容。
例如:
在“项目”中说,列是“ id”和“ title”。
在“ item_options”中,列为“ id”,“ itemID”和“ option”。
在“ sub_options”中,列为“ id”,“ item_optionsID”和“ subOption”。
我可以做到这一点:
insert into dbo.items (title)
select title
from dbo.items where id = '123'
从这里开始,我一直在返回“ itmes”中新复制的行的新id,然后使用服务器端语言遍历并复制“ item_options”,然后遍历那些以复制“ sub_options”,但是我经常碰到数据库,而性能却受到打击。
我想用SQL进行全部操作,但似乎无法弄清楚。
对于示例数据,我将尝试以下方法:
dbo.items
id:“ 123”
标题:“新车”
dbo.item_options
id:“ 456”
itemID:“ 123”
选项:“自定义车轮”
id:'457'
itemID:“ 123”
选项:“自定义绘画”
dbo.sub_options
id:“ 789”
item_optionsID:“ 456”
子选项:“ Chrome”
id:“ 790”
item_optionsID:“ 456”
子选项:“ 20英寸”
id:'791'
item_optionsID:“ 457”
子选项:“红色”
基本上,我想复制所有这些,同时使ID与复制时所有新生成的ID都匹配。
答案 0 :(得分:0)
您需要在插入每个表中时捕获新的“ id”值,以将其用于子表中的外键引用。捕获新“ id”的最可靠方法是使用SQL output clause,因为它将始终提供正确的ID并可以处理多个ID(许多其他方法来获取新创建的记录ID都应避免陷阱)
您还希望将其包装在事务中以确保其全部或全部操作(您可能还需要其他错误处理)。
由于output
语句上的insert
子句不允许原始表中的值,因此我在第二部分中使用了merge
语句,匹配条件为{ {1}},即它永远不会匹配,因此总是插入,并且1=0
语句的确允许来自merge
子句中原始表的值。
output
答案 1 :(得分:0)
已更新(经过OP澄清):
您正在尝试在表items
中插入新行,并且需要保存新生成的ID(AKA IDENTITY),以便将该行用作其他插入操作中的FK(在您的情况下,想要在item_options中使用它)。
如果items
和item_options
中的ID是身份,则可以使用SCOPE_IDENTITY()
SCOPE_IDENTITY()
返回插入到的身份列中的最后一个身份值 范围相同
因此,您的插入内容将像这样简单:
INSERT INTO dbo.items (title) VALUES ('New Car')
INSERT INTO item_options (itemId, [option]) VALUES (SCOPE_IDENTITY(), 'Custom Wheels')
INSERT INTO sub_options (item_optionsId, subOption) VALUES (SCOPE_IDENTITY(), 'Chrome')
第一个SCOPE_IDENTITY()
将使用item中最后生成的ID,第二个将使用item_options id,依此类推。
您还可以将id存储在变量中,以进一步使用,如下所示:
DECLARE
@itemId INT
, @optionId INT
INSERT INTO dbo.items (title) VALUES ('New Car')
SELECT @itemId = SCOPE_IDENTITY()
INSERT INTO item_options (itemId, [option]) VALUES (@itemId, 'Custom Wheels')
SELECT @optionId = SCOPE_IDENTITY()
INSERT INTO sub_options (item_optionsId, subOption) VALUES (@optionId, 'Chrome')
这将为您提供超出其范围的ID的更多灵活性。
我希望这可以解决您的难题。