SQL Output子句可以返回一个没有被插入的列吗?
我对数据库做了一些修改,我需要将旧数据迁移到新表中。 为此,我需要填写一个表(ReportOptions)从原始表(Practice)中取数据,并填写第二个中间表(PracticeReportOption)。
ReportOption (ReportOptionId int PK, field1, field2...) Practice (PracticeId int PK, field1, field2...) PracticeReportOption (PracticeReportOptionId int PK, PracticeId int FK, ReportOptionId int FK, field1, field2...)
我做了一个查询,以获得所有我需要从实践移动到ReportOptions的数据,但是我无法填充中间表
--Auxiliary tables DECLARE @ReportOption TABLE (PracticeId int /*This field is not on the actual ReportOption table*/, field1, field2...) DECLARE @PracticeReportOption TABLE (PracticeId int, ReportOptionId int, field1, field2) --First I get all the data I need to move INSERT INTO @ReportOption SELECT P.practiceId, field1, field2... FROM Practice P --I insert it into the new table, but somehow I need to have the repation PracticeId / ReportOptionId INSERT INTO ReportOption (field1, field2...) OUTPUT @ReportOption.PracticeId, --> this is the field I don't know how to get inserted.ReportOptionId INTO @PracticeReportOption (PracticeId, ReportOptionId) SELECT field1, field2 FROM @ReportOption --This would insert the relationship, If I knew how to get it! INSERT INTO @PracticeReportOption (PracticeId, ReportOptionId) SELECT PracticeId, ReportOptionId FROM @ReportOption
如果我可以引用一个不在OUTPUT子句的目标表上的字段,这将是很好的(我想我不能,但我不知道)。 任何想法如何满足我的需要?
提前致谢。
您可以通过使用MERGE
而不是插入:
所以replace这个
INSERT INTO ReportOption (field1, field2...) OUTPUT @ReportOption.PracticeId, --> this is the field I don't know how to get inserted.ReportOptionId INTO @PracticeReportOption (PracticeId, ReportOptionId) SELECT field1, field2 FROM @ReportOption
同
MERGE INTO ReportOption USING @ReportOption AS temp ON 1 = 0 WHEN NOT MATCHED THEN INSERT (field1, field2) VALUES (temp.Field1, temp.Field2) OUTPUT temp.PracticeId, inserted.ReportOptionId, inserted.Field1, inserted.Field2 INTO @PracticeReportOption (PracticeId, ReportOptionId, Field1, Field2);
关键是在合并语句中使用永远不会为真(1 = 0)的语句,因此您将始终执行插入操作,但可以访问源表和目标表中的字段。
这是我用来testing它的整个代码:
CREATE TABLE ReportOption (ReportOptionID INT IDENTITY(1, 1), Field1 INT, Field2 INT) CREATE TABLE Practice (PracticeID INT IDENTITY(1, 1), Field1 INT, Field2 INT) CREATE TABLE PracticeReportOption (PracticeReportOptionID INT IDENTITY(1, 1), PracticeID INT, ReportOptionID INT, Field1 INT, Field2 INT) INSERT INTO Practice VALUES (1, 1), (2, 2), (3, 3), (4, 4) MERGE INTO ReportOption r USING Practice p ON 1 = 0 WHEN NOT MATCHED THEN INSERT (field1, field2) VALUES (p.Field1, p.Field2) OUTPUT p.PracticeId, inserted.ReportOptionId, inserted.Field1, inserted.Field2 INTO PracticeReportOption (PracticeId, ReportOptionId, Field1, Field2); SELECT * FROM PracticeReportOption DROP TABLE ReportOption DROP TABLE Practice DROP TABLE PracticeReportOption
更多的阅读,以及我所知道的关于这个主题的来源是Here
也许有人使用MS SQL Server 2005或更低版本会发现这个答案有用。
MERGE只能用于SQL Server 2008或更高版本。 为了rest,我find了另一个解决方法,这将使您能够创build一种映射表。
下面是解决scheme对于SQL 2005来说的样子:
DECLARE @ReportOption TABLE (ReportOptionID INT IDENTITY(1, 1), Field1 INT, Field2 INT) DECLARE @Practice TABLE(PracticeID INT IDENTITY(1, 1), Field1 INT, Field2 INT) DECLARE @PracticeReportOption TABLE(PracticeReportOptionID INT IDENTITY(1, 1), PracticeID INT, ReportOptionID INT, Field1 INT, Field2 INT) INSERT INTO @Practice (Field1, Field2) VALUES (1, 1) INSERT INTO @Practice (Field1, Field2) VALUES (2, 2) INSERT INTO @Practice (Field1, Field2) VALUES (3, 3) INSERT INTO @Practice (Field1, Field2) VALUES (4, 4) INSERT INTO @ReportOption (field1, field2) OUTPUT INSERTED.ReportOptionID, INSERTED.Field1, INSERTED.Field2 INTO @PracticeReportOption (ReportOptionID, Field1, Field2) SELECT Field1, Field2 FROM @Practice ORDER BY PracticeID ASC; WITH CTE AS ( SELECT PracticeID, ROW_NUMBER() OVER ( ORDER BY PracticeID ASC ) AS ROW FROM @Practice ) UPDATE M SET M.PracticeID = S.PracticeID FROM @PracticeReportOption AS M JOIN CTE AS S ON S.ROW = M.PracticeReportOptionID SELECT * FROM @PracticeReportOption
主要的诀窍是我们用来自源和目的表的有序数据填充映射表两次。 有关更多详细信息,请参阅: 在SQL Server 2005中使用OUTPUT合并插入的数据