У меня есть такая хранимая процедура:
select
TransactionDate
from
(select
cast(TransactionDate as Date) as TransactionDate
from RetailTransaction) t
Однако это делает столбец TransactionDate внешнего выбора допускающим значение NULL, в то время как столбец RetailTransaction.TransactionDate не имеет значения NULL.
RetailTransaction.TransactionDate определение / дизайн:
Внутренний выбор:
Внешний выбор:
Даже после добавления isnull или coalesce SQL Server / SSMS по-прежнему показывает, что столбец внешнего выбора TransactionDate по-прежнему допускает значение NULL.
select
TransactionDate
from
(select
isnull(cast(TransactionDate as Date), getdate()) as TransactionDate
from
RetailTransaction) t
Как сделать столбец TransactionDate не допускающим значения NULL?
Обратите внимание, что база данных находится в Azure с уровнем совместимости 100 (SQL Server 2008).
Обновлено:
Добавление isnull во внешний выбор по-прежнему делает столбец допускающим значение NULL для внешнего вложенного запроса:
@TimBiegeleisen См. Всплывающие подсказки, тип данных этого столбца - (date, null), тогда как он должен быть (date, not null). Сравните пример внутреннего выбора с примером внешнего выбора
Вы управляете этим из определения вашей таблицы. Вы можете это добавить?
Столбец TransactionDate в таблице RetailTransaction - это (datetime, not null). Результирующий набор данных после преобразования на сегодняшний день - (date, null).
@TimBiegeleisen Обновил вопрос
Итак, у меня нет конкретных ответов здесь, я просто догадываюсь, как работает intellisense и почему это может не иметь значения фактически. Intellisense может быть спроектирован так, чтобы просто автоматически предполагать, что результат любой функции (например, CAST, CONVERT, ISNULL) мог бы будет NULL (поскольку он может не быть разработан для определения того, может ли функция иметь значение NULL на основе входных данных). Однако это может не отражать фактически того, что происходит на самом деле. Если результат никогда не может быть нулевым, В самом деле не имеет значения, что об этом говорит intellisense.
@ZLK Причина, по которой это проблема, заключается в том, что я использую эту хранимую процедуру с помощью EntityFramework (C#) и обнаруживаю, что этот столбец допускает значение NULL, что делает мои типы допускающими значение NULL. Я думаю, что нашел обходной путь, при котором я делаю Insert into @temptable с TransactionDate, установленным как (date, not null), а затем выбираю его.
Это, наверное, самое простое решение. Альтернативой может быть что-то вроде ручного изменения типа данных в C# или, я думаю, добавление постоянного вычисляемого столбца в вашу таблицу, который преобразует дату и время в дату и уже не равен нулю (что может быть полезно для вас, если вы регулярно используете его как дату так или иначе).
Это может быть глупый вопрос, но если столбец не допускает значения NULL, зачем вы добавляете isnull или coalesce? если это значение DateTime, которое не допускает значения NULL, приведение к Date никогда не вернет значение NULL, поэтому isnull/coalesce является избыточным.
Почему вы используете столбец datetime? Это для удаления каких-либо отметок времени?
@MatsMagnem Да, но мне нужно, чтобы он был строго типизирован
@ZoharPeled CAST превращает столбец в (datetime, null), и мне нужно, чтобы столбец был (datetime, not null)
Я понимаю. Сегодня узнал кое-что новое, спасибо!





Да, причина, по которой он показывает Nullable для столбца, не допускающего значения NULL, заключается в том, что вы делаете свой внешний выбор как вычисленный на основе условия isnull и других.
В этой таблице электронная почта не является столбцом, допускающим значение NULL, и теперь, если я задаю условие Isnull во внутреннем запросе, оно будет таким.
Теперь, если я не поставлю никаких условий, все будет так.
Вы также можете обратиться к этой ссылке для подробного объяснения.
Я не думаю, что этот ответ точен ... И в предоставленной вами ссылке прямо говорится: «Выражение, допускающее значение NULL, можно превратить в выражение, не допускающее значения NULL, указав ISNULL (check_expression, constant), где константа является ненулевым значением. заменяется на любой нулевой результат ". так что это не касается этого ...
Хитрость заключается в том, чтобы поместить ISNULL во внешний запрос и добавить псевдоним, чтобы вы не потеряли имя
select
isnull(TransactionDate, GETDATE()) as TransactionDate
from (
select
Cast(TransactionDate as Date) as TransactionDate
from RetailTransaction
) t
Таким образом, SQL поймет, что поле не может быть нулевым. Это должно хорошо информировать любой ORM о том, что это поле не должно отображаться в тип, допускающий значение NULL.
См. Обновленный вопрос. У меня это решение не работает.
@Minijack - это вычисляемый столбец?
Нет. TransactionDate: datetime not null.
Прочитав ваш комментарий, я немного покопался и протестировал, и хотя я не смог найти официальную документацию по этому поводу, вы правы, и приведение к настоящему времени делает значение обнуляемым, даже если datetime не допускает значения NULL. Я даже пробовал другой метод, используя datetimefromparts для создания типа данных даты, но это также меняет возможность нулевого значения результата.
На мой взгляд, у вас есть два варианта:
Первый вариант - добавить в таблицу постоянный вычисляемый столбец, который будет содержать значение даты для даты транзакции. Он должен сохраняться, чтобы не допускать значения NULL:
ALTER TABLE RetailTransaction
ADD TransactionDateOnly AS CAST(TransactionDate As Date) PERSISTED NOT NULL;
и тогда ваш запрос будет выглядеть так:
SELECT TransactionDateOnly as TransactionDate
FROM RetailTransaction
Другой вариант - объявить табличную переменную со столбцом даты, не допускающим значения NULL, выбрать в нем результаты приведения, а затем выбрать из табличной переменной:
DECLARE @Target AS TABLE
(
TransactionDate Date NOT NULL
)
INSERT INTO @Target(TransactionDate)
SELECT CAST(TransactionDate as Date)
FROM RetailTransaction) t
И тогда ваш выбор будет выглядеть так:
SELECT TransactionDate
FROM @Target
В результате в обоих случаях вы получите дату, не допускающую значения NULL, но я думаю, что параметр сохраняемого вычисляемого столбца, вероятно, должен обеспечить лучшую производительность при выборе, потому что не требует этой дополнительной вставки ... select.
Спасибо за хорошо продуманный ответ с актуальными решениями.
Я решил воспользоваться вашим методом помещения моего набора результатов во временную таблицу, а затем просто вернуть его.
Рад помочь :-)
Что вы имеете в виду под тем, что столбец по-прежнему «допускает значение NULL»?