Як зробити стовпець подання НЕ ПУСТИМ


84

Я намагаюся створити подання, де я хочу, щоб стовпець був лише істинним чи хибним. Однак, здається, незалежно від того, що я роблю, 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. Але це ніколи не повинно бути НУЛОМ. Чи є якийсь магічний трюк SQL, який я можу використати, щоб змусити цей стовпець бути NOT NULL.

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

Відповіді:


150

Ви можете досягти бажаного, трохи переставивши запит. Фокус у тому, що 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, і ви не хочете, щоб отримане значення було зіставлене з типом, що має значення. Це може полегшити все навколо, якщо ваш додаток вважає, що значення ніколи не є нульовим. Тоді вам не потрібно писати код для обробки нульових винятків тощо.


@Gunder: не хвилюйся, насправді це трохи загадково. Це також зручно використовувати при створенні обчислюваного бітового стовпця в таблиці та бажаючи, щоб результат не міг обнулятись.
RedFilter

8
Мені потрібно було щось подібне, і я виявив, що COALESCE()це не спрацювало, ви насправді повинні скористатисяISNULL()
EvilBob22

@ EvilBob22 Це дивно, оскільки і COALESCE, і ISNULL можуть повернути NULL. Просто примха компілятора, я думаю.
RedFilter

1
Це, помножене на мільярд, для того, щоб EntityFramework вивів ключ, коли його зазвичай не виводять.
Ерік,

1
Дивіться також: dba.stackexchange.com/questions/114260/…
emragins

3

FYI, для людей, які стикаються з цим повідомленням, додавання ISNULL () навколо зовнішньої частини приведення / конвертації може зіпсувати оптимізатор у вашому поданні.

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

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

Я знайшов цю публікацію, кинув ISNULL () навколо колони і вуаля - більше не можна обнуляти.

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

З якихось причин явний CONVERT () у стовпці результату подання не зіпсував оптимізатор (це все одно доведеться зробити через різні точності), але додавши зайву обгортку ISNULL (), у великий шлях.


Не могли б ви показати рішення про те, як забезпечити / вказати ненульованість за CONVERT()допомогою прикладу, будь ласка?
АБО Mapper

1
Привіт АБО - вибачте, я деякий час цього не бачив. Ось приклад. Якщо у вас є CONVERT (BIT, U.RETIRED), 0) AS Retired на ваш погляд, перетворюючи байт або стовпець int у біт / bool, тоді він стає нульовим. Ви можете зробити цей стовпець у своєму поданні ненульованим, замінивши його на ISNULL (CONVERT (BIT, U.RETIRED), 0) AS Retired. Якщо для запуску U.RETIRED не було null, це функціонально не змінює нічого, крім стовпця у поданні. ПОПЕРЕДЖЕННЯ: ISNULL () може перешкоджати оптимізації запитів та вибору показників.
user1664043

-3

Все, що ви можете зробити в операторі Select, - це керувати даними, які механізм баз даних надсилає вам як клієнту. Оператор select не впливає на структуру базової таблиці. Щоб змінити структуру таблиці, потрібно виконати оператор Alter Table.

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

Якщо, ото, все, що ти намагаєшся зробити, це контролювати висновок подання, тоді достатньо того, що ти робиш. Ваш синтаксис гарантуватиме, що результат виведення стовпця HasStatus у наборі результатів подань насправді ніколи не буде нульовим. Це завжди буде або бітове значення = 1, або бітове значення = 0. Не хвилюйтеся, що говорить дослідник об’єктів ...


6
Я не хочу змінювати стовпець таблиці. Стовпець визначається як цілочисельний стовпець, що допускає значення null. Це відповідає нашій специфікації. Але мені потрібен подання, яке повертає стовпець із бітовим полем, яке не може бути нульовим. Недостатньо того, що я знаю, що це не може бути нулем, стовпець повинен бути НЕ НУЛЬНИМ, щоб він правильно відображався в нашій ORM.
Рене,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.