SQL Server INSERT INTO SELECT FROM语句上的更新ID

xe55xuns  于 2022-12-22  发布在  其他
关注(0)|答案(1)|浏览(253)

我想将表[From]中的特定列复制到表[To]中,但还想在[From]中插入[To]中的外键
表格定义:

[From]
Id    (int)
pic   (varbinary(MAX))
picId (int)

[To]
Id (int)
pic (varbinary(MAX))

我的复制查询工作正常,但我不知道如何更新Table [From]中的“picId”列

INSERT INTO dbo.[To] (Id,pic)
SELECT 
    isnull(T.m, 0) + row_number() over (order by F.pic),
    F.pic
FROM dbo.[From] AS F
    outer apply (select max(pic) as m from dbo.[To]) as T;

现在我想将插入的[To].Id复制到[From]. picId。
有人能帮帮我吗?

u2nhd7ah

u2nhd7ah1#

2个更改将使您的解决方案变得更加简单,但是假设您无法控制dbo.[TO]表的任何内容,下面是一个适合您的解决方案。
第一个改进是将dbo.[to].ID设置为标识列。然后,您可以删除整个“row_number()over”行,让SQL管理ID。您所做的工作是有效的,但这就像用链锯在木头上来回拖动(不运行)锯子来切割木头。您可以做到这一点,但如果您启动引擎并让它来完成工作,则会容易得多。
第二个更改是添加列dbo.[to].FromID,并在插入行时填充该列。OUTPUT语句只能引用要插入的行中的字段(或已删除,但这与此处无关),因此无法获取dbo.[from]中要更新的行的ID,除非它位于dbo.[to]中刚插入的行中。如果这样做,你可以使用一个带OUTPUT子句的普通INSERT语句。这里的技巧是使用MERGE语句,你可以在这里看到完整的解释:如果你觉得这个答案有用,我强烈建议你投赞成票。如果没有这个答案,我不可能为你提供这个答案!
不管怎样,解决办法是这样的:

--Create some fake data, you'll already have dbo.[From]
CREATE TABLE #TestFrom (FromID INT, Pic nvarchar(1000), ToID INT NULL)
CREATE TABLE #TestTo (ToID INT, Pic nvarchar(1000))

--It would be much easier if your TO used an IDENTITY column instead of managing the ID manually
CREATE TABLE #TestToIdent (ToID INT IDENTITY(1,1), Pic nvarchar(1000))

INSERT INTO #TestFrom 
VALUES (1, 'Test 1', NULL)
        , (3, 'Test 3', NULL)
        , (7, 'Test 7', NULL)
        , (13, 'Test 13', NULL)

--Define a table variable to hold your OUTPUT, you'll need this
DECLARE @Mapping as table (FromID INT, ToID INT);

with cteIns as (
    SELECT 
        isnull(T.m, 0) + row_number() over (order by F.pic) as ToID
        , F.pic, F.FromID 
    FROM #TestFrom  AS F
        outer apply (select max(ToID) as m from #TestTo ) as T
) --From https://stackoverflow.com/questions/10949730/is-it-possible-to-for-sql-output-clause-to-return-a-column-not-being-inserted 
MERGE INTO #TestTo as T --Put results here
    USING cteIns as F --Source is here
        on 0=1 --But this is never true so never merge, just INSERT
WHEN NOT MATCHED THEN --ALWAYS because 0 never = 1
    INSERT (ToID, pic)
    VALUES (F.ToID, F.pic)
    OUTPUT F.FromID, inserted.ToID
    INTO @Mapping (FromID, ToID );
    
--SELECT * FROM @Mapping --Test the mapping if you're curious
--SELECT * FROM #TestTo --Test the insedert if you're curious

--Update the dbo.[FROM] with the ID of the [TO] that got inserted
UPDATE #TestFrom SET ToID = M.ToID 
FROM #TestFrom as F 
    INNER JOIN @Mapping as M 
        ON M.FromID = F.FromID 

--View the results
SELECT * FROM #TestFrom

DROP TABLE #TestFrom
DROP TABLE #TestTo 
DROP TABLE #TestToIdent

相关问题