Как сделать столбец вида NOT NULL

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

Ответ 1

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

Ответ 2

FYI, для людей, работающих в этом сообщении, добавление ISNULL() по внешней стороне cast/convert может испортить оптимизатор в вашем представлении.

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

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

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

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

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

Ответ 3

Это код, который я использую, он сделает столбец ID NOT NULL и все остальные NULL. Вы должны указать столбец бит или varchar и сравнить столбец int с NULL.

CREATE TABLE [dbo].[aTestTable](
    [ID] [int] NOT NULL,
    [varcharCol] [varchar](50) NOT NULL,
    [nullvarcharCol] [varchar](50) NULL,
    [bitCol] [bit] NOT NULL,
    [nullbitCol] [bit] NULL,
    [intCol] [int] NOT NULL,
    [nullintCol] [int] NULL,
 CONSTRAINT [PK_aTestTable] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]


CREATE VIEW [dbo].[aTestView]
AS
SELECT  ID ,
        NULLIF(varcharCol , '') AS varcharCol ,
        NULLIF(CAST(varcharCol AS VARCHAR), null) AS varcharCol1, --better
        nullvarcharCol ,
        NULLIF(CAST(bitCol AS INT), null) AS bitCol ,
        nullbitCol ,
        NULLIF(CAST(intCol AS INT), NULL) AS intCol ,
        nullintCol
FROM    dbo.aTestTable


Sample Data:

ID  varcharCol  nullvarcharCol  bitCol  nullbitCol  intCol  nullintCol
1   1   1   1   1   1   1
2   0   0   0   0   0   0
3   0   NULL    0   NULL    0   NULL
4   a   a   1   1   2   2

HTH

Ответ 4

Если у вас есть столбец, например, nullbitCol, с тремя значениями: True, False, NULL.

Вот как вы можете создать представление НЕ НЕДЕЙСТВИТЕЛЬНОЕ:

CREATE VIEW [dbo].[testView]
AS
select NULLIF(CAST(nullbitCol AS INT), null) as tmp FROM    dbo.testTable

Ответ 5

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

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

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

Ответ 6

DROP TABLE [dbo].[myTable1]
GO

CREATE TABLE [dbo].[myTable1](
    [a] [int] NULL,
    [b] [varchar](50),
) ON [PRIMARY]
GO

INSERT INTO [dbo].[myTable1]([a],[b]) VALUES(1,'A');
INSERT INTO [dbo].[myTable1]([a],[b]) VALUES(2,'B');
INSERT INTO [dbo].[myTable1]([a],[b]) VALUES(3,'C');
INSERT INTO [dbo].[myTable1]([a],[b]) VALUES(4,'D');
INSERT INTO [dbo].[myTable1]([a],[b]) VALUES(5,NULL);


SELECT *, 
    (CASE b
        WHEN NULL THEN CAST(0 AS BIT)
        WHEN 'A' THEN CAST(1 AS BIT)
        WHEN 'B' THEN CAST(0 AS BIT)
        ELSE CAST(0 AS BIT)
    END) AS Status
FROM dbo.myTable1