使用日期值时,为什么IIF和ISNULL的返回结果不符合我的期望?

时间:2019-05-02 19:49:11

标签: sql sql-server

我正在尝试使用IIF()返回列的强制转换作为日期,但是仅当该值不是空白字符串时(这些值未在我正在使用的数据库中存储为null)

我尝试使用ISNULL作为更好的中介,但是由于日期返回为1900-01-01,因此无法正常工作。它似乎可以与其他数据类型(int)一起使用。

示例表

CREATE TABLE #temp_test (
[reg_dt] varchar(10)
)
insert into #temp_test SELECT ''
insert into #temp_test SELECT ''
insert into #temp_test SELECT ''
insert into #temp_test SELECT ''
INSERT INTO #temp_test select '20080509'
select * from #temp_test

IIF测试示例(似乎可以正常运行,我还测试了反='','false','true');当我取消对try_convert的注释并删除“ true”时,遇到错误

SELECT IIF([reg_dt] != '', 'true'
       --TRY_CONVERT(date, [reg_dt], 112)
       , 'false') [reg_dt]
FROM   [#temp_test];

ISNULL的示例(返回1900-01-01)

SELECT ISNULL(TRY_CONVERT( DATE, [reg_dt], 112), '') [reg_dt] from [#temp_test]

如果现有值是空白,我希望输出是空白值,如果不是,则返回日期值。 我认为在检查空值之前转换为日期可能是最好的方法,因为如果传递了无效的日期(例如04/31/2019),则将其转换为空白值,这是这种情况下的首选功能。 / p>

下面的代码可以工作,但是我真的不确定这是否是最好的方法。

select ISNULL(NULLIF(CONVERT(VARCHAR(10), CAST([reg_dt] as date), 112), '19000101'), '') as [reg_dt] from #temp_test

3 个答案:

答案 0 :(得分:2)

NULL不等于空字符串。空字符串将转换为有效日期“ 1900-01-01”。如果要使用NULL,则需要指定NULL。

顺便说一句,与NULL的比较不会返回true或false。它将返回未知。

这是一个基于您的例子。

CREATE TABLE #temp_test (
[reg_dt] varchar(10)
)
insert into #temp_test SELECT ''
insert into #temp_test SELECT NULL
INSERT INTO #temp_test select '20080509'

SELECT IIF([reg_dt] != '', 'true', 'false') [reg_dt]
FROM   [#temp_test];

SELECT [reg_dt],
    TRY_CONVERT( DATE, [reg_dt], 112) [converted_reg_dt],
    ISNULL(TRY_CONVERT( DATE, [reg_dt], 112), '') [formatted_reg_dt] 
from [#temp_test];

答案 1 :(得分:1)

SQL不能为单个列返回多个数据类型,因此SQL必须将所有值转换为DATE。如果我理解正确,似乎您想检查日期是否有效,然后返回varchar(空白) 那么呢:

SELECT CASE reg_dt WHEN '' THEN '' ELSE CAST(TRY_CONVERT(date, [reg_dt], 112) AS varchar(20)) END AS YourDate FROM [#temp_test]

答案 2 :(得分:1)

  

如果现有值是,我希望输出为空值   空白,如果没有,则返回日期值。

结果集中的每一列都必须具有数据类型。 DATEDATETIME数据类型不能包含空字符串,只能包含有效日期或NULL。如果要查看空字符串,则必须使用字符串数据类型,例如VARCHAR

检查以下示例:

DECLARE @Varchar VARCHAR(100) = ''

SELECT
    EmptyVarchar = @Varchar,
    EmptyVarcharAsDate = CONVERT(DATE, @Varchar),
    CaseExpression = CASE WHEN @Varchar = '' THEN '' ELSE CONVERT(DATE, @Varchar) END

结果:

EmptyVarchar    EmptyVarcharAsDate  CaseExpression
                1900-01-01          1900-01-01

如果我们检查CASE实际返回的数据类型...

DECLARE @Varchar VARCHAR(100) = ''

SELECT
    ResultType = SQL_VARIANT_PROPERTY(
        CASE WHEN @Varchar = '' THEN '' ELSE CONVERT(DATE, @Varchar) END, 
        'BaseType')

结果:

ResultType
date

您看到CASEIIF的工作原理与此相似)返回日期类型,因此空字符串隐式转换为1900-01-01的默认日期。

一种处理日期并在无法转换时将其作为空字符串返回的方法如下:

DECLARE @VarcharDates TABLE (VarcharDate VARCHAR(100))

INSERT INTO @VarcharDates (VarcharDate)
VALUES
    (''),
    (NULL),
    ('NULL'),
    ('15'),
    ('2019'),
    ('2019-05'),
    ('31/01/2000'),
    ('1800-01-01'),
    ('20190503'),
    ('20190503111111')

SELECT
    V.VarcharDate,
    DateAsVarchar = CASE 
        WHEN V.VarcharDate = '' THEN ''
        ELSE ISNULL(
            CONVERT(VARCHAR(100), TRY_CONVERT(DATE, V.VarcharDate, 112)),
            '') END
FROM
    @VarcharDates AS V

结果:

VarcharDate     DateAsVarchar

NULL    
NULL    
15  
2019            2019-01-01
2019-05 
31/01/2000  
1800-01-01  
20190503        2019-05-03
20190503111111