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

Confronto delle date memorizzate come varchar

Memorizzare i valori della data come varchar è semplicemente sbagliato.

Se possibile, dovresti modificare la tabella per memorizzarli come tipo di dati di data.
Puoi farlo in pochi semplici passaggi:

  1. Rinomina le colonne correnti (suppongo che anche ScheduleStartDate sia varchar) in columnName_old. Questo può essere fatto facilmente usando sp_rename .

  2. Usa alter table per aggiungere le colonne con il tipo di dati appropriato.

  3. Copia i valori dalle vecchie colonne alle nuove colonne usando un'istruzione di aggiornamento. Poiché tutte le date sono memorizzate nello stesso formato, puoi utilizzare convert in questo modo:set ScheduleStartDate = convert(date, NULLIF(ltrim(rtrim(ScheduleStartDate_old)), ''), 103) Se la versione del tuo server sql è 2012 o successiva, usa try_convert . Nota che ho usato nullif , ltrim e rtrim per convertire i valori che contengono solo spazi bianchi in null.
  4. Elimina e ricrea gli indici che fanno riferimento a queste colonne. Il modo più semplice per farlo è fare clic con il pulsante destro del mouse sull'indice su SSMS e scegliere script index as -> drop and create .
  5. Usa alter table per rimuovere le vecchie colonne.

Nota: se a queste colonne viene fatto riferimento in qualsiasi altro oggetto sul database, dovrai modificare anche questi oggetti. Ciò include stored procedure, chiavi esterne, ecc.

Se non puoi modificare i tipi di dati delle colonne e la versione del tuo server sql è inferiore alla 2012, devi utilizzare convert in questo modo:

SELECT * FROM tblServiceUsersSchedule 
WHERE CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103) 
      < CAST(GETDATE() As Date);
AND ScheduleEndDate IS NOT NULL

Tieni presente che se hai anche una sola riga in cui i dati della colonna non sono nel formato gg/MM/aaaa verrà generato un errore.

Per SQL Server versioni 2012 o successive, utilizzare Try_convert . Questa funzione restituirà semplicemente null se la conversione non riesce:

SELECT * FROM tblServiceUsersSchedule 
WHERE TRY_CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103)
      < CAST(GETDATE() As Date);
AND ScheduleEndDate IS NOT NULL

Nota: Ho usato CAST(GETDATE() as Date) per rimuovere la parte temporale della data corrente. Ciò significa che otterrai solo record in cui è ScheduleEndDate ha almeno un giorno. Se vuoi ottenere anche i record in cui è ScheduleEndDate è oggi, usa <= invece di < .

Un'ultima cosa: L'utilizzo delle funzioni sulle colonne nella clausola where impedirà a SQL Server di utilizzare qualsiasi indicizzazione su queste colonne.
Questo è un altro motivo per cui dovresti modificare le colonne nel tipo di dati appropriato.