TSQL CASE неожиданно обрабатывает несколько операторов THEN - PullRequest
0 голосов
/ 19 сентября 2018

У меня есть простой оператор SQL CASE, который я пытаюсь интерпретировать тип данных переменной, а затем преобразовать его в указанный формат.У меня есть следующий пример:

  DECLARE @P1 varchar(10) = '2';

  SELECT CASE 1 
    WHEN ISNUMERIC(@P1) THEN (CAST(@P1 AS INT)) 
    WHEN ISDATE(@P1) THEN (CAST(@P1 AS DateTime)) 
    ELSE 'N' END AS Test2P1

Я ожидаю, что он вернет целочисленное значение 2. Однако, это то, что я получаю.

Test2P1

1900-01-03 00: 00: 00.000

Однако, если я изменю код, чтобы просто отобразить символ, а не CASTING переменной, я получу другой результат:

  DECLARE @P1 varchar(10) = '2';


  SELECT CASE 1 
    WHEN ISNUMERIC(@P1) THEN 'I' 
    WHEN ISDATE(@P1) THEN 'D'
    ELSE 'N' END AS Test2P1

Тогда я получурезультат: I

Если продвинуться в этом эксперименте на один шаг дальше, если я оставлю первый тест, возвращающий «Я», но приведу дату, то получу ошибку:

  DECLARE @P1 varchar(10) = '2';

  SELECT CASE 1 
    WHEN ISNUMERIC(@P1) THEN 'I'
    WHEN ISDATE(@P1) THEN (CAST(@P1 AS DateTime)) 
    ELSE 'N' END AS Test2P1

Msg 241, Level 16, State 1, Line 3
Conversion failed when converting date and/or time from character string.

ЭтоПохоже, что SQL оценивает несколько экземпляров операторов THEN.Однако выражение ISDATE НЕ возвращает true.Я в замешательстве.

В своем исследовании я наткнулся на эту статью [Производительность SQL] (https://sqlperformance.com/2014/06/t-sql-queries/dirty-secrets-of-the-case-expression) То, что он говорит в этой статье, имеет полный смысл. Но я не понимаю, где это применимо вв этой ситуации я никогда не изменяю значение переменной.

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

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

Хотя я не могу придумать вескую причину для этого, вы можете заставить выражение case возвращать sql_variant, которое может хранить несколько различных типов, например:

 DECLARE @P1 varchar(10) = '2';

  SELECT CASE 1 
    when 0 then cast(null as sql_variant)
    WHEN ISNUMERIC(@P1) THEN (CAST(@P1 AS INT)) 
    WHEN ISDATE(@P1) THEN (CAST(@P1 AS DateTime)) 
    ELSE 'N' END AS Test2P1
0 голосов
/ 19 сентября 2018

DateTime имеет более высокий приоритет типов данных в SQL Server, чем INT, поэтому весь ваш CASE получает приведение к DATETIME.Вы можете возвращать данные только одного типа данных в одном столбце, поэтому необходимо указывать приоритет типа данных.

Здесь - статья MSDN с указанием приоритета.

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