我有两张桌子。一个表A
有n行数据,另一个表B
为空。我希望将insert
n行放入表B
中,为表A
中的每一行添加1行。表B
中包含表A
中的几个字段,包括表A
中的外键。
最后,我想在B
中为A
中的每一行添加一行。为此,我使用了:
INSERT INTO B(Col1
,Col2
,Col3
,Col4
,Col5
);
SELECT 100
,25
,'ABC'
,1
,A.ID
FROM Auctions A
现在,我已将此代码放在存储过程中,此SP采用名为int
的{{1}}参数。
我想插入NumInserts
行。因此,如果n为10且NumInserts为5,我想运行此代码5 * 10(50)次。
换句话说,对于n * NumInserts
中的每一行,我想table A
中的insert
5行。我该怎么做?
答案 0 :(得分:14)
create procedure insert_into_b
@numInserts int
as
begin
while @numInserts > 0
begin
insert into b (id)
select id from a
set @numInserts = @numInserts - 1
end
end
exec insert_into_b 2
答案 1 :(得分:7)
我希望尽可能避免循环,这样我就不必在存储过程中维护一些容易破解且有些丑陋的循环结构。
您可以使用Numbers
表格,CROSS APPLY
语句和现有的INSERT
语句轻松完成此操作。
鉴于你的数字表看起来像这样:
Number
======
0
1
2
...
您的SQL语句变为:
INSERT INTO B
(
[Col1]
,[Col2]
,[Col3]
,[Col4]
,[Col5]
)
SELECT
100
,25
,'ABC'
,1
,a.ID
FROM
Auctions a
CROSS APPLY
Numbers n
WHERE
n.Number BETWEEN 1 AND @NumInserts
如果使用得当,数字表会很有用。如果你不熟悉它们,这里有一些资源和一些优点/缺点:
如果@NumInserts
总是一个相当小的数字,也许这个解决方案有点过分,但如果你已经有一张Numbers表,你可以利用它!
<强>更新强>:
这是一个快速而简单的方法,可以将数字表从0填充到65,535:
CREATE TABLE Numbers
(
Number INT NOT NULL,
CONSTRAINT PK_Numbers
PRIMARY KEY CLUSTERED (Number)
WITH FILLFACTOR = 100
)
GO
INSERT INTO Numbers
SELECT
(a.Number * 256) + b.Number AS Number
FROM
(
SELECT number
FROM master..spt_values
WHERE
type = 'P'
AND number <= 255
) a (Number),
(
SELECT number
FROM master..spt_values
WHERE
type = 'P'
AND number <= 255
) b (Number)
GO
答案 2 :(得分:5)
这是一个黑客,我不建议在生产或大量数据中使用它。但是,在开发快速和肮脏的场景中,我发现它通常很有用:
使用GO \[count\]
执行指定次数的一批命令。
具体而言,如果您有一个名为InsertAIntoB
的存储过程,则可以在Management Studio中运行它:
exec InsertAIntoB
GO 10
(用任何NumInserts替换10
)
答案 3 :(得分:1)
Create procedure DoitNTimes
@N integer = 1
As
Set NoCount On
While @N > 0 Begin
Insert B (Col1, Col2, Col3, Col4, Col5)
Select 100, 25, 'ABC', 1, A.ID
From Auctions A
-- -----------------------------------
Set @N -= 1
End
如果使用SQL Server 2005或更早版本替换Set @N -= 1' with
设置@N = @ N-1`
如果你真的想避免使用T-SQL变量循环,那么使用CTE,而不是基于磁盘的表:
Create procedure DoitNTimes
@N integer = 1
As
Set NoCount On
With nums(num) As
(Select @N Union All
Select num - 1
From nums
Where num > 1)
Insert B (Col1, Col2, Col3, Col4, Col5)
Select 100, 25, 'ABC', 1, A.ID
From Auctions A Full Join nums
Option(MaxRecursion 10000)
但当然,这仍然是循环,就像这个问题的任何解决方案一样。
答案 4 :(得分:0)
答案非常晚,但没有必要循环,这比Corey的好答案简单一点;
DECLARE @n int = 10;
INSERT INTO B(Col1,Col2,Col3,Col4,Col5);
SELECT 100,25,'ABC',1,A.ID
FROM Auctions A
JOIN (SELECT TOP(@n) 1 [junk] FROM sys.all_objects) as copies ON 1 = 1
只要具有您需要的行数,您就可以使用连接中的任何表。您还可以将“1 [垃圾]”更改为“ROW_NUMBER()OVER(ORDER BY object_id)[copyno]”如果您想在插入表格中的某处复制数字。
希望这会为某人节省一些工作......
答案 5 :(得分:0)
尝试一下:
DECLARE @NumInserts SMALLINT = 3
INSERT INTO B (Col1, Col2, Col3, Col4, Col5)
SELECT 100, 25, 'ABC', 1, A.ID
FROM Auctions A
JOIN master.dbo.spt_values numbers ON numbers.number < @NumInserts
WHERE numbers.[type] = 'P'
@NumInserts
小于或等于2048时有效master.dbo.spt_values WHERE type = 'P'
只是一个内置的SQL Server数字表,范围是0到2047