Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Comparando datas armazenadas como varchar


Armazenar valores de data como varchar é simplesmente errado.

Se possível, você deve alterar a tabela para armazená-los como tipo de dados de data.
Você pode fazer isso em algumas etapas simples:

  1. Renomeie as colunas atuais (suponho que ScheduleStartDate também seja varchar) para columnName_old. Isso pode ser feito facilmente usando sp_rename .

  2. Use alter table para adicionar as colunas com o tipo de dados apropriado.
  3. Copie os valores das colunas antigas para as novas colunas usando uma instrução de atualização. Como todas as datas são armazenadas no mesmo formato, você pode usar convert assim:set ScheduleStartDate = convert(date, NULLIF(ltrim(rtrim(ScheduleStartDate_old)), ''), 103) Se a versão do seu servidor sql for 2012 ou superior, use try_convert . Observe que usei o nullif , ltrim e rtrim para converter valores que contêm apenas espaços em branco para nulos.
  4. Elimine e recrie índices que fazem referência a essas colunas. A maneira mais simples de fazer isso é clicar com o botão direito do mouse no índice no SSMS e escolher script index as -> drop and create .
  5. Usar alter table para remover as colunas antigas.

Observação: se essas colunas estiverem sendo referenciadas em quaisquer outros objetos no banco de dados, você também terá que alterar esses objetos. Isso inclui procedimentos armazenados, chaves estrangeiras, etc.

Se você não puder alterar os tipos de dados das colunas, e sua versão do sql server é inferior a 2012, você precisa usar convert assim:
SELECT * FROM tblServiceUsersSchedule 
WHERE CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103) 
      < CAST(GETDATE() As Date);
AND ScheduleEndDate IS NOT NULL

Observe que, se você tiver uma única linha em que os dados da coluna não estejam no formato dd/MM/aaaa, isso gerará um erro.

Para versões do sql server 2012 ou superior, use Try_convert . Esta função simplesmente retornará null se a conversão falhar:
SELECT * FROM tblServiceUsersSchedule 
WHERE TRY_CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103)
      < CAST(GETDATE() As Date);
AND ScheduleEndDate IS NOT NULL

Observação: Eu usei CAST(GETDATE() as Date) para remover a parte da hora da data atual. Isso significa que você só obterá registros onde o ScheduleEndDate tem pelo menos um dia. Se você quiser também obter os registros onde o ScheduleEndDate é hoje, use <= em vez de < .

Uma última coisa: Usar funções em colunas na cláusula where impedirá o Sql Server de usar qualquer indexação nessas colunas.
Esta é mais uma razão pela qual você deve alterar suas colunas para o tipo de dados apropriado.