使用光标插入 2 tables,然后使用返回的 scope_identity 插入另一个 table
Insert into 2 tables with cursor, then use returned scope_identity to insert into another table
基本上我想使用现有的 table,我们称它为 T1
。我必须逐行获取 table,并将不同的列插入到 2 个单独的 table 中。例如,C1
、C2
变成 T2
和 C3
、C4
变成 T3
。
在这两个插入过程中,我需要确保我插入的值不存在。不幸的是有多个重复项。这不是我的数据,而且很脏。我必须按原样进行大量铸造。
我想插入 T2
或 T3
的列可能存在而另一个不存在,但不是 100%。
完成这些插入后,我需要一个 @SCOPE_Identity
或其他方法来唯一标识并在两个声明的值中保存 T2
和 T3
创建的自动递增 ID。
然后需要将这些插入到 T4
中,这是一个查找 table,主要只存储 FK、它自己的 ID、注释和 BIT。
我知道这是一项艰巨的任务,但我真的需要一些帮助。
我已经修改了多个游标和循环,但还没有到那里。
如果我想出了一些办法,我会 post 一个解决方案,如果在我之前没有人想出的话。
编辑:
所以我解决了。我已经 post 编辑了我的代码,使其易于阅读和用作答案。如果有人想查看它、发表评论、进行编辑等,它就会在那里。可能有更好的方法,如果可以的话请评论。
我不熟悉你的table结构和数据量,但我会采取其他方法来解决这个问题。
- 创建一个缓冲区table,用于存放需要插入table
T1
和T2
的数据
- 使用此缓冲区 table 填充所有 tables
T1
、T2
、T3
我会尝试这样做,因为在大多数情况下使用游标很慢 - 您需要尝试批量操作数据(行组)。
如何做到这一点?
- 首先可以在
T1
和T2
中找到最大身份ID
然后,创建一个 table 将具有以下列:
- T1_ID
- T2_ID
- C1
- C2
- C3
- C4
- ShouldBeInsertedInT1
- ShouldBeInsertedInT2
现在,您必须使用来自 T1
的数据填充 table 并生成 T1_ID
和 T2_ID
字段。这是简单的ROW_NUMBER
函数+
最大身份ID为tableT1
和T2
.
- 数据进入缓冲区table后,您必须执行两次单独的更新才能升起
ShouldBeInsertedInT
标志。您必须检查缓冲区 table 中的哪些列应该插入到 T1
和 T2
table 中。这可以通过连接、存在等来完成——这基本上取决于您的数据和业务逻辑。
如果你在这里,你只需要执行插入。例如:
SET IDENTITY_INSERT dbo.T1 ON
INSERT INTO T1
SELECT T1_ID, C1, C2
FROM bufffer
WHERE ShouldBeInsertedInT1 = 1;
SET IDENTITY_INSERT dbo.T1 OFF
SET IDENTITY_INSERT dbo.T2 ON
INSERT INTO T2
SELECT T2_ID, C3, C4
FROM bufffer
WHERE ShouldBeInsertedInT2 = 1;
SET IDENTITY_INSERT dbo.T2 OFF
INSERT INTO T3
SELECT T1_ID, T2_ID
FROM bufffer;
这只是一个概念,因此您必须更改此代码。请注意,整个过程可能需要在事务中进行,以确保 T1
和 T2
的最大身份 ID 未更改。
这是我最终用于插入的用户安全版本(我就这么称呼它)。这实际上是为导入数据集而设计的,在我看来,如果没有行级插入,这些数据集会有些困难。当我 运行 插入 50, 000 行大约需要 2 分钟。请记住,我有超过 4 列,有些列很大,我必须至少投射一次(有些比其他多),我必须使用 LEFT 或 RIGHT 进行各种切割以清理数据新表。
Declare @Col1 varchar(50);
DECLARE @Col2 varchar (50);
DECLARE @col3 varchar (50);
DECLARE @col4 varchar (50);
DECLARE @T2ID int;
DECLARE @T3ID int;
DECLARE Cur1 CURSOR -- Create the cursor
LOCAL FAST_FORWARD
-- set the type of cursor. Note you could also use READ_ONLY and FORWARD_ONLY.
-- You would have to performance test to see if you benifit from one or the other
FOR
--select FROM base table Table1
SELECT
Col1, Col2, Col3, Col4
FROM
Table1
WHERE Col1 IS NOT NULL AND Col3 IS NOT NULL
-- If the main columns are null then they are skipped. This was
-- required for my data but not necessarily yours.
OPEN Cur1
FETCH NEXT FROM Cur1 INTO
@Col1, @Col2, @Col3, @Col4;
-- Assigns values to variables declared at the top
WHILE @@FETCH_STATUS = 0
BEGIN
-- Select from table 2
SELECT @T2ID = T2ID
-- where some data in the table is = to the stored data we are searching for
FROM Table2
WHERE @Col1 = [Col1]
IF @@rowcount = 0
BEGIN
INSERT INTO T2
(Col1
,Col2)
VALUES
(@Col1
,@Col2)
SET @T2ID = SCOPE_IDENTITY();
END;
-- Selects from Table3
SELECT @Col3 = Table3Col1
FROM Table3
IF @@rowcount = 0
-- If no rows are returned then proceed with insert
BEGIN
INSERT INTO Table3
(col3
,col4)
VALUES
-- Uses values assigned to the variables from the cursor select
(@col3
,@col4)
SET @T3ID = SCOPE_IDENTITY();
END;
-- Inserts the gathered row id's into the lookup table
INSERT INTO Table4
(Table2ID
,Table3ID)
VALUES (
@Table2ID
,@Table3ID)
FETCH NEXT FROM Cur1 INTO @Col1, @Col2, @col3, @col4;
END;
CLOSE Cur1;
DEALLOCATE Cur1;
如果有人要提供改进,请提供。我愿意接受建议。
另外,除非有人要我这样做,否则我不会接受我的答案是正确的,因为可能会有更好的答案。
基本上我想使用现有的 table,我们称它为 T1
。我必须逐行获取 table,并将不同的列插入到 2 个单独的 table 中。例如,C1
、C2
变成 T2
和 C3
、C4
变成 T3
。
在这两个插入过程中,我需要确保我插入的值不存在。不幸的是有多个重复项。这不是我的数据,而且很脏。我必须按原样进行大量铸造。
我想插入 T2
或 T3
的列可能存在而另一个不存在,但不是 100%。
完成这些插入后,我需要一个 @SCOPE_Identity
或其他方法来唯一标识并在两个声明的值中保存 T2
和 T3
创建的自动递增 ID。
然后需要将这些插入到 T4
中,这是一个查找 table,主要只存储 FK、它自己的 ID、注释和 BIT。
我知道这是一项艰巨的任务,但我真的需要一些帮助。 我已经修改了多个游标和循环,但还没有到那里。 如果我想出了一些办法,我会 post 一个解决方案,如果在我之前没有人想出的话。
编辑: 所以我解决了。我已经 post 编辑了我的代码,使其易于阅读和用作答案。如果有人想查看它、发表评论、进行编辑等,它就会在那里。可能有更好的方法,如果可以的话请评论。
我不熟悉你的table结构和数据量,但我会采取其他方法来解决这个问题。
- 创建一个缓冲区table,用于存放需要插入table
T1
和T2
的数据
- 使用此缓冲区 table 填充所有 tables
T1
、T2
、T3
我会尝试这样做,因为在大多数情况下使用游标很慢 - 您需要尝试批量操作数据(行组)。
如何做到这一点?
- 首先可以在
T1
和T2
中找到最大身份ID
然后,创建一个 table 将具有以下列:
- T1_ID
- T2_ID
- C1
- C2
- C3
- C4
- ShouldBeInsertedInT1
- ShouldBeInsertedInT2
现在,您必须使用来自
T1
的数据填充 table 并生成T1_ID
和T2_ID
字段。这是简单的ROW_NUMBER
函数+
最大身份ID为tableT1
和T2
.- 数据进入缓冲区table后,您必须执行两次单独的更新才能升起
ShouldBeInsertedInT
标志。您必须检查缓冲区 table 中的哪些列应该插入到T1
和T2
table 中。这可以通过连接、存在等来完成——这基本上取决于您的数据和业务逻辑。 如果你在这里,你只需要执行插入。例如:
SET IDENTITY_INSERT dbo.T1 ON INSERT INTO T1 SELECT T1_ID, C1, C2 FROM bufffer WHERE ShouldBeInsertedInT1 = 1; SET IDENTITY_INSERT dbo.T1 OFF SET IDENTITY_INSERT dbo.T2 ON INSERT INTO T2 SELECT T2_ID, C3, C4 FROM bufffer WHERE ShouldBeInsertedInT2 = 1; SET IDENTITY_INSERT dbo.T2 OFF INSERT INTO T3 SELECT T1_ID, T2_ID FROM bufffer;
这只是一个概念,因此您必须更改此代码。请注意,整个过程可能需要在事务中进行,以确保 T1
和 T2
的最大身份 ID 未更改。
这是我最终用于插入的用户安全版本(我就这么称呼它)。这实际上是为导入数据集而设计的,在我看来,如果没有行级插入,这些数据集会有些困难。当我 运行 插入 50, 000 行大约需要 2 分钟。请记住,我有超过 4 列,有些列很大,我必须至少投射一次(有些比其他多),我必须使用 LEFT 或 RIGHT 进行各种切割以清理数据新表。
Declare @Col1 varchar(50);
DECLARE @Col2 varchar (50);
DECLARE @col3 varchar (50);
DECLARE @col4 varchar (50);
DECLARE @T2ID int;
DECLARE @T3ID int;
DECLARE Cur1 CURSOR -- Create the cursor
LOCAL FAST_FORWARD
-- set the type of cursor. Note you could also use READ_ONLY and FORWARD_ONLY.
-- You would have to performance test to see if you benifit from one or the other
FOR
--select FROM base table Table1
SELECT
Col1, Col2, Col3, Col4
FROM
Table1
WHERE Col1 IS NOT NULL AND Col3 IS NOT NULL
-- If the main columns are null then they are skipped. This was
-- required for my data but not necessarily yours.
OPEN Cur1
FETCH NEXT FROM Cur1 INTO
@Col1, @Col2, @Col3, @Col4;
-- Assigns values to variables declared at the top
WHILE @@FETCH_STATUS = 0
BEGIN
-- Select from table 2
SELECT @T2ID = T2ID
-- where some data in the table is = to the stored data we are searching for
FROM Table2
WHERE @Col1 = [Col1]
IF @@rowcount = 0
BEGIN
INSERT INTO T2
(Col1
,Col2)
VALUES
(@Col1
,@Col2)
SET @T2ID = SCOPE_IDENTITY();
END;
-- Selects from Table3
SELECT @Col3 = Table3Col1
FROM Table3
IF @@rowcount = 0
-- If no rows are returned then proceed with insert
BEGIN
INSERT INTO Table3
(col3
,col4)
VALUES
-- Uses values assigned to the variables from the cursor select
(@col3
,@col4)
SET @T3ID = SCOPE_IDENTITY();
END;
-- Inserts the gathered row id's into the lookup table
INSERT INTO Table4
(Table2ID
,Table3ID)
VALUES (
@Table2ID
,@Table3ID)
FETCH NEXT FROM Cur1 INTO @Col1, @Col2, @col3, @col4;
END;
CLOSE Cur1;
DEALLOCATE Cur1;
如果有人要提供改进,请提供。我愿意接受建议。 另外,除非有人要我这样做,否则我不会接受我的答案是正确的,因为可能会有更好的答案。