Почему значение этого символа не конвертируется в datetime? - PullRequest
1 голос
/ 02 июля 2019

У меня есть экземпляр системного монитора, который сохраняет данные в таблицу базы данных сервера MS SQL.Данные о производительности сохраняются в таблице с именем CounterData.В таблице есть поле char (24) (counterdatetime) для хранения даты / времени данных.Я пытаюсь обработать это поле как данные даты и времени, но продолжаю получать сообщение «Ошибка при преобразовании при преобразовании даты и / или времени из символьной строки».

Вот пример данных из контрдата: 2019-07-02 09: 19: 46.300

Я пробовал разные варианты CAST и CONVERT, чтобы позволить мне обрабатывать эти данные как дату и время.Например:

SELECT CAST(counterdatetime as datetime) from CounterData
SELECT CAST(counterdatetime as datetime2) from CounterData
SELECT CONVERT(datetime,counterdatetime,101) from CounterData

Каждый дает мне «Преобразование не удалось ...»ошибка.Я подумал, что, возможно, сбой был вызван фиктивным значением в одной записи, поэтому я попытался ограничить преобразование выражением WHERE, которое указывает правильное значение.Я также попытался привести само значение, например:

SELECT CAST('2019-07-02 09:19:46.300' as datetime)

В этом случае CAST работает.

Почему не работает, когда я выбираю значение из таблицы?

ОБНОВЛЕНИЕ

@ Йерун Мостерт предоставил ответ в комментарии, который я разместил в качестве ответа.

Ответы [ 4 ]

3 голосов
/ 02 июля 2019

Я не уверен, является ли литерал '2019-07-02 09:19:46.300' текстовым значением, которое фактически приводит к сбою вашего запроса. Если вы используете SQL Server 2012 или более позднюю версию, существует вспомогательная функция TRY_CONVERT, которая будет пытаться преобразовать входную строку в определенный тип (в данном случае datetime) и либо возвратит преобразованное datetime значение или NULL, если преобразование не удалось.

Попробуйте выполнить следующий запрос:

SELECT
    counterdatetime
FROM CounterData
WHERE
    TRY_CONVERT(datetime, counterdatetime) IS NULL;

Если вы видите какие-либо записи в наборе результатов, это означает, что эти значения не могут быть успешно преобразованы.

0 голосов
/ 02 июля 2019

@ Йерун Мостерт предоставил правильный ответ в комментарии к оригинальному сообщению, поэтому следует отдать ему должное.

О-о, Спагетти-О.Это символ NUL, который не принадлежит там.Это очень ужасно, потому что REPLACE по умолчанию не знает, что с ними делать.Попробуйте CONVERT (DATETIME, REPLACE (CounterDateTime COLLATE Latin1_General_BIN2, CHAR (0), '')).(SUBSTRING (CounterDateTime, 1, 23) также должен работать в этом случае, так как мы можем ожидать, что NUL всегда будет в конце.)

0 голосов
/ 02 июля 2019

В таблице есть поле char (24) ... Я пытаюсь обработать это поле как данные даты и времени

НЕ ДЕЛАЙТЕ ЭТОГО! Если у вас есть значения DateTime, сохраняйте их, используя тип из семейства DateTime!Надеюсь, что все это является частью проекта fix (потому что сейчас схема действительно повреждена ) этой таблицы.В качестве одного из многих примеров того, почему это важно, индексы в этом столбце в основном бесполезны.

Я подумал, что, возможно, сбой был вызван фиктивным значением в одной записи ....

Это точно , что происходит.Есть плохие данные.(Использование реального типа DateTime предотвратит это в первую очередь).

... поэтому я попытался ограничить преобразование выражением WHERE, которое задает правильное значение.

Еще раз проверьте предложение WHERE, поскольку оно не былодостаточно конкретным, или возникла проблема с выбранным значением, которое вы сначала не видели.

0 голосов
/ 02 июля 2019

yyyy-MM-dd hh:mm:ss.sss не является однозначным форматом при использовании типа данных datetime;оно меняется в зависимости от языка.

Возьмите следующие примеры:

SET LANGUAGE ENGLISH; --American
SELECT CONVERT(datetime,'2019-07-06'); --Returns 06 July 2019

SET LANGUAGE BRITISH; --English
SELECT CONVERT(datetime,'2019-07-06'); --Returns 07 June 2019

Если мы возьмем дату, подобную приведенной ниже, посмотрите, что произойдет:

SET LANGUAGE ENGLISH; --American
SELECT CONVERT(datetime,'2019-01-31'); --Returns 01 January 2019

SET LANGUAGE British; --English
SELECT CONVERT(datetime,'2019-01-31'); --Conversion error

Однако на самом деле вы не должны хранить свои даты как char, и вам нужно это исправить.К счастью, вы можете легко исправить ваши данные, изменив их на формат ISO yyyy-MM-ddThh:mm:ss.sss:

UPDATE CounterData
SET counterdatetime = STUFF(counterdatetime,11,1,'T');

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