SQL Server преобразовать дату и время в дату без нуля

У меня есть такая хранимая процедура:

select 
    TransactionDate 
from 
    (select 
         cast(TransactionDate as Date) as TransactionDate
     from RetailTransaction) t

Однако это делает столбец TransactionDate внешнего выбора допускающим значение NULL, в то время как столбец RetailTransaction.TransactionDate не имеет значения NULL.

RetailTransaction.TransactionDate определение / дизайн:

SQL Server преобразовать дату и время в дату без нуля

Внутренний выбор:

SQL Server преобразовать дату и время в дату без нуля

Внешний выбор:

SQL Server преобразовать дату и время в дату без нуля

Даже после добавления isnull или coalesce SQL Server / SSMS по-прежнему показывает, что столбец внешнего выбора TransactionDate по-прежнему допускает значение NULL.

select 
    TransactionDate 
from 
    (select 
         isnull(cast(TransactionDate as Date), getdate()) as TransactionDate
     from 
         RetailTransaction) t

SQL Server преобразовать дату и время в дату без нуля

Как сделать столбец TransactionDate не допускающим значения NULL?

Обратите внимание, что база данных находится в Azure с уровнем совместимости 100 (SQL Server 2008).

Обновлено:

Добавление isnull во внешний выбор по-прежнему делает столбец допускающим значение NULL для внешнего вложенного запроса:

SQL Server преобразовать дату и время в дату без нуля

Что вы имеете в виду под тем, что столбец по-прежнему «допускает значение NULL»?

Tim Biegeleisen 04.01.2019 05:01

@TimBiegeleisen См. Всплывающие подсказки, тип данных этого столбца - (date, null), тогда как он должен быть (date, not null). Сравните пример внутреннего выбора с примером внешнего выбора

Minijack 04.01.2019 05:03

Вы управляете этим из определения вашей таблицы. Вы можете это добавить?

Tim Biegeleisen 04.01.2019 05:04

Столбец TransactionDate в таблице RetailTransaction - это (datetime, not null). Результирующий набор данных после преобразования на сегодняшний день - (date, null).

Minijack 04.01.2019 05:05

@TimBiegeleisen Обновил вопрос

Minijack 04.01.2019 05:14

Итак, у меня нет конкретных ответов здесь, я просто догадываюсь, как работает intellisense и почему это может не иметь значения фактически. Intellisense может быть спроектирован так, чтобы просто автоматически предполагать, что результат любой функции (например, CAST, CONVERT, ISNULL) мог бы будет NULL (поскольку он может не быть разработан для определения того, может ли функция иметь значение NULL на основе входных данных). Однако это может не отражать фактически того, что происходит на самом деле. Если результат никогда не может быть нулевым, В самом деле не имеет значения, что об этом говорит intellisense.

ZLK 04.01.2019 06:11

@ZLK Причина, по которой это проблема, заключается в том, что я использую эту хранимую процедуру с помощью EntityFramework (C#) и обнаруживаю, что этот столбец допускает значение NULL, что делает мои типы допускающими значение NULL. Я думаю, что нашел обходной путь, при котором я делаю Insert into @temptable с TransactionDate, установленным как (date, not null), а затем выбираю его.

Minijack 04.01.2019 06:17

Это, наверное, самое простое решение. Альтернативой может быть что-то вроде ручного изменения типа данных в C# или, я думаю, добавление постоянного вычисляемого столбца в вашу таблицу, который преобразует дату и время в дату и уже не равен нулю (что может быть полезно для вас, если вы регулярно используете его как дату так или иначе).

ZLK 04.01.2019 06:30

Это может быть глупый вопрос, но если столбец не допускает значения NULL, зачем вы добавляете isnull или coalesce? если это значение DateTime, которое не допускает значения NULL, приведение к Date никогда не вернет значение NULL, поэтому isnull/coalesce является избыточным.

Zohar Peled 04.01.2019 08:00

Почему вы используете столбец datetime? Это для удаления каких-либо отметок времени?

Mats Magnem 04.01.2019 11:55

@MatsMagnem Да, но мне нужно, чтобы он был строго типизирован

Minijack 15.01.2019 02:27

@ZoharPeled CAST превращает столбец в (datetime, null), и мне нужно, чтобы столбец был (datetime, not null)

Minijack 15.01.2019 02:28

Я понимаю. Сегодня узнал кое-что новое, спасибо!

Zohar Peled 15.01.2019 08:15
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
13
1 507
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Да, причина, по которой он показывает Nullable для столбца, не допускающего значения NULL, заключается в том, что вы делаете свой внешний выбор как вычисленный на основе условия isnull и других.

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

Теперь, если я не поставлю никаких условий, все будет так.

Вы также можете обратиться к этой ссылке для подробного объяснения.

https://dba.stackexchange.com/questions/114260/why-is-a-not-null-computed-column-considered-nullable-in-a-view

Я не думаю, что этот ответ точен ... И в предоставленной вами ссылке прямо говорится: «Выражение, допускающее значение NULL, можно превратить в выражение, не допускающее значения NULL, указав ISNULL (check_expression, constant), где константа является ненулевым значением. заменяется на любой нулевой результат ". так что это не касается этого ...

ZLK 04.01.2019 05:44

Хитрость заключается в том, чтобы поместить ISNULL во внешний запрос и добавить псевдоним, чтобы вы не потеряли имя

select 
    isnull(TransactionDate, GETDATE()) as TransactionDate
from ( 
    select 
        Cast(TransactionDate as Date) as TransactionDate
    from RetailTransaction
) t

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

См. Обновленный вопрос. У меня это решение не работает.

Minijack 08.01.2019 02:19

@Minijack - это вычисляемый столбец?

Mack 08.01.2019 12:46

Нет. TransactionDate: datetime not null.

Minijack 08.01.2019 22:57
Ответ принят как подходящий

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

Спасибо за хорошо продуманный ответ с актуальными решениями.

Minijack 15.01.2019 23:21

Я решил воспользоваться вашим методом помещения моего набора результатов во временную таблицу, а затем просто вернуть его.

Minijack 16.01.2019 05:58

Рад помочь :-)

Zohar Peled 16.01.2019 06:26

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