ANSI_PADDING на varbinary (16) не работает - PullRequest
0 голосов
/ 18 октября 2018

Когда я добавляю новый столбец varbinary фиксированной длины с ограничением по умолчанию 0x00000000000000000000000000000000 к существующей непустой таблице, существующие записи в таблице получают усеченную версию ограничения по умолчанию 0x00.

При последующих вставках новых записей корректно применяется ограничение по умолчанию.

Это происходит только в SQL 2017, предыдущие версии SQL корректно применяют ограничение по умолчанию ко всем существующим записям.

Включение 'SET ANSI_PADDING ON' не влияет на результат.

0x11111111110000000 ... также ведет себя так же, когда обрезает конечные нули.

Я также попытался использовать значение по умолчанию DEFAULT Cast(0x00000000000000000000000000000000 as varbinary(16)), но результат тот же.


Запуск Microsoft SQL Server 2017 (RTM-CU11) (KB4462262) - 14.0.3038,14 (X64)


Воспроизвести:

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;

Результат:

+----+------------------------------------+
| id |           testvarbinary            |
+----+------------------------------------+
|  1 | 0x00                               |
|  2 | 0x00                               |
|  3 | 0x00                               |
|  4 | 0x00000000000000000000000000000000 |
+----+------------------------------------+

1 Ответ

0 голосов
/ 18 октября 2018

В SQL Server 2012 появилась функция , позволяющая добавлять пустые столбцы NOT в существующую таблицу (с ограничением по умолчанию). Это позволяло добавлять ненулевые столбцы в очень большие таблицы..

Это ограничено выпуском Enterprise Edition и функционально эквивалентными номерами 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))

Вы должны сообщить об этом как об ошибке на сайте uservoice .

...