2012-05-01 9 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 

Questo sta dando seguente errore:In che modo SQL Server decide il formato per la conversione datetime implicita?

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.

mia domanda è come SQL Server decide quale formato da utilizzare per la conversione datetime implicita?

risposta

23

Questo può dipendere da una varietà di fattori: le impostazioni regionali del sistema operativo, la lingua dell'utente corrente e le impostazioni del dataformat. Per impostazione predefinita, Windows utilizza US English e le impostazioni dell'utente sono US English e MDY.

Ma qui ci sono alcuni esempi per mostrare come questo può cambiare.

utente sta utilizzando le impostazioni della lingua 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.

utente sta utilizzando 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.

utente è di nuovo usando 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.

utente sta utilizzando DMY invece di 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.

La tua migliore scommessa, sempre, è quella di utilizzare formati di data ISO standard, non regionali, sicuri e non ambigui. I due Io di solito raccomando sono:

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

Nessuno di questi venga meno

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

Perciò, vi raccomando vivamente che, invece di lasciare che gli utenti digitano nei liberi formati di data testo (o di utilizzare i formati inaffidabili te), controlla le stringhe di input e assicurati che aderiscano a uno di questi formati sicuri. Quindi non importa quali siano le impostazioni dell'utente o quali siano le impostazioni regionali sottostanti, le tue date saranno sempre interpretate come le date che avrebbero dovuto essere.Se attualmente si lascia che gli utenti inseriscano le date in un campo di testo in un modulo, smettere di farlo e implementare un controllo del calendario o almeno un elenco di selezione in modo da poter controllare in ultima analisi il formato stringa che viene passato a SQL Server.

Per alcuni sfondo, si prega di leggere di "The ultimate guide to the datetime datatypes" Tibor Karaszi e il mio post "Bad Habits to Kick : Mis-handling date/range queries."

+0

Vedere la mia risposta [qui] (http://stackoverflow.com/a/23369706/2108149) come farlo all'interno di una funzione definita dall'utente. –

+2

@Eli Penso che manchi il punto che stavo cercando di fare. Se una persona è in Inghilterra e passa una stringa '09/04/2014 'e un'altra persona è negli Stati Uniti e passa '09/04/2014', come fa la tua funzione magicamente a sapere quale di loro intendeva il 9 aprile e quale significava il 4 settembre? –

+0

Devo ammettere che non ho letto tutto il thread, stavo cercando una soluzione di traduzione di un mese e mentre cercavo mi sono imbattuto nella tua risposta, quindi ho pensato che alcune persone potrebbero trovare utile ... –

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

Quindi è quello che dovete fare è impostare il formato della data di prima mano come così:

SET DATEFORMAT dmy 
GO 

E poi la query funzionerà.

+0

... fino a quando qualcuno non utilizza un formato diverso. –

+1

@AaronBertrand corretto. Ci sono approcci infallibili per gestire questo su SQL? Voglio dire, ricevere una stringa che rappresenta una data su qualsiasi formato e fare la conversione in modo sicuro, senza alcuna logica cattiva? – Icarus

+1

No, non c'è. È necessario controllare la stringa di input. Se un utente passa '05/06/2012', perché gli è stato permesso di digitarlo in qualsiasi formato desiderato, in che modo SQL Server può determinare in modo affidabile se l'utente intendeva il 6 maggio o il 5 giugno? –

1

È anche possibile modificare de formato data di default per ogni account di accesso e/o per ogni futura login aggiunto (senza le necessità di fare "SET DATEFORMAT" in ogni sessione.

si va in SQL Management Studio/Sicurezza/Account di accesso. fare clic l'accesso, quindi Proprietà. si vedrà "Lingua" nella parte inferiore.

Se si vuole fare in modo qualsiasi gli accessi aggiunti in futuro ottengono la "buona" lingua. Fai clic con il tasto destro del mouse sulla root del server, quindi su Proprietà e pagina Avanzate. Esiste anche un'opzione "Lingua predefinita" che viene utilizzata per gli accessi appena creati.

+0

tu non dovrei solo commentare "grazie" qui .... ma ho bisogno di, quindi: grazie. – Steen

Problemi correlati