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

Resolución de problemas al trabajar con fecha y hora en SQL Server

La base de datos de Microsoft SQL Server almacena la información de fecha y hora en una variedad de formatos. Los más comunes son DateTime , FechaHora2 y Fecha . Como sucede con todo tipo de datos, los problemas pueden ocurrir una y otra vez. En este artículo, nos centraremos en la solución de algunos de los problemas más comunes que puede enfrentar al trabajar con los tipos de datos de hora y fecha de SQL.

Problemas relacionados con diferentes formatos de fecha regionales

El formato de las fechas varía globalmente. Por ejemplo, los británicos escriben las fechas como dd-mm-aaaa, mientras que los estadounidenses escriben las fechas en el formato mm-dd-aaaa. De esta forma, la misma fecha, 31 de diciembre de 2020, se escribe como 31-12-2020 en el formato de fecha británico y como 31-12-2020 en el formato americano.

Pueden surgir problemas de incapacidad si no especifica la fecha en un formato correspondiente a la configuración de idioma de su instancia de SQL Server.

El siguiente script convierte la cadena de texto con la información de la fecha al formato DATETIME. La configuración de idioma está establecida en BRITÁNICO. La cadena de texto contiene 31-12-2020 04:25:30 .

Si convierte esta cadena en el formato DATETIME, el 31 se tratará como un día, mientras que el 12 será un mes de forma predeterminada. Por lo tanto, la conversión será exitosa como se muestra en el resultado:

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

Sin embargo, si intenta convertir la cadena que contiene la fecha 31-12-2020 al formato DATETIME usando el US_ENGLISH configuración de idioma, recibirá un error como se muestra a continuación:

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

El error ocurre porque la configuración de idioma US_ENGLISH define 31 como un mes en lugar de un día. Como el mes el valor no puede ser mayor que 12, estamos recibiendo el error de valor fuera de rango .

Si especifica la fecha como 31-12-2020 y luego convierte la cadena de fecha a DATETIME usando la configuración US_ENGLISH, verá la conversión exitosa:

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

Del mismo modo, convertir el 31-12-2020 La cadena de fecha en la configuración de idioma BRITÁNICO también provoca un error:31 se trata como un mes, eso no puede ser.

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

Para convertir su fecha con precisión, independientemente de la configuración de idioma, puede utilizar el estándar ISO 8601 para el formato de fecha. Para cumplir con este estándar, especifique la fecha como yyyy-mm-ddThh:mm:ss .

Por ejemplo, la cadena de fecha 2020-12-31T04:25:30 se convierte correctamente al tipo de datos DATETIME en la configuración de idioma BRITÁNICO:

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

El siguiente script muestra la misma cadena convertida a DATETIME con la configuración US_ENGLISH:

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

Consideraciones sobre la zona horaria

Es posible que desee desarrollar algunas aplicaciones de base de datos de SQL Server para la audiencia global. Para eso, es posible que deba agregar la información de la zona horaria a los tipos de datos de fecha y hora.

En SQL Server, el tipo de datos DATETIMEOFFSET almacena la información de fecha y hora junto con el desplazamiento de la zona horaria. El desplazamiento de la zona horaria se especifica como UTC +/- número de horas.

Por ejemplo, la siguiente secuencia de comandos utiliza el método SYSDATETIMEOFFSET() para obtener la fecha, la hora y la información de compensación del sistema que ejecuta su instancia de SQL Server. Los valores devueltos por la función SYSDATETIMEOFFSET() se almacenan en la variable de tipo DATETIMEOFFSET @dateoffset. El valor de la variable @dateoffset se imprime utilizando la sentencia SELECT:

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

El siguiente resultado muestra la fecha y hora actuales y el valor de compensación. En este caso, son las +02:00.

También puede obtener solo el valor de compensación de la variable DATETIMEOFFSET. Para hacerlo, debe pasar la variable de tipo DATETIMEOFFSET como segundo valor del parámetro a la función DATENAME(). El primer parámetro del método DATENAME() debería ser tzoffset .

La siguiente secuencia de comandos devuelve la parte de compensación de tiempo de la fecha actual del sistema:

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

Para crear una variable DATETIMEOFFSET personalizada, especifique valores para las porciones de fecha, hora y compensación horaria. Por ejemplo, en el siguiente script, el valor de la fecha es 2015-02-22 , el valor de la porción de tiempo es 23:59:59:999 y el valor de compensación de tiempo es +05:00 .

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

