Как SQL Server определяет формат неявного преобразования datetime?

declare @str_datetime varchar(50)
set @str_datetime='30-04-2012 19:01:45' -- 30th April 2012
declare @dt_datetime datetime
select @dt_datetime=@str_datetime

Это дает следующую ошибку:

Msg 242, Уровень 16, Состояние 3, Строка 4
преобразование varchar типа данных в тип данных datetime в результате вне диапазона значение.

мой вопрос в том, как SQL Server решает, какой формат использовать для неявного преобразования datetime?

3 ответов


это может зависеть от различных факторов - региональных настроек операционной системы, языка текущего пользователя и параметров dateformat. По умолчанию, Windows использует US English и настройки US English и MDY.

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

пользователь использует настройки английского языка:

-- works:
SET LANGUAGE BRITISH;
SELECT CONVERT(DATETIME, '30-04-2012 19:01:45');

-- fails:
SELECT CONVERT(DATETIME, '04/13/2012');
GO

(ошибка)

Msg 242, Уровень 16, Состояние 3, Строка 5
преобразование a данных varchar тип в тип данных datetime в результате вне диапазона значение.

пользователь использует Français:

-- works:
SET LANGUAGE FRENCH;
SELECT CONVERT(DATETIME, '30-04-2012 19:01:45');

-- fails:
SELECT CONVERT(DATETIME, '04/13/2012');
GO

(ошибка)

Msg 242, Уровень 16, Состояние 3, Строка 1
La преобразование d'un type de données varchar en type de données datetime a créé une valeur hors по limites.

пользователь снова использует Français:

SET LANGUAGE FRENCH;

-- fails (proving that, contrary to popular belief, YYYY-MM-DD is not always safe):
SELECT CONVERT(DATETIME, '2012-04-30');
GO

(ошибка)

Msg 242, Уровень 16, Состояние 3, строка 1
La преобразование d'un type de données varchar en type de données datetime a créé une valeur hors limites.

пользователь использует DMY вместо MDY:

SET LANGUAGE ENGLISH;
SET DATEFORMAT DMY;

-- works:
SELECT CONVERT(DATETIME, '30-04-2012 19:01:45');

-- fails:
SELECT CONVERT(DATETIME, '04-30-2012');
GO

(ошибка)

Msg 242, Уровень 16, Состояние 3, Строка 2
преобразование varchar типа данных в тип данных datetime в результате вне диапазона значение.

ваш лучший выбор, всегда, использовать стандарт ИСО, не-региональный, безопасный, однозначные форматы дат. Два, которые я обычно рекомендую:

YYYYMMDD                  - for date only.
YYYY-MM-DDTHH:MM:SS[.mmm] - for date + time, and yes that T is important.

ни один из них не терпит неудачу:

SET DATEFORMAT MDY;
SET LANGUAGE ENGLISH;
SELECT CONVERT(DATETIME, '20120430');
SELECT CONVERT(DATETIME, '2012-04-30T19:01:45');
SET LANGUAGE FRENCH;
SELECT CONVERT(DATETIME, '20120430');
SELECT CONVERT(DATETIME, '2012-04-30T19:01:45');
SET LANGUAGE BRITISH;
SELECT CONVERT(DATETIME, '20120430');
SELECT CONVERT(DATETIME, '2012-04-30T19:01:45');
SET DATEFORMAT DMY;
SELECT CONVERT(DATETIME, '20120430');
SELECT CONVERT(DATETIME, '2012-04-30T19:01:45');

поэтому я настоятельно рекомендую вместо того, чтобы позволять пользователям вводить форматы даты свободного текста (или использовать ненадежные форматы самостоятельно), контролировать входные строки и убедиться, что они придерживаются одного из этих безопасных форматов. Тогда не будет иметь значения, какие настройки у пользователя есть или каковы основные региональные настройки, ваши даты всегда будут интерпретироваться как они должны были быть датами. Если вы разрешаете пользователям вводить даты в текстовое поле формы, прекратите это делать и реализуйте элемент управления calendar или, по крайней мере, список выбора, чтобы в конечном итоге можно было управлять строковым форматом, возвращаемым SQL Server.

для некоторого фона, пожалуйста, прочитайте Тибора Карасци "окончательное руководство по типам данных datetime" и мой пост "вредные привычки, чтобы пнуть: Mis-обработка запросов даты / диапазона."


по умолчанию формат даты для SQL server находится в формате даты США MM/DD / YY, если не установлена локализованная версия SQL Server. Этот параметр подходит для случаев, когда приложение, требующее этого функциональность развертывается таким образом, чтобы гарантировать использование дат и вставляется в том же формате на всех платформах и местах где используется приложение.

однако в некоторых случаях дата должна быть в DD / MM/YY формат, потому что многие страны / регионы используют этот формат, а не дефолт США MM/DD / YY. Особенно это касается международных заявок они распространены по всему миру.

источник

Итак, вам нужно установить формат даты перед рукой так:

SET DATEFORMAT dmy
GO

и тогда ваш запрос будет работать.


вы также можете изменить формат даты по умолчанию для каждого входа и / или для каждого будущего добавленного входа (без необходимости делать "SET DATEFORMAT" в каждом сеансе.

вы идете в SQL Management Studio / Security / логины. Справа-clic логин, затем Свойства. Вы увидите "язык по умолчанию" в нижней части.

Если вы хотите убедиться, что любые логины, добавленные в будущем, получат "хороший" язык. Щелкните правой кнопкой мыши корень сервера, затем Свойства и расширенную страницу. Есть опция "язык по умолчанию" там тоже используется для вновь созданных Логинов.