Как сделать столбец представления NOT NULL - PullRequest
73 голосов
/ 24 февраля 2010

Я пытаюсь создать представление, в котором я хочу, чтобы столбец был только true или false. Однако, похоже, что независимо от того, что я делаю, SQL Server (2008) считает, что мой битовый столбец может как-то быть нулевым.

У меня есть таблица «Продукт» со столбцом «Статус», которая INT, NULL. В представлении я хочу вернуть строку для каждой строки в Product, причем для столбца BIT установлено значение true, если столбец Product.Status равен 3, в противном случае битовое поле должно быть ложным.

Пример SQL

SELECT CAST( CASE ISNULL(Status, 0)  
               WHEN 3 THEN 1  
               ELSE 0  
             END AS bit) AS HasStatus  
FROM dbo.Product  

Если я сохраню этот запрос как представление и посмотрю на столбцы в обозревателе объектов, для столбца HasStatus будет установлено значение BIT, NULL. Но это никогда не должно быть NULL. Есть ли какой-нибудь магический трюк SQL, который я могу использовать, чтобы этот столбец был NOT NULL.

Обратите внимание, что если я удаляю CAST() вокруг CASE, столбец будет правильно установлен как NOT NULL, но тогда тип столбца будет установлен на INT, что не является тем, что я хочу. Я хочу, чтобы это было BIT. : -)

Ответы [ 3 ]

136 голосов
/ 24 февраля 2010

Вы можете достичь того, чего хотите, немного изменив порядок запроса.Хитрость в том, что ISNULL должен быть снаружи, прежде чем SQL Server поймет, что результирующее значение никогда не может быть NULL.

SELECT ISNULL(CAST(
    CASE Status
        WHEN 3 THEN 1  
        ELSE 0  
    END AS bit), 0) AS HasStatus  
FROM dbo.Product  

Одна из причин, по которой я на самом деле считаю это полезным, - это использование ORM и вы не хотите, чтобы результирующее значение отображалось в обнуляемый тип.Это может упростить ситуацию, если ваше приложение увидит, что значение никогда не будет нулевым.Тогда вам не нужно писать код для обработки нулевых исключений и т. Д.

3 голосов
/ 14 января 2015

К вашему сведению, для людей, сталкивающихся с этим сообщением, добавление функции ISNULL () за пределами приведения / преобразования может испортить оптимизатор в вашем представлении.

У нас было 2 таблицы, использующие одно и то же значение в качестве ключа индекса, но с типами различной числовой точности (я знаю, что это плохо), и наше представление объединялось с ними для получения окончательного результата. Но наш код промежуточного программного обеспечения искал определенный тип данных, и у представления было CONVERT () вокруг возвращаемого столбца

Как и OP, я заметил, что дескрипторы столбцов результата представления определили его как обнуляемый, и я подумал, что это первичный / внешний ключ в 2 таблицах; почему мы хотим, чтобы результат был определен как nullable?

Я нашел этот пост, бросил ISNULL () вокруг колонки и вуаля - больше не обнуляется.

Проблема заключалась в том, что при просмотре запроса по этому столбцу производительность представления сразу падала в унитаз.

По какой-то причине явный CONVERT () в столбце результатов представления не испортил оптимизатор (в любом случае он должен был сделать это из-за разной точности), но добавил избыточную оболочку ISNULL () с размахом.

0 голосов
/ 24 февраля 2010

Все, что вы можете сделать в операторе Select, это управлять данными, которые ядро ​​базы данных отправляет вам как клиенту. Оператор выбора не влияет на структуру базовой таблицы. Чтобы изменить структуру таблицы, необходимо выполнить инструкцию Alter Table.

  1. Сначала убедитесь, что в этом битовом поле в таблице в настоящее время нет нулей
  2. Затем выполните следующую инструкцию ddl: Alter Table dbo.Product Alter column status bit not null

Если, ооо, все, что вы пытаетесь сделать, это контролировать вывод представления, то то, что вы делаете, достаточно. Ваш синтаксис гарантирует, что вывод столбца HasStatus в наборе результатов представлений будет на самом деле никогда быть нулевым. всегда будет либо битовым значением = 1, либо битовым значением = 0. Не беспокойтесь о том, что говорит проводник объектов ...

...