Предположим, что у нас есть таблица, как показано ниже:SQL Server метаданные вычисляемого столбца в
CREATE TABLE dbo.tab(id INT PRIMARY KEY
-- other columns
,is_active BIT);
INSERT INTO dbo.tab(id, is_active)
VALUES (1, NULL), (2, 1), (3,0);
Дело в том, чтобы добавить вычисляемый столбец, который изменит NULL
к 0
и вернуть исходные значения, когда это возможно.
Окончательный результат:
- оригинальные колонны должны оставаться нетронутыми (так что нет никакой возможности
UPDATE
иALTER
таблицы) - вычисляемый столбец должен иметь правильный тип и допустимость пустых
- не может использовать
VIEW/TRIGGER/...
Итак, давайте просто добавим эту колонку:
CREATE TABLE dbo.tab(
id INT PRIMARY KEY
,is_active BIT
,calc_flag1 AS CAST(IIF(is_active IS NULL,0 ,is_active) AS BIT)
,calc_flag2 AS CAST(IIF(is_active IS NULL,0 ,ISNULL(is_active,0)) AS BIT)
,calc_flag3 AS IIF(is_active IS NULL,0 , ISNULL(is_active,0))
,calc_flag4 AS CAST(ISNULL(IIF(is_active IS NULL,0 , is_active), 0) AS BIT)
,calc_flag5 AS ISNULL(IIF(is_active IS NULL,0 ,is_active),0)
,calc_flag6 AS ISNULL(CAST(IIF(is_active IS NULL,0 ,is_active) AS BIT),
CAST(0 AS BIT))
);
данных:
SELECT * FROM dbo.tab;
╔══╦═════════╦══════════╦══════════╦══════════╦══════════╦══════════╦══════════╗
║id║is_active║calc_flag1║calc_flag2║calc_flag3║calc_flag4║calc_flag5║calc_flag6║
╠══╬═════════╬══════════╬══════════╬══════════╬══════════╬══════════╬══════════╣
║ 1║ NULL ║ False ║ False ║ 0 ║ False ║ 0 ║ False ║
║ 2║ True ║ True ║ True ║ 1 ║ True ║ 1 ║ True ║
║ 3║ False ║ False ║ False ║ 0 ║ False ║ 0 ║ False ║
╚══╩═════════╩══════════╩══════════╩══════════╩══════════╩══════════╩══════════╝
и метаданные проверка:
EXEC sp_help 'dbo.tab';
╔═════════════╦══════╦══════════╦════════╦══════╦═══════╦══════════╗
║ Column_name ║ Type ║ Computed ║ Length ║ Prec ║ Scale ║ Nullable ║
╠═════════════╬══════╬══════════╬════════╬══════╬═══════╬══════════╣
║ id ║ int ║ no ║ 4 ║ 10 ║ 0 ║ no ║
║ is_active ║ bit ║ no ║ 1 ║ ║ ║ yes ║
║ calc_flag1 ║ bit ║ yes ║ 1 ║ ║ ║ yes ║
║ calc_flag2 ║ bit ║ yes ║ 1 ║ ║ ║ yes ║
║ calc_flag3 ║ int ║ yes ║ 4 ║ 10 ║ 0 ║ no ║
║ calc_flag4 ║ bit ║ yes ║ 1 ║ ║ ║ yes ║
║ calc_flag5 ║ int ║ yes ║ 4 ║ 10 ║ 0 ║ no ║
║ calc_flag6 ║ bit ║ yes ║ 1 ║ ║ ║ no ║
╚═════════════╩══════╩══════════╩════════╩══════╩═══════╩══════════╝
Первая попытка:
,calc_flag1 AS CAST(IIF(is_active IS NULL,0 ,is_active) AS BIT)
Исправьте тип данных, но он не может получить значение nullability. Я могу понять это потому, что он имеет жестко заданное значение и столбец с нулевым значением, поэтому все выражение оценивается как NULL.
Вторая попытка:
,calc_flag2 AS CAST(IIF(is_active IS NULL,0 ,ISNULL(is_active,0)) AS BIT)
То же, что и раньше, но с явным ISNULL(is_active, 0)
. Теперь он должен работать, потому что есть hardcoded значение и ISNULL
, но это не так.
,calc_flag3 AS IIF(is_active IS NULL,0 , ISNULL(is_active,0))
Что интересно, без CAST
это получить nullable
- no
, но тип данных INT
в настоящее время.
Третья попытка:
,calc_flag4 AS CAST(ISNULL(IIF(is_active IS NULL,0 , is_active), 0) AS BIT)
Кастинг ISNULL
когда второе значение жёстко. Почему это может быть nullable
?
,calc_flag5 AS ISNULL(IIF(is_active IS NULL,0 ,is_active),0)
Конечно, без приведения его работы, как это должно быть.
Заключительная попытка:
,calc_flag6 AS ISNULL(CAST(IIF(is_active IS NULL,0 ,is_active) AS BIT),
CAST(0 AS BIT))
Теперь я получаю правильный тип данных и допустимость пустых, но это как-то некрасиво.
Вопрос заключается в том, почему он ведет себя таким образом, и не могут получить правильные метаданные при calc_flag2
или calc_flag4
используется.
Любопытный ... Я голосовал, чтобы закрыть и перейти на сайт дБА, где мы надеемся, Пол Уайт, или кто-то с подобным опытом на внутренностях SQL Server будет видеть это. Для чего вы можете получить столбец с недействительным битом, используя просто 'calc_flag7 AS ISNULL (is_active, 0)' – GarethD
Я думаю, что проблема может быть упрощена до того, почему 'ISNULL (is_active, 0)' дает столбец с непустым значением столбца , но просто добавив преобразование, подобное 'CONVERT (BIT, ISNULL (is_active, 0))', приводит к тому, что один и тот же столбец имеет значение NULL. Используя специальный раздел из [этого ответа] (http://dba.stackexchange.com/a/114266/7257) (я знал, что у Пола Уайта будет ответ!), Причина в том, что некоторые сеансы настройки могут привести к переполнению конверсий return null, так что единственный способ обеспечить столбец с нулевым значением - это то, что внешняя самая большая функция - 'ISNULL'. – GarethD
Еще одно замечание состоит в том, что выражение 'CASE' будет иметь только возвращаемый тип с нулевым значением, если ** все ** возвращаемые выражения не являются нулевыми, поэтому даже если вы используете' IIF (is_active IS NULL, 0, is_active) ', выражение return для false никогда не будет достигнуто, если оно равно null, оно по-прежнему является возвращаемым типом возвращаемого значения, поэтому возвращаемый тип является нулевым. – GarethD