何时初始化默认值?

时间:2014-06-22 15:06:15

标签: sql-server sql

create table tab3(a integer,d1 datetime default getdate())
insert into tab3(a) values(1)
insert into tab3 (a) select a from tab3
GO 20
insert into tab3 (a) select a from tab3

select d1,count(*) from tab3(NOLOCK) group by d1

最后一次插入肯定需要很长的时间(在我的机器上3秒)

但是,d1中的值每批次不同。即最终查询仅返回22行

2014-06-22 20:34:53.787 1
2014-06-22 20:34:56.127 1
2014-06-22 20:34:56.140 2
2014-06-22 20:34:56.153 4
2014-06-22 20:34:56.157 8
2014-06-22 20:34:56.160 16
2014-06-22 20:34:56.163 32
2014-06-22 20:34:56.167 64
2014-06-22 20:34:56.170 128
2014-06-22 20:34:56.177 256
2014-06-22 20:34:56.183 512
2014-06-22 20:34:56.193 1024
2014-06-22 20:34:56.210 2048
2014-06-22 20:34:56.240 4096
2014-06-22 20:34:56.293 8192
2014-06-22 20:34:56.397 16384
2014-06-22 20:34:56.493 32768
2014-06-22 20:34:56.607 65536
2014-06-22 20:34:56.817 131072
2014-06-22 20:34:57.240 262144
2014-06-22 20:34:57.710 524288
2014-06-22 20:35:01.630 1048576

为什么GETDATE()初始化每个语句而不是每个插入?

如何在不使用游标的情况下确保每行而不是每个语句初始化默认值?

编辑:可能相关,tab3_log与tab3具有相同的架构

CREATE TRIGGER tab3_logger on tab3
AFTER INSERT
AS
BEGIN
INSERT INTO tab3_log(a) select a from inserted
END

将单个insert语句中的所有行显示为具有相同的日期时间

3 个答案:

答案 0 :(得分:4)

  

什么时候初始化默认值?

这取决于表达式是否为“runtime constant”。

要获得所需的行为,可以将调用包装在标量UDF中。

CREATE FUNCTION dbo.F()
RETURNS DATETIME
AS
  BEGIN
      RETURN GETDATE()
  END

GO

CREATE TABLE T
  (
     A CHAR(8000) NULL,
     B FLOAT DEFAULT RAND(), 
     C DATETIME DEFAULT GETDATE(),
     D DATETIME DEFAULT dbo.F(),
     E UNIQUEIDENTIFIER DEFAULT NEWID()
  )

INSERT INTO T
            (A)
SELECT TOP 100000 'A'
FROM   master..spt_values v1,
       master..spt_values v2

SELECT COUNT(DISTINCT B) AS B,
       COUNT(DISTINCT C) AS C,
       COUNT(DISTINCT D) AS D,
       COUNT(DISTINCT E) AS E
FROM   T

GO

DROP TABLE T;
DROP FUNCTION F;

返回(例如,D的确切值会有所不同)

+---+---+-----+--------+
| B | C |  D  |   E    |
+---+---+-----+--------+
| 1 | 1 | 823 | 100000 |
+---+---+-----+--------+

每个语句评估前两个,每行第二个。

答案 1 :(得分:3)

SQL是基于集合的,而不是逐行的。 insert语句在逻辑上一次性发生,因此为语句插入的所有行分配相同的值是正确的。您甚至可以在更快的机器上获得不同语句的相同getdate值,因为getdate只有精度为毫秒,精度为正负3-4毫秒。

答案 2 :(得分:1)

为什么会发生这种情况很难说清楚。我认为这是优化与“列默认值”的语义之间的关系。也许SQL对此没有任何说法。但是有人可以说这个日期可以用于单笔交易。

不确定如何解决,但我会尝试这个:

insert into tab3 (a, d1) select a, getdate() from tab3
GO 20