SQL Server将datetime转换为date而不为null

Min*_*ica 8 t-sql sql-server ssms azure-sql-database

我有一个像这样的存储过程:

select 
    TransactionDate 
from 
    (select 
         cast(TransactionDate as Date) as TransactionDate
     from RetailTransaction) t
Run Code Online (Sandbox Code Playgroud)

但是,这使得TransactionDate外部选择的RetailTransaction.TransactionDate列可以为空,而列不为空.

RetailTransaction.TransactionDate 定义/设计:

在此输入图像描述

内部选择:

内在选择

外选择:

外选择

即使在添加isnullcoalesceSQL Server/SSMS之后仍然显示外部选择TransactionDate列仍然可以为空.

select 
    TransactionDate 
from 
    (select 
         isnull(cast(TransactionDate as Date), getdate()) as TransactionDate
     from 
         RetailTransaction) t
Run Code Online (Sandbox Code Playgroud)

例2

如何使TransactionDate列不可为空?

请注意,该数据库位于Azure上,兼容级别为100(SQL Server 2008).

编辑:

isnull在外部选择上添加仍然使列可以为外部嵌套查询:

外嵌套查询

Zoh*_*led 1

阅读您的评论后,我做了一些挖掘和测试,即使我找不到有关它的官方文档,您是正确的,并且转换为日期使得该值可以为空,即使日期时间不可为空。我什至尝试了一种不同的方法来datetimefromparts创建日期数据类型,但这也改变了结果的可为空性。
所以在我看来,你有两个选择:

第一个选项是向表中添加一个持久计算列,该列将保存事务日期的日期值。它必须被持久化为不可空:

ALTER TABLE RetailTransaction
    ADD TransactionDateOnly AS CAST(TransactionDate As Date) PERSISTED NOT NULL;
Run Code Online (Sandbox Code Playgroud)

然后你的查询看起来像这样:

SELECT TransactionDateOnly as TransactionDate
FROM RetailTransaction
Run Code Online (Sandbox Code Playgroud)

另一种选择是声明一个具有不可空日期列的表变量,将转换结果选择到其中,然后从表变量中进行选择:

DECLARE @Target AS TABLE
(
    TransactionDate Date NOT NULL
)
INSERT INTO @Target(TransactionDate)
SELECT CAST(TransactionDate as Date) 
FROM RetailTransaction) t
Run Code Online (Sandbox Code Playgroud)

然后你的选择看起来像这样:

SELECT TransactionDate 
FROM  @Target
Run Code Online (Sandbox Code Playgroud)

这两种方法都会得到一个不可为空的日期,但我认为持久计算列选项可能会在选择上产生更好的性能,因为它不需要额外的插入...选择。