OUTPUT INTO子句中可以使用哪些列?
我正在尝试构建映射表,以将表中新行的ID与从中复制新行的ID相关联。 OUTPUT INTO子句对此似乎很完美,但是根据文档来看,它似乎并不起作用。
我的代码:
DECLARE @Missing TABLE (SrcContentID INT PRIMARY KEY ) INSERT INTO @Missing ( SrcContentID ) SELECT cshadow.ContentID FROM Private.Content AS cshadow LEFT JOIN Private.Content AS cglobal ON cshadow.Tag = cglobal.Tag WHERE cglobal.ContentID IS NULL PRINT 'Adding new content headers' DECLARE @Inserted TABLE (SrcContentID INT PRIMARY KEY, TgtContentID INT ) INSERT INTO Private.Content ( Tag, Description, ContentDate, DateActivate, DateDeactivate, SortOrder, CreatedOn, IsDeleted, ContentClassCode, ContentGroupID, OrgUnitID ) OUTPUT cglobal.ContentID, INSERTED.ContentID INTO @Inserted (SrcContentID, TgtContentID) SELECT Tag, Description, ContentDate, DateActivate, DateDeactivate, SortOrder, CreatedOn, IsDeleted, ContentClassCode, ContentGroupID, NULL FROM Private.Content AS cglobal INNER JOIN @Missing AS m ON cglobal.ContentID = m.SrcContentID
错误消息的结果:
Msg 207, Level 16, State 1, Line 34 Invalid column name 'SrcContentID'.
(第34行是具有" OUTPUT INTO"的输出)
实验表明,只有在INSERT目标中实际存在的行才能在OUTPUT INTO中选择。但这与在线书籍中的文档相矛盾。关于OUTPUT子句的文章有示例E,描述了类似的用法:
The OUTPUT INTO clause returns values from the table being updated (WorkOrder) and also from the Product table. The Product table is used in the FROM clause to specify the rows to update.
有人使用过此功能吗?
(与此同时,我已经重写了代码以使用游标循环来完成这项工作,但这很丑陋,但我仍然很好奇)
解决方案
我已经证实问题是我们只能使用" INSERTED"列。该文档似乎表明我们可以使用from_table_name
,但是我似乎无法使其正常工作(无法绑定多部分标识符" m.ContentID"。):
TRUNCATE TABLE main SELECT * FROM incoming SELECT * FROM main DECLARE @Missing TABLE (ContentID INT PRIMARY KEY) INSERT INTO @Missing(ContentID) SELECT incoming.ContentID FROM incoming LEFT JOIN main ON main.ContentID = incoming.ContentID WHERE main.ContentID IS NULL SELECT * FROM @Missing DECLARE @Inserted TABLE (ContentID INT PRIMARY KEY, [Content] varchar(50)) INSERT INTO main(ContentID, [Content]) OUTPUT INSERTED.ContentID /* incoming doesn't work, m doesn't work */, INSERTED.[Content] INTO @Inserted (ContentID, [Content]) SELECT incoming.ContentID, incoming.[Content] FROM incoming INNER JOIN @Missing AS m ON m.ContentID = incoming.ContentID SELECT * FROM @Inserted SELECT * FROM incoming SELECT * FROM main
显然,from_table_name前缀只允许在DELETE或者UPDATE或者2008年的MERGE上使用,我不确定为什么:
- from_table_name
是列前缀,用于指定包含在" DELETE"或者" UPDATE"语句的" FROM"子句中的表,该表用于指定要更新或者删除的行。
如果在" FROM"子句中也指定了要修改的表,则对该表中列的任何引用都必须使用" INSERTED"或者" DELETED"前缀进行限定。
我遇到了与我们完全相同的问题,我感到痛苦...
据我所知,还没有办法在INSERT语句中使用from_table_name前缀。
我敢肯定有一个可行的技术原因,我很想知道它到底是什么。
好的,找到它了,这是一个关于为什么它不起作用的论坛帖子:
MSDN论坛
我想我找到了解决这个问题的方法,可悲的是它涉及一个临时表,但至少可以防止创建可怕的游标:)
我们需要做的是在要从中复制记录的表中添加一个额外的列,并为其指定" uniqueidentifer"类型。
然后声明一个临时表:
DECLARE @tmptable TABLE (uniqueid uniqueidentifier, original_id int, new_id int)
像这样将数据插入到临时表中:
insert into @tmptable (uniqueid,original_id,new_id) select NewId(),id,0 from OriginalTable
继续并真正插入到原始表中:
insert into OriginalTable (uniqueid) select uniqueid from @tmptable
现在,将新创建的标识值添加到临时表中:
update @tmptable set new_id = o.id from OriginalTable o inner join @tmptable tmp on tmp.uniqueid = o.uniqueid
现在,我们有了一个查找表,该表在一条记录中保存了新ID和原始ID,以供我们使用:)
我希望这对某人有帮助...
(MS)如果也在FROM子句中指定了要修改的表,则对该表中列的任何引用都必须使用INSERTED或者DELETED前缀进行限定。
在示例中,我们不能在OUTPUT中使用cglobal表,除非它是INSERTED.column_name或者DELETED.column_name:
INSERT INTO Private.Content (Tag) OUTPUT cglobal.ContentID, INSERTED.ContentID INTO @Inserted (SrcContentID, TgtContentID) SELECT Tag FROM Private.Content AS cglobal INNER JOIN @Missing AS m ON cglobal.ContentID = m.SrcContentID
对我有用的是一个简单的别名表,如下所示:
INSERT INTO con1 (Tag) OUTPUT **con2**.ContentID, INSERTED.ContentID INTO @Inserted (SrcContentID, TgtContentID) SELECT Tag FROM Private.Content con1 **INNER JOIN Private.Content con2 ON con1.id=con2.id** INNER JOIN @Missing AS m ON con1.ContentID = m.SrcContentID