我有两个表cursor_created
和cursor_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
答案 0 :(得分:0)
您只需在光标内按如下所示重写您的插入内容:
INSERT INTO cursor_copied (id, name, amount, date)
VALUES (@ID, @Name, @Amount, @Date),
(@ID, @Name, @Amount, @Date)
但是,您选择的解决方案可能不是解决此类问题的好方法。如果您对其他解决方案感兴趣,请阅读以下故事。
解决方案1
参考@GordonLinoff's答案
解决方案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 Key
或Identity
列(如果存在)!
解决方案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上会有所不同!