Finalmente, también puede actualizar la información de compensación de tiempo usando SWITCHOFFSET() función.

Debe pasar el DATETIMEOFFSET escriba variable como primer valor de parámetro y pase el nuevo desplazamiento de tiempo como segundo valor de parámetro a SWITCHOFFSET función.

El siguiente script actualiza el valor de compensación de tiempo para la variable DATETIMEOFFSET de +05:00 a +09:00.

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

Seleccionar registros utilizando el operador BETWEEN con DateTime

El ENTRE El operador en el servidor SQL filtra los registros entre el rango de valores que se le pasan.

Puede utilizar el operador BETWEEN para devolver registros entre dos fechas. Sin embargo, debe tener mucho cuidado al usarlo para filtrar registros con fechas.

Por ejemplo, la siguiente secuencia de comandos crea un Hostal ficticio base de datos y agrega un Estudiante mesa a ella.

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
)

El siguiente script agrega algunos registros ficticios al Estudiante mesa. La fecha de nacimiento columna del Estudiante la tabla almacena fechas. A partir de este guión, puede ver que dos estudiantes, Sara y Nik, tienen las mismas fechas de nacimiento. Sin embargo, la hora de nacimiento es diferente:

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

Se podría pensar que el operador BETWEEN podría usarse para recuperar los registros de todos los estudiantes nacidos el 22-02-2015.

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

Pero si ejecuta el script anterior, verá que solo se devuelve un registro, a pesar del tiempo parte también está incluido.

El motivo es que el operador BETWEEN trata de forma predeterminada el valor DATETIME de 2015-02-22 como 2015-02-22 00:00:00 . Por lo tanto, el operador BETWEEN en la consulta anterior buscó los registros con la Fecha de nacimiento valor entre 2015-02-22 00:00:00 y 2015-02-22 00:00:00 .

Para resolver este problema, debemos especificar la porción de tiempo cuando usamos el operador BETWEEN con el tipo de datos DATETIME.

El siguiente script devolverá todos los registros entre 2015-02-22 00:00:00 y 2015-02-22 23:59:59:999 . La porción de tiempo para el límite de fecha superior es 23:59:999.

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

En el resultado, obtenemos dos registros para Fecha de nacimiento 2015-02-22 .

Problemas relacionados con los intervalos de fechas

El tipo de datos DATETIME solo admite los años 1753 a 9999. Por lo tanto, si intenta almacenar una fecha con un valor de año mayor que 9999 o menor que 1753, obtendrá un error.

El siguiente script intenta convertir el 1392-12-31 cadena de fecha. 1392 es menor que 1753. Por lo tanto, tenemos el error de valor fuera de rango.

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

Para almacenar valores de años menos de 1753 , puede usar el DATETIME2 tipo de datos. Almacena valores de año desde 0000 hasta 9999.

El siguiente script convierte con éxito la cadena de fecha 1392-12-31 al tipo de datos DATETIME2:

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

Uso de TRY_COVERT para la conversión de fecha y hora

La función CONVERTIR en SQL Server convierte los datos de un tipo a otro. Puede usarlo para convertir los formatos de datos de tipo fecha a otros formatos y viceversa. Sin embargo, si la conversión falla, la función CONVERTIR arroja un error.

Por ejemplo, estamos convirtiendo la cadena 2015-31-31 al formato DATETIME:

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

Si desea que se devuelva un valor NULL cuando falla la conversión en lugar del mensaje de error, use TRY_CONVERT función. Este método no permitirá que la aplicación se bloquee, simplemente devuelve un valor NULL.

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

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

Conclusión

Al trabajar con SQL Server, es posible que enfrente muchos problemas que estropeen su experiencia y compliquen las tareas. Conocer los problemas más comunes es, por otro lado, el método más eficaz para evitar que sucedan. Es por eso que dedicamos este artículo a solucionar los inconvenientes que puedan ocurrir durante su trabajo con la información sobre fechas y horas.

Tenga en cuenta también que las herramientas modernas para trabajar con bases de datos de SQL Server pueden simplificar mucho la vida de los especialistas en bases de datos. En particular, dbForge Studio para SQL Server proporciona la función Editor de datos visuales para aplicar cuando se trata de fechas. Puede usarlo para ver y editar las fechas de la manera más fácil de usar.