插入多行,获取ID,并对这些ID执行操作

问题描述

我有一个问题是否可以在sql中完成

我有两个表: 表1:

+----+---------+------------+-----------+
| Id | OrderId | CategoryId | OrderType |
+----+---------+------------+-----------+
|  1 |      10 |         15 | Type1     |
|  2 |      10 |         15 | Type2     |
|  3 |       9 |         17 | Type1     |
|  4 |      99 |         17 | Type2     |
|  5 |      20 |         25 | Type1     |
|  6 |      20 |         25 | Type2     |
+----+---------+------------+-----------+

这是Orders表(其ID在表1中的OrderId下引用)

+----+-----------+-----------+
| Id | SomeProp1 | SomeProp2 |
+----+-----------+-----------+
|  9 | test1     | test2     |
| 99 | test1     | test2     |
| 10 | test3     | test4     |
| 20 | test5     | test6     |
+----+-----------+-----------+

现在,对于表1中OrderId-CategoryId的每个重复组合,我想

  • 在具有新ID的订单中创建订单条目的副本
  • 获取给定重复项的条目,其中Table1中的OrderType = Type2
  • 使用“订单”表中新创建的条目更新其ID

所以最终这些表将更新如下:

表1:

+----+---------+------------+-----------+
| Id | OrderId | CategoryId | OrderType |
+----+---------+------------+-----------+
|  1 |      10 |         15 | Type1     |
|  2 |      11 |         15 | Type2     |
|  3 |       9 |         17 | Type1     |
|  4 |      99 |         17 | Type2     |
|  5 |      20 |         25 | Type1     |
|  6 |      21 |         25 | Type2     |
+----+---------+------------+-----------+

订单:

+----+-----------+-----------+
| Id | SomeProp1 | SomeProp2 |
+----+-----------+-----------+
|  9 | test1     | test2     |
| 99 | test1     | test2     |
| 10 | test3     | test4     |
| 11 | test3     | test4     |
| 20 | test5     | test6     |
| 21 | test5     | test6     |

所以我知道如何在Orders表中创建一行的副本并获取其ID:

insert into Orders
(SomeProp1,SomeProp2)
SELECT 
SomeProp1,SomeProp2
from Orders

SELECT ScopE_IDENTITY()

我知道如何在表1中找到重复的ID。

select OrderId from Table1
    GROUP BY OrderId,CategoryId
    HAVING COUNT(OrderId) > 1

我不知道的事情是如何对找到的所有重复项运行此命令。我的意思是创建某种foreach循环,然后在此foreach循环中,将新行插入Orders表中,获取其ID,然后使用此ID更新Table1的OrderId值。最让我困惑的是,如果可以执行这样的多行插入,并且每次插入时仍能够检索ID。

我想知道对于单个查询来说这是否太多,或者我以错误的方式进行处理(也许可以按顺序进行更多操作?)

谢谢!

解决方法

这是基于以下反馈的更新版本。

原始版本仅将OrderIds加1,但是它们位于IDENTITY字段中并自动创建。 DB_fiddle

中的原始代码/等

由于订单的标识字段,现在的逻辑如下

  • 识别上述重复项
  • 为此创建适当数量的订单,并记录OrderIDs
  • 更新表T1中的相关OrderID(原始行的OrderType ='Type 2')
  • 使用相关的SomeProp1和SomeProp2更新“订单”表

请注意,可以删除一个步骤(而不是插入新订单,然后更新它们),但是我要非常小心,您可以将新订单与相关的旧订单进行匹配。

交易在其中以帮助隔离更改;但是如果同时运行几次该过程,则需要小心。

这是一个带有以下代码的DB_Fiddle

/*    DATA SETUP    */

CREATE TABLE #T1 (Id int,OrderID int,CategoryId int,OrderType nvarchar(50))
INSERT INTO #T1 (Id,OrderID,CategoryId,OrderType) VALUES
(1,10,15,N'Type1'),(2,N'Type2'),(3,9,17,(4,99,(5,20,25,(6,N'Type2')

CREATE TABLE #Orders (Id int NOT NULL IDENTITY(1,1),SomeProp1 nvarchar(50),SomeProp2 nvarchar(50))

SET IDENTITY_INSERT #Orders ON;
INSERT INTO #Orders (Id,SomeProp1,SomeProp2) VALUES
( 9,N'test1',N'test2'),(99,(10,N'test3',N'test4'),(20,N'test5',N'test6')
SET IDENTITY_INSERT #Orders OFF;


/*    WORKING TABLES    */

CREATE TABLE #OrderChanges (OCId_temp int IDENTITY(1,OrderId_new int)

CREATE TABLE #Dupes (DupesId_temp int IDENTITY(1,CategoryId int)


/*    PROCESSING    */

BEGIN TRY
    BEGIN TRANSACTION

    INSERT INTO #Dupes (OrderID,CategoryID)
        SELECT  OrderID,CategoryID 
        FROM    #T1 
        GROUP BY OrderID,CategoryID 
        HAVING  COUNT(*) > 1

    IF EXISTS(SELECT * FROM #Dupes)
        BEGIN

        -- Create appropriate number of new orders,to get IDs (blank for the moment)
        INSERT INTO #Orders (SomeProp1,SomeProp2)
            OUTPUT  inserted.Id
            INTO    #OrderChanges (OrderID_new)
            SELECT  NULL,NULL
            FROM    #Dupes

        -- Should now have same number of rows,with matching IDENTITY Ids,in #Dupes and #OrderChanges

        -- Update #T1
        UPDATE      T1
            SET     OrderId = OC.OrderID_new
            FROM    #T1 AS T1
                    INNER JOIN #Dupes AS Dupes ON T1.OrderID = Dupes.OrderID AND T1.CategoryId = Dupes.CategoryId
                    INNER JOIN #OrderChanges AS OC ON Dupes.DupesId_temp = OC.OCId_temp
            WHERE   T1.OrderType = N'Type2'

        -- Update Orders
        UPDATE      Orders
            SET     SomeProp1 = PrevOrders.SomeProp1,SomeProp2 = PrevOrders.SomeProp2
            FROM    #Orders AS Orders
                    INNER JOIN #OrderChanges AS OC ON Orders.Id = OC.OrderId_new
                    INNER JOIN #Dupes AS Dupes ON OC.OCId_temp = Dupes.DupesId_temp
                    INNER JOIN #Orders AS PrevOrders ON Dupes.OrderID = PrevOrders.Id
    
        END
    
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
    THROW;
END CATCH


/*    REPORTING AND WRAPUP     */

SELECT * FROM #T1 ORDER BY Id
SELECT * FROM #Orders ORDER BY Id

DROP TABLE #OrderChanges
DROP TABLE #Orders
DROP TABLE #T1
DROP TABLE #Dupes