Вопрос

Я пытаюсь создать представление, в котором я хочу, чтобы столбец был только истинным или ложным.Однако, похоже, что бы я ни делал, 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. :-)

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top