2012-05-01 12 views
14
declare @str_datetime varchar(50) 
set @str_datetime='30-04-2012 19:01:45' -- 30th April 2012 
declare @dt_datetime datetime 
select @[email protected]_datetime 

Esto está dando siguiente error:¿Cómo decide SQL Server el formato para la conversión implícita de fecha y hora?

Msg 242, Level 16, State 3, Line 4
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.

Mi pregunta es cómo SQL Server decide qué formato utilizar para la conversión de fecha y hora implícita?

Respuesta

23

Esto puede depender de una variedad de factores: la configuración regional del sistema operativo, el idioma del usuario actual y la configuración del formato de la fecha. De forma predeterminada, Windows usa US English, y la configuración del usuario es US English y MDY.

Pero aquí hay algunos ejemplos para mostrar cómo esto puede cambiar.

usuario está utilizando la configuración de idioma: BRITISH

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

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

(error)

Msg 242, Level 16, State 3, Line 5
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.

usuario está utilizando Français:

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

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

(error)

Msg 242, Level 16, State 3, Line 1
La conversion d'un type de données varchar en type de données datetime a créé une valeur hors limites.

usuario está de nuevo utilizando 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 

(Error)

Msg 242, Level 16, State 3, Line 1
La conversion d'un type de données varchar en type de données datetime a créé une valeur hors limites.

usuario está utilizando DMY en lugar de 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 

(Error)

Msg 242, Level 16, State 3, Line 2
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.

Su mejor opción, siempre, es utilizar formatos de fecha estándar ISO, no regionales, seguros y sin ambigüedades. Los dos Generalmente, recomiendo son:

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

Ninguno de estos fallan:

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'); 

Por lo tanto, le recomiendo que en vez de dejar que los usuarios escriben en los formatos de fecha de texto libre (o que utilice formatos poco fiables yourself), controle sus cadenas de entrada y asegúrese de que se adhieran a uno de estos formatos seguros. Entonces no importará qué configuraciones tenga el usuario o cuáles sean las configuraciones regionales subyacentes, sus fechas siempre serán interpretadas como las fechas en que estaban destinadas a ser.Si actualmente permite que los usuarios ingresen fechas en un campo de texto en un formulario, deje de hacerlo e implemente un control de calendario o, al menos, una lista de selección para poder controlar finalmente el formato de cadena que se transfiere a SQL Server.

Para algunos antecedentes, lea de "The ultimate guide to the datetime datatypes" Tibor Karaszi y mi post "Bad Habits to Kick : Mis-handling date/range queries."

+0

Vea mi respuesta [aquí] (http://stackoverflow.com/a/23369706/2108149) cómo hacerlo dentro de una función definida por el usuario. –

+2

@Eli Creo que te estás perdiendo el punto que estaba tratando de hacer. Si una persona está en Inglaterra y pasa una cadena '09/04/2014 'y otra persona está en los EE. UU. Y aprueba '09/04/2014', ¿cómo sabe mágicamente su función cuál de ellas significaba el 9 de abril y cuál? significaba el 4 de septiembre? –

+0

Debo admitir que no leí todo el hilo, estaba buscando una solución de traducción de un mes y mientras la buscaba me encontré con su respuesta, por lo que pensé que algunas personas podrían encontrarla útil ... –

1

By default, the date format for SQL server is in U.S. date format MM/DD/YY, unless a localized version of SQL Server has been installed. This setting is fine for cases when an application that requires this functionality is deployed in a manner guaranteeing that dates are used and inserted in the same format across all platforms and locations where the application is used.

However, in some cases the date must be in a DD/MM/YY format because many countries/regions use this format rather than the U.S. default of MM/DD/YY. This is especially an issue for international applications that are distributed all over the world.

Source

Así que lo que hay que hacer es configurar el formato de fecha antes de la mano como tan:

SET DATEFORMAT dmy 
GO 

Y a continuación, la consulta va a funcionar.

+0

... hasta que alguien use un formato diferente. –

+1

@AaronBertrand Correcto. ¿Hay algún enfoque infalible para manejar esto en SQL? Quiero decir, recibir una cadena que representa una fecha en cualquier formato y hacer la conversión de forma segura, sin ninguna lógica desagradable? – Icarus

+1

No, no hay. Necesitas controlar la cadena de entrada. Si un usuario pasa el 05/06/2012, porque se les permitió escribirlo en el formato que quisieran, ¿cómo puede SQL Server determinar de manera confiable si el usuario quiso decir el 6 de mayo o el 5 de junio? –

1

También puede cambiar de formato de fecha por defecto para cada inicio de sesión y/o para cada futura añadido inicios de sesión (sin las necesidades que se pueden hacer "SET DATEFORMAT" en cada sesión.

uno va en SQL Management Studio/Seguridad/inicios de sesión. haga clic en el inicio de sesión, a continuación, en Propiedades. usted verá "idioma predeterminado" en la parte inferior.

Si desea asegurarse de que cualquier los inicios de sesión agregados en el futuro obtienen el idioma "bueno". Haces clic derecho en la raíz del servidor, luego en la página Propiedades y Avanzado. Hay una opción "Default Language" allí también que se usa para inicios de sesión recién creados.

+0

no debería simplemente comentar "gracias" aquí ... pero necesito hacerlo, así que: gracias. – Steen

Cuestiones relacionadas