Не удается преобразовать дату и / или время из символьной строки - PullRequest
0 голосов
/ 14 октября 2018

У меня есть этот запрос, и я попытался преобразовать его в каждый формат, я имею в виду дату и т. Д., Но он не работает и выдает ошибку:

Преобразование не удалось при преобразовании даты и / или временииз строки символов.

SELECT  W.Organization_ID, 
        W.NIT_No, 
        W.SchemeID,
        OpeningDate,
        OpeningTime,
        GETDATE(), 
        WorkNo, 
        CONVERT(decimal(10, 2), W.Cost) AS Cost, 
        WorkName, 
        W.ExpiryDate as ExpiryDate,
        CONVERT(VARCHAR,OpeningDate,106),
        CASE WHEN 
               CONVERT(DATETIME, CONVERT(VARCHAR(20),OpeningDate,106) + ' ' 
               + CONVERT(VARCHAR(20),OpeningTime,108))< GETDATE() 
             THEN 1 
             ELSE 0 END AS OpeningVaild
FROM Works W

часть CASE выдает ошибку.

OpeningDate имеет тип Varchar, а OpeningTime имеет тип Time.

Почему?

Ответы [ 3 ]

0 голосов
/ 14 октября 2018

Итак, я понимаю, что проблема в этой части:

CASE WHEN CONVERT(DATETIME, CONVERT(VARCHAR(20),OpeningDate,106) + ' ' + CONVERT(VARCHAR(20),OpeningTime,108))< GETDATE() THEN 1 ELSE 0 END AS OpeningVaild

Обновление

Так как я впервые опубликовал свой ответ,Оказывается, вы сохраняете дату открытия как varchar вместо date.
Во-первых, вам следует прекратить это делать.Никогда не храните даты ни в каком другом столбце, кроме Date (если только они вам не нужны со временем, а затем используйте DateTime2).Для получения дополнительной информации прочитайте Плохие привычки Аарона Бертранда: выбор неправильного типа данных.

Предполагая, что тип данных столбца не может измениться, вы написали в комментариях к вопросу:

@ ZoharPeled: это формат даты открытия 2017-04-10

Иллюстрирование одной из проблем, вызванных сохранением дат в виде строк - Как я могу, иликто-нибудь еще по этому вопросу, знаете, это 10 апреля или 4 октября?Ответ - мы не можем.

Итак, если предположить, что это 10 апреля, вы можете преобразовать его в DateTime, используя преобразование с 126 в качестве параметра стиля:

CASE 
    WHEN CONVERT(DateTime, OpeningDate, 126) + CAST(OpeningTime As DateTime) < GETDATE() THEN 
        1 
    ELSE 
        0 
END As OpeningVaild

Firstверсия:

Предполагая, что тип данных OpeningDate равен Date, а тип данных OpeningTime равен Time. Похоже, вы пытаетесь выяснить, является ли комбинация этих столбцов в DateTime перед текущим DateTime.

Вместо преобразования их в строки и обратно в DateTime, вы можете привести оба к DateTime и просто сложить их вместе:

CASE 
    WHEN CAST(OpeningDate As DateTime) + CAST(OpeningTime As DateTime) < GETDATE() THEN 
        1 
    ELSE 
        0 
END As OpeningVaild

Другой вариант - использовать GETDATE() дважды.Я не думаю, что это должно иметь значение в предложении select, но в предложении where важно использовать эту опцию, так как первый сделает эти столбцы недоступными для поиска, то есть ядро ​​базы данных не сможет использоватьлюбые индексы, которые могут помочь плану выполнения оператора:

CASE 
WHEN OpeningDate < CAST(GETDATE() AS DATE) 
     OR 
     (
         OpeningDate = CAST(GETDATE() AS DATE) 
         AND OpeningTime <= CAST(GETDATE() AS TIME)
     ) THEN 
    1 
ELSE 
    0 
END AS OpeningVaild

При этом ваш запрос также имеет CONVERT(VARCHAR,OpeningDate,106) - стиль 106 возвращает строковое представление даты в виде dd mon yyyy - значение 11chars - так что измените это на CONVERT(CHAR(11),OpeningDate,106) Обратите внимание, что использование varchar без указания длины по умолчанию равно 30, что не является проблемой в этом случае, так как это больше, чем вам нужно 11 символов, но это плохая привычкане указывайте длину, и вы должны пнуть его.

0 голосов
/ 15 октября 2018

Вы можете упростить это большое время, немного изменив выражение.

Таким образом, вам не нужно конвертировать и объединять.

SELECT
  CASE WHEN OpeningDate < GETDATE() - OpeningTime
       THEN 1 
       ELSE 0 END AS OpeningVaild

Примечание. Предполагается, что для открытия даты в формате dd-mon-yyyy.В противном случае вам все равно нужно конвертировать его, но все равно короче:

SELECT
  CASE WHEN Convert(date, OpeningDate, 106) < GETDATE() - OpeningTime
       THEN 1 
       ELSE 0 END AS OpeningVaild
0 голосов
/ 14 октября 2018

Вы конвертируете только тип данных TIME, а не DATETIME, поэтому вам не нужно указывать стиль:

DECLARE @T TIME = '08:05:06';

SELECT CONVERT(VARCHAR(8), @T) AS [Time];
SELECT CAST(@T AS VARCHAR(8)) AS [Time];

Или, поскольку вы используете CONVERT(), выберите правильный style для TIME тип данных 108 или 114 вместо 106

SELECT CONVERT(VARCHAR(8), @T, 108) AS [Time];

Обновление:

В соответствии с ошибкой Msgваша проблема в части CASE.

То, что вы пытаетесь объединить DATETIME с типом данных VARCHAR, посмотрите на то, что вы конвертируете:

CASE WHEN 
       CONVERT(DATETIME, CONVERT(VARCHAR(20),OpeningDate,106) + ' ' 
       + CONVERT(VARCHAR(20),OpeningTime,108))< GETDATE() 
     THEN 1 
     ELSE 0 END AS OpeningVaild

Также столбец OpeningDate - в соответствии с ошибкой Msg - равен VARCHAR, поэтому вы конвертируете VARCHAR в VARCHAR, затем конвертируете его снова в DATETIME, затем вы пытаетеськонкатенировать DATETIME с VARCHAR, возвращаемым после преобразования столбца OpeningTime из TIME в VARCHAR, а затем попытаться сравнить их с GETDATE(), который имеет DATETIME тип данных.

Вы CASE должны выглядеть следующим образом:

CASE WHEN 
       (
         CAST(OpeningDate AS DATETIME) + -- VARCHAR to DATETIME  
         CAST(OpeningTime AS DATETIME)   -- TIME to DATETIME
       ) < GETDATE() 
     THEN 1 
     ELSE 0 END AS OpeningVaild

Рядом с примечанием, здесь в этой строке

CONVERT(VARCHAR,OpeningDate,106),

Вы пытаетесь преобразовать VARCHAR в VARCHAR и без указанияу длины тоже, поэтому эта строка должна быть:

CONVERT(VARCHAR(10),CAST(OpeningDate AS DATE),106),

Наконец, никогда не храните DATE как VARCHAR, DATE/ TIME/ DATEIME существуют по причине, поэтому используйте их ивсе остальные типы данных с умом.

Вот пример демо , представляющий вашу проблему и способ ее устранения.

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