SQL Server将datetime转换为日期,不包含null

时间:2019-01-04 03:10:18

标签: sql-server tsql azure-sql-database ssms

我有一个类似的存储过程:

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

但是,这会使外部选择的TransactionDate列为空,而RetailTransaction.TransactionDate列不为空。

RetailTransaction.TransactionDate定义/设计:

enter image description here

内部选择

Inner Select

外部选择:

Outer Select

即使添加了isnullcoalesce之后,SQL Server / SSMS仍然显示外部选择TransactionDate列仍然可以为空。

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

Example 2

如何使TransactionDate列不可为空?

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

编辑:

在外部选择上添加isnull仍会使该列对外部嵌套查询为空:

outer-nested-query

3 个答案:

答案 0 :(得分:3)

是的,对于不可为空的列显示为可为空的原因是因为您正在根据外部条件和其他条件进行外部选择。

在此表中,电子邮件不可为空列,现在,如果我在内部查询中提供Isnull条件,它将是这样。

enter image description here

现在,如果我不给出任何条件,它将是这样。

enter image description here

您也可以参考此链接以获取详细说明。

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

答案 1 :(得分:1)

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

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

ALTER TABLE RetailTransaction
    ADD TransactionDateOnly AS CAST(TransactionDate As Date) PERSISTED NOT NULL;

,然后您的查询如下所示:

SELECT TransactionDateOnly as TransactionDate
FROM RetailTransaction

另一种选择是声明一个带有不可为null的date列的表变量,选择强制转换结果,然后从表变量中进行选择:

DECLARE @Target AS TABLE
(
    TransactionDate Date NOT NULL
)
INSERT INTO @Target(TransactionDate)
SELECT CAST(TransactionDate as Date) 
FROM RetailTransaction) t

然后您的选择如下所示:

SELECT TransactionDate 
FROM  @Target

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

答案 2 :(得分:0)

诀窍是将ISNULL放在外部查询上并添加别名,以免丢失名称

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

这样,SQL将意识到该字段不能为null。这应该很好地通知任何ORM,该字段不应映射为可为空的类型。