SQL Server:将原始表中的标志设置为复制数据后处理



我有一个大表,我想从该表中获取数据,并将其插入到其他(较小的)表中。但是在执行此操作时,我想将大表中的一列("已处理")标记为 true,以便下次运行查询时,它最终不会创建重复项。除了事后创建小查询以将所有内容设置为 0 到 1 之外,是否有更简单的方法可以做到这一点? 或者这是最有效的方法?

DECLARE @largeTable TABLE(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    productName varchar(100),
    productId int,
    quantity int,
    someVar int,
    Processed bit)
INSERT INTO @largeTable (productName, productId, quantity, someVar, Processed)
VALUES ('Apple', 1, 50, 34, 0),
        ('Orange', 2, 50, 53, 0),
        ('Banana', 3, 50, 165, 0),
        ('Pineapple', 4, 74, 34, 0),
    ('Mango', 5, 50, 388, 0),
        ('Kiwi', 6, 50, 2, 0),
        ('Strawberry', 7, 50, 16, 0)
SELECT * FROM @largeTable
DECLARE @smallTable TABLE(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    productName varchar(100),
    productId int)
INSERT INTO @smallTable (productName, productId)
SELECT productName, productId
FROM @largeTable
WHERE Processed = 0
UPDATE @largeTable
Set Processed = 1
WHERE Processed = 0
SELECT * FROM @largeTable
SELECT * FROM @smallTable

您可以使用合并语句,在这里基于产品 ID,您可以发现如果任何行已经存在,如果是,则更新它或插入:

MERGE smalltable AS target
USING (SELECT productName, productId from largetable) AS source (productName, productId)
ON (target.productId = source.productId)
WHEN MATCHED THEN 
    UPDATE SET productName = source.productName
WHEN NOT MATCHED THEN   
    INSERT (productId, productName)
    VALUES (source.productId, source.productName)

此外,若要获取插入的产品 ID,以便可以更新"已处理"列,可以执行以下操作:

  Update largetable
  set Processed=1
  from largetable join Inserted on largetable.Productid=Inserted.ProductId

这里,插入是SQL在插入/更新操作后创建的逻辑表

这个想法是获取未处理的记录 (Delta) 并将其主键值插入表变量中,然后使用此信息来管理从大表到小表的传输数据,并更新大表传输的记录(更新标志)。

BEGIN TRY
BEGIN TRANSACTION 
DECLARE @ProccessTable TABLE (IsProcessed SMALLINT)
DECLARE @LargeTable TABLE ( 
                   field1 INT IDENTITY(1,1) NOT NULL, 
                   field2 NVARCHAR(50) NULL, 
                   field3 NVARCHAR(50) NULL, 
                   field4 NVARCHAR(50) NULL, 
                   IsProcessed SMALLINT NOT NULL  
                   )
INSERT INTO @LargeTable 
VALUES ('ABC', 'DEF', 'GHI',0), ('JKL','MNO','PQR',0), ('STU','VXY','ZAB',0)
SELECT * FROM @LargeTable WHERE IsProcessed = 0
DECLARE @SmallTable TABLE ( 
                   field1 INT NOT NULL, 
                   field2 NVARCHAR(50) NULL, 
                   field3 NVARCHAR(50) NULL
                   )
INSERT INTO @ProccessTable
SELECT field1 FROM  @LargeTable WHERE IsProcessed = 0 
INSERT INTO @SmallTable
SELECT field1, field2, field3 FROM @LargeTable WHERE field1 IN (SELECT 
field1 FROM @ProccessTable)
UPDATE @LargeTable SET IsProcessed = 1 WHERE field1 IN (SELECT field1 FROM @ProccessTable)
SELECT * FROM @LargeTable WHERE IsProcessed = 0
SELECT * FROM @SmallTable
COMMIT TRANSACTION 
END TRY
BEGIN CATCH 
ROLLBACK 
END CATCH