USE Model GO CREATE TABLE Numbers ( Number INT NOT NULL,CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number) WITH FILLFACTOR = 100 ) 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
Numbers tables are truly invaluable. I use them all of the time for string manipulation,simulating window functions,populating test tables with lots of data,eliminating cursor logic,and many other tasks that would be incredibly difficult without them.
但我完全不明白这些用途是什么 – 你能提供一些引人注目的具体例子,说明“数字表”在sql Server中为你节省了大量工作 – 以及为什么我们应该拥有它们?
解决方法
我见过的其他例子使用了类似的时间序列技巧(日期/时间/ – 数字)来进行各种窗口计算.通常,每当使用命令式语言时,您将使用具有众所周知的迭代次数的for循环,sql的声明性和集合性可以使用基于数字表的技巧.
顺便说一句,我觉得有必要提出一个事实,即使用数字表感觉就像命令式程序执行一样,不要陷入假设必要的谬误.让我举个例子:
int x; for (int i=0;i<1000000;++i) x = i; printf("%d",x);
这个程序将输出999999,这是非常有保证的.
让我们使用数字表在sql中尝试相同的操作.首先创建一个包含1M个数字的表:
create table numbers (number int not null primary key); go declare @i int = 0,@j int = 0; set nocount on; begin transaction while @i < 1000 begin set @j = 0; while @j < 1000 begin insert into numbers (number) values (@j*1000+@i); set @j += 1; end commit; raiserror (N'Inserted %d*1000',@i) begin transaction; set @i += 1; end commit go
现在让我们做’for循环’:
declare @x int; select @x = number from numbers with(nolock); select @x as [@x];
结果是:
@x ----------- 88698
如果你现在有一个WTF时刻(在所有数字都是聚集的主键之后!),诀窍被称为allocation order scan并且我没有偶然插入@ j * 1000 @i …你也可以冒险猜测说结果是因为parallelism而且有时可能是正确的答案.
有很多trolls under this bridge,我在On SQL Server boolean operator short-circuit和T-SQL functions do no imply a certain order of execution提到了一些