繁体   English   中英

使用光标将数据两次插入同一表

[英]Insert data twice into the same table using cursor

我有两个表cursor_createdcursor_copied具有相同的列。 我想使用cursor_created获取数据并将其插入cursor_copied两次。

查询:

DECLARE @ID INT
DECLARE @Name NVARCHAR(50)
DECLARE @Amount DECIMAL(18,0)
DECLARE @Date NVARCHAR(50)

DECLARE IDs CURSOR FOR 
    SELECT
        ID, Name, Amount, Date 
    FROM
        cursor_created 

OPEN IDs

FETCH NEXT FROM IDs into @ID, @Name, @Amount, @Date

WHILE @@FETCH_STATUS = 0
BEGIN
    INSERT INTO cursor_copied (id, name, amount, date)
    VALUES (@ID, @Name, @Amount, @Date)
    ----Verify that Data in TestTable
    --print @ID 
    --print @Name
    --print @Amount
    --print @Date

    --SELECT @ID, @Name, @Amount, @Date FROM cursor_copied 
    FETCH NEXT FROM IDs into @ID, @Name, @Amount, @Date
END

CLOSE IDs
DEALLOCATE IDs

输出:

ID  Name  Amount  Date
------------------------------------------
1   A     2000    2008-03-15 18:15:43.000
2   B     3000    2008-03-15 18:15:43.000
3   C     4000    2008-03-15 18:15:43.000

我想要这样:

ID  Name  Amount  Date
------------------------------------------
 1  A     2000    2008-03-15 18:15:43.000
 2  B     3000    2008-03-15 18:15:43.000
 3  C     4000    2008-03-15 18:15:43.000
 1  A     2000    2008-03-15 18:15:43.000
 2  B     3000    2008-03-15 18:15:43.000
 3  C     4000    2008-03-15 18:15:43.000

您应该after insert触发器after insert使用。

您可以在cursor_insertedon after insert触发器on after insert设置on after insert并控制该表上的插入事件,然后插入重复行。

CREATE TRIGGER DublicateInsert ON cursor_copied 
AFTER INSERT  
AS
BEGIN
INSERT INTO cursor_copied (id, name, amount, date)
    SELECT id, name, amount, date
    FROM  INSERTED 
END

或者您可以使用此语法解决问题

INSERT INTO cursor_copied (id, name, amount, date)
OUTPUT inserted.id, inserted.name,inserted.amount,inserted.date
INTO cursor_copied (id, name, amount, date)
 VALUES (@ID, @Name, @Amount, @Date)

为此使用游标是一个错误。 您应该在以下位置使用设置操作:

INSERT INTO cursor_copied (id, name, amount, date)
    SELECT ID, Name, Amount, Date 
    FROM cursor_created CROSS APPLY
         (VALUES (1), (2)) copies(n);

即使您正在学习游标,也非常重要的是学习适当的游标。 当代码可以被单个查询替换时,它们几乎是不合适的。

您只需在光标内按如下所示重写您的插入:

INSERT INTO cursor_copied (id, name, amount, date)
    VALUES (@ID, @Name, @Amount, @Date),
           (@ID, @Name, @Amount, @Date)

但是您选择的解决方案可能不是解决此类问题的好方法。 如果您对其他解决方案感兴趣,请阅读以下故事。

解决方案1

请参阅@GordonLinoff的答案

解决方案2

让我们逐步解决问题:

首先,我想有两个这样的表:

CREATE TABLE t1(Id INT, Name NVARCHAR(50), Amount DECIMAL(18,0), Date NVARCHAR(50))
GO
CREATE TABLE t1_copy(Id INT, Name NVARCHAR(50), Amount DECIMAL(18,0), Date NVARCHAR(50))

然后我想,我已经将以下记录插入到t1

INSERT INTO t1 VALUES
(1,'A', 2000,'2008-03-15 18:15:43.000'),
(2,'B', 3000,'2008-03-15 18:15:43.000'),
(3,'C', 4000,'2008-03-15 18:15:43.000')

接下来,我需要考虑一个查询,这可以帮助我生成重复的记录。 我有很多可用的选项,例如提到的@GordonLinoff的Cross Apply 另一种方法是按如下方式使用UNION ALL

SELECT t1.Id,
       t1.Name,
       t1.Amount,
       t1.Date FROM dbo.t1
UNION ALL
SELECT Id,
       Name,
       Amount,
       Date FROM dbo.t1;

此查询将产生所需的结果,而我在这里需要做的就是将它们简单地插入到目标表中,如下所示:

INSERT INTO dbo.t1_copy(Id,Name,Amount,Date)
SELECT t1.Id,
       t1.Name,
       t1.Amount,
       t1.Date FROM dbo.t1
UNION ALL
SELECT Id,
       Name,
       Amount,
       Date FROM dbo.t1;

很明显,在插入表之前,您可能需要注意Primary KeyIdentity列(如果存在)!

解决方案3

您可以使用GO 像这样:

   INSERT INTO dbo.t1_copy(Id,Name,Amount,Date)
   SELECT Id,Name,Amount,Date FROM dbo.t1
   GO 2

这不是我建议的方式,因为GO是批次分隔符,并且会给您带来麻烦。 同样,前面提到的查询将作为两个单独的事务执行,这又可能是一个麻烦点!

解决方案4

您可以使用OUTPUT运算符。 但是由于复杂性,我再次不建议这样做。 像这样:

   INSERT INTO dbo.t1_copy(Id,Name,Amount,Date)
   SELECT * FROM(
       INSERT INTO dbo.t1_copy(Id,Name,Amount,Date)
          OUTPUT Inserted.id, Inserted.Name, Inserted.Amount, Inserted.Date
       SELECT Id,Name,Amount,Date FROM dbo.t1) AS k

使用游标怎么办?

@GordonLinoff提到了在这种情况下使用Cursor的错误点,但是,如果您坚持使用Cursor,则需要在Fast_Forward模式下声明游标。 SCROLL模式下进行声明将无济于事,并且会降低查询的总体性能!

DECLARE IDs CURSOR FAST_FORWARD FOR ...

性能比较:

如果仅看一下上述解决方案的执行计划,就会发现解决方案1与其他解决方案相比具有更好的性能输出。 在我的PC中,执行计划输出如下:

Solution 1 ====================> Subtree Cost: 0.0133
Solution 2 ====================> Subtree Cost: 0.0165
Solution 3 ====================> Subtree Cost: 0.0132*2=0.0264
Solution 4 ====================> Subtree Cost: 0.0232
Cursor in SCROLL mode =========> Subtree Cost: 0.0332
Cursor in Fast_Forward mode ===> Subtree Cost: 0.0203

这些数字在您的PC中会有所不同!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM