Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Risoluzione dei problemi relativi all'utilizzo di data e ora in SQL Server

Il database di Microsoft SQL Server archivia le informazioni su data e ora in diversi formati. I più comuni sono DateTime , DataOra2 e Data . Come accade con tutti i tipi di dati, i problemi possono verificarsi di volta in volta. In questo articolo, ci concentreremo sulla risoluzione di alcuni dei problemi più comuni che potresti incontrare mentre lavori con i tipi di dati di ora e data SQL.

Problemi relativi a formati di data diversi a livello regionale

Il formato delle date varia a livello globale. Ad esempio, gli inglesi scrivono le date come gg-mm-aaaa, mentre gli americani scrivono le date nel formato mm-gg-aaaa. In questo modo, la stessa data, 31 dicembre 2020, viene scritta come 31-12-2020 nel formato data britannico e come 31-12-2020 nel formato americano.

Potrebbero sorgere problemi di impossibilità se non specifichi la data in un formato corrispondente alle impostazioni della lingua della tua istanza di SQL Server.

Lo script seguente converte la stringa di testo con le informazioni sulla data nel formato DATETIME. Le impostazioni della lingua sono impostate su BRITISH. La stringa di testo contiene 31-12-2020 04:25:30 .

Se esegui il cast di questa stringa nel formato DATETIME, 31 verrà considerato come giorno, mentre 12 sarà mese per impostazione predefinita. Quindi, la conversione avrà esito positivo come mostrato dall'output:

SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '31-12-2020 04:25:30';
SELECT CAST(@date AS DATETIME);

Tuttavia, se provi a convertire la stringa contenente la data 31-12-2020 nel formato DATETIME utilizzando US_ENGLISH impostazioni della lingua, riceverai un errore come mostrato di seguito:

SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '31-12-2020 04:25:30';
SELECT CAST(@date AS DATETIME);

L'errore si verifica perché le impostazioni della lingua US_ENGLISH definiscono 31 come un mese invece che un giorno. Come il mese il valore non può essere maggiore di 12, stiamo ricevendo l'errore di valore fuori intervallo .

Se specifichi la data come 31-12-2020 e poi converti la stringa della data in DATETIME utilizzando le impostazioni US_ENGLISH, vedrai la conversione riuscita:

SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '12-31-2020 04:25:30';
SELECT CAST(@date AS DATETIME);

Allo stesso modo, la conversione del 31-12-2020 anche la stringa della data nell'impostazione della lingua BRITANNICA causa un errore:31 è considerato un mese, non può essere.

SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '12-31-2020 04:25:30';
SELECT CAST(@date AS DATETIME);

Per convertire la data in modo accurato indipendentemente dalle impostazioni della lingua, puoi utilizzare lo standard ISO 8601 per il formato della data. Per rispettare questo standard, specifica la data come aaaa-mm-ggThh:mm:ss .

Ad esempio, la stringa di data 2020-12-31T04:25:30 è stata convertita correttamente nel tipo di dati DATETIME nelle impostazioni della lingua BRITANNICA:

SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '2020-12-31T04:25:30';
SELECT CAST(@date AS DATETIME);

Lo script seguente mostra la stessa stringa convertita in DATETIME con le impostazioni US_ENGLISH:

SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '2020-12-31T04:25:30';
SELECT CAST(@date AS DATETIME);

Considerazioni sul fuso orario

Potresti voler sviluppare alcune applicazioni di database di SQL Server per il pubblico globale. Potrebbe essere necessario aggiungere le informazioni sul fuso orario ai tipi di dati di data e ora.

In SQL Server il tipo di dati DATETIMEOFFSET archivia le informazioni sulla data e l'ora insieme all'offset del fuso orario. L'offset del fuso orario è specificato come UTC +/- numero di ore.

Ad esempio, lo script seguente utilizza il metodo SYSDATETIMEOFFSET() per ottenere la data, l'ora e le informazioni sull'offset del sistema che esegue l'istanza di SQL Server. I valori restituiti dalla funzione SYSDATETIMEOFFSET() sono memorizzati nella variabile di tipo DATETIMEOFFSET @dateoffset. Il valore della variabile @dateoffset viene stampato utilizzando l'istruzione SELECT:

DECLARE @dateoffset DATETIMEOFFSET = SYSDATETIMEOFFSET();
SELECT @dateoffset

L'output seguente mostra la data e l'ora correnti e il valore di offset. In questo caso, sono +02:00.

È inoltre possibile ottenere solo il valore di offset dalla variabile DATETIMEOFFSET. Per fare ciò, è necessario passare la variabile di tipo DATETIMEOFFSET come secondo valore del parametro alla funzione DATENAME(). Il primo parametro del metodo DATENAME() dovrebbe essere tzoffset .

Lo script seguente restituisce la parte di offset dell'ora della data di sistema corrente:

DECLARE @dateoffset DATETIMEOFFSET = SYSDATETIMEOFFSET();
SELECT DATENAME(tzoffset, @dateoffset)

Per creare una variabile DATETIMEOFFSET personalizzata, specificare i valori per le parti di data, ora e offset dell'ora. Ad esempio, nello script seguente, il valore per la data è il 22-02-2015 , il valore per la parte temporale è 23:59:59:999 e il valore di offset temporale è +05:00 .

DECLARE @dateoffset DATETIMEOFFSET = '2015-02-22 23:59:59:999 +05:00';
SELECT @dateoffset

Infine, puoi anche aggiornare le informazioni sulla differenza di orario utilizzando SWITCHOFFSET() funzione.

Devi superare il DATETIMEOFFSET digitare variabile come primo valore di parametro e passare il nuovo offset di tempo come secondo valore di parametro a SWITCHOFFSET funzione.

Lo script seguente aggiorna il valore di offset dell'ora per la variabile DATETIMEOFFSET da +05:00 a +09:00.

DECLARE @dateoffset DATETIMEOFFSET = '2015-02-22 23:59:59:999 +05:00';
SELECT SWITCHOFFSET(@dateoffset, '+09:00');

Selezione dei record utilizzando BETWEEN Operator con DateTime

Il TRA l'operatore nel server SQL filtra i record tra l'intervallo di valori passati.

È possibile utilizzare l'operatore BETWEEN per restituire i record tra due date. Tuttavia, dovresti prestare molta attenzione mentre lo usi per filtrare i record con le date.

Ad esempio, il seguente script crea un Ostello fittizio database e aggiunge uno Studente tavolo ad esso.

CREATE DATABASE Hostel

USE Hostel
CREATE TABLE Student

(
Id INT PRIMARY KEY IDENTITY(1,1),
Name VARCHAR (50) NOT NULL,
Gender VARCHAR (50),
BirthDate DateTime
)

Lo script successivo aggiunge alcuni record fittizi allo Studente tavolo. La data di nascita colonna dello Studente la tabella memorizza le date. Da questo copione, puoi vedere che due studenti Sara e Nik hanno le stesse date di nascita. Tuttavia, l'ora della nascita è diversa:

INSERT INTO Student
VALUES ('Jack', 'Male', '2017-06-30 16:30:35'),
('Sara', 'Female', '2015-02-22 00:00:00'),
('Elisa', 'Female',  '2020-03-16 22:24:39'),
('Nik', 'Male',  '2015-02-22 09:45:55'),
('Jos', 'Male',  '2015-03-25 11:55:20')

Si potrebbe pensare che BETWEEN operator possa essere utilizzato per recuperare i record di tutti gli studenti nati il ​​22-02-2015.

SELECT * FROM Student
WHERE BirthDate BETWEEN '2015-02-22' AND '2015-02-22'

Ma se esegui lo script precedente, vedrai che viene restituito un solo record, nonostante il tempo parte è incluso anche.

Il motivo è che l'operatore BETWEEN tratta per impostazione predefinita il valore DATETIME di 22-02-2015 come 22-02-2015 00:00:00 . Pertanto, l'operatore BETWEEN nella query precedente ha cercato i record con BirthDate valore tra il 22-02-2015 00:00:00 e il 22-02-2015 00:00:00 .

Per risolvere questo problema, dobbiamo specificare la parte temporale quando si utilizza l'operatore BETWEEN con il tipo di dati DATETIME.

Il seguente script restituirà tutti i record tra il 22-02-2015 00:00:00 e 22-02-2015 23:59:59:999 . La parte di tempo per il limite di data superiore è 23:59:999.

SELECT * FROM Student
WHERE BirthDate BETWEEN '2015-02-22' AND '2015-02-22 23:59:59:999';

Nell'output, otteniamo due record per il BirthDate 22-02-2015 .

Problemi relativi agli intervalli di date

Il tipo di dati DATETIME supporta solo gli anni dal 1753 al 9999. Pertanto, se tenti di memorizzare una data con un valore dell'anno maggiore di 9999 o minore di 1753, visualizzerai un errore.

Il seguente script tenta di convertire il 1392-12-31 stringa di data. 1392 è ​​minore di 1753. Quindi, abbiamo l'errore di valore fuori intervallo.

DECLARE @date VARCHAR(50) = '1392-12-31 04:25:30';
SELECT CAST(@date AS DATETIME);

Per memorizzare i valori dell'anno meno di 1753 , puoi utilizzare DATETIME2 tipo di dati. Memorizza i valori dell'anno da 0000 a 9999.

Lo script seguente converte correttamente la stringa di data 1392-12-31 nel tipo di dati DATETIME2:

DECLARE @date VARCHAR(50) = '1392-12-31 04:25:30';
SELECT CAST(@date AS DATETIME2);

Utilizzo di TRY_COVERT per la conversione DateTime

La funzione CONVERT in SQL Server converte i dati da un tipo a un altro. Puoi usarlo per convertire i formati di dati di tipo data in altri formati e viceversa. Tuttavia, se la conversione non riesce, la funzione CONVERT genera un errore.

Ad esempio, stiamo convertendo la stringa 2015-31-31 nel formato DATETIME:

DECLARE @date VARCHAR(50) = '2015-31-13';
SELECT  CONVERT(DATETIME, @date ,105) as DOB_CONV

Se desideri che venga restituito un valore NULL quando la conversione non riesce invece del messaggio di errore, utilizza TRY_CONVERT funzione. Questo metodo non consente l'arresto anomalo dell'applicazione:restituisce semplicemente un valore NULL.

DECLARE @date VARCHAR(50) = '2015-31-13';

SELECT  TRY_CONVERT(DATETIME, @date ,105) as DOB_CONV

Conclusione

Lavorando con SQL Server, potresti dover affrontare molti problemi che rovinano la tua esperienza e complicano le attività. Conoscere i problemi più comuni è, d'altra parte, il metodo più efficace per prevenirli. Ecco perché abbiamo dedicato questo articolo alla risoluzione dei problemi di tali inconvenienti che potrebbero verificarsi durante il tuo lavoro con le informazioni su date e orari.

Si noti inoltre che gli strumenti moderni per l'utilizzo dei database di SQL Server possono semplificare notevolmente la vita degli specialisti di database. In particolare, dbForge Studio per SQL Server fornisce la funzionalità di Visual Data Editor da applicare quando si tratta di date. Puoi usarlo per visualizzare e modificare le date nel modo più intuitivo.