2016-11-25 46 views
3

我有一个表中包含一个数字,在列中定义了一个属性有多少车库。现在,我需要为所有车库(规模,停车位数量,租赁费用等)添加更多信息,因此我必须通过插入尽可能多的记录来创建不同表格中每个车库的记录。MSSQL插入n次,其中n来自一个选择

我想什么来完成:

SELECT ID,GarageCount FROM属性

- 运行下面的语句GarageCount次

INSERT INTO车库(物业ID)VALUES(Property.ID )

我需要将其运行到属性表中的所有属性,其中GarageCount> 0

Properties.ID是一个PK,Garages.PropertyID是一个FK。

+0

所以,如果您的查询返回'1 ,4',你想四次插入'1'? – HoneyBadger

+0

这就是我正在寻找的。 – Daniel

回答

3

你不需要这个以“循环”的方式运行。你可以只使用一个公用表表达式生成行,与尽可能多的行每财产有在产权车库:

with GarageRows as (
select id 
    , garagecount 
    , 0 [counter] 
from Properties 
union all 
select p.id 
    , 1 
    , gr.counter + 1 
from GarageRows gr 
    inner join Properties p on gr.id = p.id 
where gr.counter + 1 < p.garagecount) 
insert into Garages(PropertyID) 
select gr.ID 
from GarageRows gr 
where gr.garagecount > 0 

如果你只是想测试上面的CTE的结果,你可以运行下面的查询,该查询生成两个属性的行,一个包含2个车库,另一个包含4个车库。

declare @properties table (id int, garagecount int) 
insert @properties values (1, 2), (2, 4) 

;with GarageRows as (
select id 
    , garagecount 
    , 0 [counter] 
from @Properties 
union all 
select p.id 
    , 1 
    , gr.counter + 1 
from GarageRows gr 
    inner join @Properties p on gr.id = p.id 
where gr.counter + 1 < p.garagecount) 
select gr.ID 
from GarageRows gr 
where gr.garagecount > 0 
order by gr.ID 
+0

使用数字表重复一行非常容易 –

+0

@PanagiotisKanavos没错,但是如果他没有数字表,那么这将为他做。 –

+0

生成一个数字表是微不足道的,并且避免了复杂的CTE –

1

您可以通过使用Numbers表避免循环和复杂的查询。数字是一个简单的表格,包含0以上的数字。

INSERT INTO Garages (PropertyID) 
Select Property.ID 
From Property inner join Numbers on Numbers.Number<Property.GarageCount 
where garagecount>0 

这将重复在同一行多次定义GarageCount:如果你有一个数字表连接

您的查询变得微不足道。

Numbers表格可以用于很多场景,包括日期计算,字符串分割,识别范围中的间隙以及将循环转换为无限快速的设置操作。 Aaron Bertrand写了很多文章that explain how to generate and how to use Numbers table

阿龙贝特朗的文章显示了一个快速的方法来生成一个索引和压缩(它可即使在Express版本的SQL Server 2016 SP1)Numbers表格:

DECLARE @UpperBound INT = 1000000; 

;WITH cteN(Number) AS 
(
    SELECT ROW_NUMBER() OVER (ORDER BY s1.[object_id]) - 1 
    FROM sys.all_columns AS s1 
    CROSS JOIN sys.all_columns AS s2 
) 
SELECT [Number] INTO dbo.Numbers 
FROM cteN WHERE [Number] <= @UpperBound; 

CREATE UNIQUE CLUSTERED INDEX CIX_Number ON dbo.Numbers([Number]) 
WITH 
(
    FILLFACTOR = 100,  
    DATA_COMPRESSION = ROW -- if the table is large enough to matter 
); 
+0

谢谢。这个也很好。 – Daniel