Почему возвращаемые результаты IIF и ISNULL не соответствуют моим ожиданиям при использовании значений даты? - PullRequest
2 голосов
/ 02 мая 2019

Я пытаюсь использовать IIF (), чтобы вернуть приведение столбца в качестве даты, но только в том случае, если значение не является пустой строкой [значения не сохраняются как нулевые значения в базе данных, с которой я работаю].

Я пытался использовать 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 (похоже, работает нормально, я также проверил inverse = '', '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]

Я ожидаю, что результат будетпустое значение, если существующее значение было пустым и, если нет, возвращаемое значение даты.Я думаю, что преобразование в дату перед проверкой на нулевые значения, вероятно, было бы лучше, потому что, если передана недопустимая дата (например, 31.04.2009), тогда она будет преобразована в пустое значение, которое является предпочтительной функциональностью в этом случае.

Приведенный ниже код работает, но я действительно не уверен, что это лучший способ сделать это.

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

Ответы [ 3 ]

2 голосов
/ 02 мая 2019

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 голос
/ 03 мая 2019

Я ожидаю, что выходные данные будут пустыми, если существующее значение было пустым, а если нет, то возвращалось значение даты.

Каждый столбец из набора результатов должен иметьтип данных.Типы данных DATE и DATETIME не могут содержать пустые строки, только действительные даты или 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

Вы видите, что CASE (IIF работает аналогично) возвращает тип даты, поэтому пустая строка неявно преобразуется в дату по умолчанию 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  
1 голос
/ 02 мая 2019

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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...