当我将具有默认约束0x00000000000000000000000000000000
的新的定长varbinary列添加到现有的非空表中时,表中的现有记录将收到修剪后的默认约束{{1 }}。
随后插入的新记录确实正确应用了默认约束。
这仅发生在SQL 2017中,SQL的早期版本正确地将默认约束应用于所有现有记录。
包括'SET ANSI_PADDING ON'不会影响结果。
0x00
...的行为也相同,它会修剪尾随零。
我也尝试使用默认值0x11111111110000000
,但结果相同。
运行Microsoft SQL Server 2017(RTM-CU11)(KB4462262)-14.0.3038.14(X64)
要复制:
DEFAULT Cast(0x00000000000000000000000000000000 as varbinary(16))
结果:
create table #test (id int);
insert into #test (id) values (1), (2), (3);
alter table #test add testvarbinary VARBINARY(16) NOT NULL CONSTRAINT
DF_MyTable_NewColumn DEFAULT 0x00000000000000000000000000000000;
insert into #test (id) values (4);
select * from #test;
答案 0 :(得分:2)
有一个功能introduced in SQL Server 2012,该功能允许将NOT Null列添加到现有表中(具有默认约束) 这是为了允许将非空添加到非常大的表中。
这仅限于企业版和功能上等效的SKU,这就是为什么您只能在测试中的某些实例上看到它的原因。
它的工作方式是将现有行保留NULL
直到下一次触摸并从元数据中检索值。
元数据本身很好,可以使用
检查SELECT pc.default_value
FROM tempdb.sys.system_internals_partitions p
JOIN tempdb.sys.system_internals_partition_columns pc
ON p.partition_id = pc.partition_id
WHERE p.object_id = OBJECT_ID('tempdb..#test')
AND default_value IS NOT NULL;
但是当读取值时,会发生对0x00
的更改。
有趣的是-如果您将默认设置更改为0x00000000000000000000000000000001
然后所有行都将更新为正确的值:
id testvarbinary
1 0x00000000000000000000000000000001
2 0x00000000000000000000000000000001
3 0x00000000000000000000000000000001
4 0x00000000000000000000000000000001
一种可能的解决方法是使默认约束没有确定性(并且不可能将其作为运行时常量进行缓存),以防止在线列的添加。尽管您随后失去了该功能的性能优势。
以下默认约束表达式避免了该问题
DEFAULT 0x00000000000000000000000000000000 + CAST(LEFT(NEWID(),0) AS varbinary(1))
您应将其报告为the uservoice site上的错误。