sql >> Base de Datos >  >> RDS >> Sqlserver

Comparando fechas almacenadas como varchar

Almacenar valores de fecha como varchar es simplemente incorrecto.

Si es posible, debe modificar la tabla para almacenarlos como tipo de datos de fecha.
Puede hacerlo en unos simples pasos:

  1. Cambie el nombre de las columnas actuales (supongo que ScheduleStartDate también es varchar) a columnName_old. Esto se puede hacer fácilmente usando sp_rename .

  2. Usar alter table para agregar las columnas con el tipo de datos apropiado.

  3. Copie los valores de las columnas antiguas a las columnas nuevas usando una declaración de actualización. Dado que todas las fechas se almacenan en el mismo formato, puede usar convert así:set ScheduleStartDate = convert(date, NULLIF(ltrim(rtrim(ScheduleStartDate_old)), ''), 103) Si la versión de su servidor sql es 2012 o superior, use try_convert . Tenga en cuenta que he usado nullif , ltrim y rtrim para convertir valores que solo contienen espacios en blanco en nulos.
  4. Elimine y vuelva a crear índices que hagan referencia a estas columnas. La forma más sencilla de hacerlo es haciendo clic con el botón derecho en el índice de SSMS y seleccionando script index as. -> drop and create .
  5. Usar alter table para eliminar las columnas antiguas.

Nota: si se hace referencia a estas columnas en cualquier otro objeto de la base de datos, también tendrá que cambiar estos objetos. Esto incluye procedimientos almacenados, claves foráneas, etc.

Si no puede cambiar los tipos de datos de las columnas, y la versión de su servidor sql es anterior a 2012, necesita usar convertir así:

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

Tenga en cuenta que si tiene una sola fila en la que los datos de la columna no están en formato dd/MM/aaaa, esto generará un error.

Para versiones de servidor sql 2012 o superiores, use Try_convert . Esta función simplemente devolverá un valor nulo si falla la conversión:

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

Nota: He usado CAST(GETDATE() as Date) para eliminar la parte de la hora de la fecha actual. Esto significa que solo obtendrá registros donde ScheduleEndDate tiene al menos un día. Si también desea obtener los registros donde ScheduleEndDate es hoy, usa <= en lugar de < .

Una última cosa: El uso de funciones en las columnas en la cláusula where evitará que Sql Server use cualquier indexación en estas columnas.
Esta es otra razón más por la que debe cambiar sus columnas al tipo de datos apropiado.