2009-06-24 32 views
13

Tôi muốn thêm một số biến của các bản ghi trong một bảng (ngày)Chèn số n của hồ sơ với T-SQL

Và tôi đã nhìn thấy một giải pháp gọn gàng cho việc này:

SET @nRecords=DATEDIFF(d,'2009-01-01',getdate()) 
SET ROWCOUNT @nRecords 
INSERT int(identity,0,1) INTO #temp FROM sysobjects a,sysobjects b 
SET ROWCOUNT 0 

Nhưng đáng buồn là không hoạt động trong UDF (vì #temp và SET ROWCOUNT). Bất kỳ ý tưởng làm thế nào điều này có thể đạt được?

Hiện tại tôi đang thực hiện nó với một biến WHILE và bảng, nhưng về mặt hiệu suất, nó không phải là một giải pháp tốt.

Trả lời

3

đây là cách tiếp cận tôi đang sử dụng và hoạt động tốt nhất cho mục đích của tôi và sử dụng SQL 2000. Bởi vì trong trường hợp của tôi là bên trong một UDF, tôi không thể sử dụng ## hoặC# bảng tạm thời để tôi sử dụng biến bảng. tôi đang làm:

DECLARE @tblRows TABLE (pos int identity(0,1), num int) 
DECLARE @numRows int,@i int 


SET @numRows = DATEDIFF(dd,@start,@end) + 1 
SET @i=1 

WHILE @i<@numRows 
begin 
    INSERT @tblRows SELECT TOP 1 1 FROM sysobjects a 

    SET @[email protected]+1 
end 
0

Bạn có thể làm những gì PinalDave gợi ý:

INSERT INTO MyTable (FirstCol, SecondCol) 
SELECT 'First' ,1 
UNION ALL 
SELECT 'Second' ,2 
UNION ALL 
SELECT 'Third' ,3 
UNION ALL 
SELECT 'Fourth' ,4 
UNION ALL 
SELECT 'Fifth' ,5 
GO 
+0

nhưng tôi cần thêm n hàng ... có thể là 2 có thể là 2.000! Điều đó có thể làm việc xây dựng một truy vấn động vẫn sử dụng vòng lặp while và sau đó thực hiện chèn ở cuối, nhưng nó sẽ không hoạt động trong một UDF anywyay. –

+2

Vui lòng không trích dẫn PinalDave ... – gbn

2

bạn có thể sử dụng một chéo tham gia

select top 100000 row_number() over(order by t1.number)-- here you can change 100000 to a number you want or a variable 
from master.dbo.spt_values t1 
     cross join master.dbo.spt_values t2 
11

Bạn có thể sử dụng một tuyên bố KHI cho rằng:

declare @i int 
declare @rows_to_insert int 
set @i = 0 
set @rows_to_insert = 1000 

while @i < @rows_to_insert 
    begin 
    INSERT INTO #temp VALUES (@i) 
    set @i = @i + 1 
    end 
+0

đây là phương pháp tôi đang sử dụng và hoạt động tốt nhất cho mục đích của mình và sử dụng SQL 2000. Vì trong trường hợp của tôi nằm trong UDF, tôi không thể sử dụng ## hoặC# bảng tạm thời vì vậy tôi sử dụng một biến bảng như được hiển thị trong câu trả lời của tôi –

16

Nếu bạn' tái sử dụng SQL 2005 hoặc mới hơn, bạn có thể sử dụng CTE đệ qui để có danh sách các ngày hoặc số ...

with MyCte AS 
    (select MyCounter = 0 
    UNION ALL 
    SELECT MyCounter + 1 
    FROM  MyCte 
    where MyCounter < DATEDIFF(d,'2009-01-01',getdate())) 
select MyCounter, DATEADD(d, MyCounter, '2009-01-01') 
from MyCte 
option (maxrecursion 0) 


/* output... 
MyCounter MyDate 
----------- ----------------------- 
0   2009-01-01 00:00:00.000 
1   2009-01-02 00:00:00.000 
2   2009-01-03 00:00:00.000 
3   2009-01-04 00:00:00.000 
4   2009-01-05 00:00:00.000 
5   2009-01-06 00:00:00.000 
.... 
170   2009-06-20 00:00:00.000 
171   2009-06-21 00:00:00.000 
172   2009-06-22 00:00:00.000 
173   2009-06-23 00:00:00.000 
174   2009-06-24 00:00:00.000 

(175 row(s) affected) 

*/ 
+3

Tôi nghĩ rằng phương pháp này nên được giới hạn trong các tập hợp kết quả tương đối nhỏ như 1.000 hoặc ít hơn. Các hoạt động đệ quy bắt đầu nhận được rõ ràng đắt tiền cho thậm chí 100.000 kết quả. Tuy nhiên, nó vẫn phải là thứ gọn gàng nhất ở đây. – SurroundedByFish

+0

Mặc dù hiệu suất tiêu cực của CTE đệ quy, nếu bạn đang sử dụng điều này để tạo hàng cho chèn, điều này sẽ cho phép bạn thực hiện chèn dựa trên bộ. Sử dụng ở trên cho một chèn dựa trên bộ sẽ có khả năng nhanh hơn rất nhiều so với chèn một bản ghi duy nhất tại một thời điểm trong một vòng lặp. – AaronLS

2

Khi bạn có một bảng số được xây dựng trước, chỉ cần sử dụng rằng:

SELECT * 
FROM numbers 
WHERE number <= DATEDIFF(d,'2009-01-01',getdate()) 

Có bất kỳ số lượng các kỹ thuật để xây dựng bảng số ở nơi đầu tiên (sử dụng kỹ thuật ở đây), nhưng một khi nó được xây dựng và lập chỉ mục, bạn không xây dựng lại nó.

+0

Hầu hết mọi người, đặc biệt là từ nền tảng coder, sẽ cười với ý tưởng có một bảng chỉ chứa đầy một triệu hoặc nhiều số thứ tự. Tuy nhiên, tôi nghĩ đây thực sự là giải pháp tốt nhất ở đây. Đó là để nói, đó là giải pháp phá vỡ ý định của các hoạt động dựa trên thiết lập ít nhất và không phải là một hack. Các nhà lập trình nghĩ trong việc lặp lại và đệ quy, nhưng họ gặp khó khăn trong việc hiểu các hoạt động dựa trên thiết lập. Bảng "số" sẽ chiếm một không gian tương đối nhỏ, không gian và trả về kết quả cực nhanh ngay cả đối với các tập kết quả lớn. Nhưng hey, nó không phải là sexy. – SurroundedByFish

+0

Cho dù bạn xây dựng nó trên bay và tuy nhiên bạn xây dựng nó, nó vẫn là một bảng số (ngay cả khi nó được ngụy trang như một loạt các ngày). –

0

Làm thế nào về:

DECLARE @nRecords INT 

SET @nRecords=DATEDIFF(d,'2009-01-01',getdate()) 

SELECT TOP (@nRecords) 
    ROW_NUMBER() OVER (ORDER BY a.object_id, b.object_id) - 1 
FROM sys.objects a, sys.objects b 

Nếu bạn không muốn nó zero-lập chỉ mục, loại bỏ các "- 1"

Yêu cầu ít nhất SQL Server 2005.

+0

xin lỗi, quên đề cập đến tôi đang ở trên SQL 2000 –

+0

Trong trường hợp đó, bạn * bị hạn chế * trong những gì bạn có thể làm và gần như không có giải pháp nào được đề xuất ở đây sẽ hoạt động. Cade Roux có lẽ là cược tốt nhất của bạn. – GalacticCowboy

3

Nhìn chung nhanh hơn nhiều để tăng gấp đôi số lượng hàng tại mỗi lần lặp

CREATE TABLE dbo.Numbers(n INT NOT NULL PRIMARY KEY) 
GO 
DECLARE @i INT; 
SET @i = 1; 
INSERT INTO dbo.Numbers(n) SELECT 1; 
WHILE @i<128000 BEGIN 
    INSERT INTO dbo.Numbers(n) 
    SELECT n + @i FROM dbo.Numbers; 
    SET @i = @i * 2; 
END; 

Tôi cố tình không SET NOCOUNT ON, vì vậy mà bạn nhìn thấy nó như thế nào chèn 1,2 , 4,8 hàng

Các vấn đề liên quan