Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Отстраняване на проблеми при работа с дата и час в SQL Server

Базата данни на Microsoft SQL Server съхранява информацията за дата и час в различни формати. Най-често срещаните от тях са DateTime , Дата и час2 и Дата . Както се случва с всички видове данни, проблемите могат да възникнат от време на време. В тази статия ще се съсредоточим върху отстраняването на някои от най-често срещаните проблеми, с които може да се сблъскате, докато работите с SQL типовете данни за час и дата.

Проблеми, свързани с регионално различни формати за дата

Форматът на датите варира в световен мащаб. Например, британците пишат датите като дд-мм-гггг, докато американците пишат датите във формат мм-дд-гггг. По този начин една и съща дата, 31 декември 2020 г., се записва като 31-12-2020 в британския формат за дата и като 12-31-2020 в американския формат.

Може да възникнат проблеми с неспособността, ако не посочите датата във формат, съответстващ на езиковите настройки на вашия екземпляр на SQL Server.

Следният скрипт преобразува текстовия низ с информацията за датата във формат DATETIME. Настройките за език са зададени на BRITISH. Текстовият низ съдържа 31-12-2020 04:25:30 .

Ако прехвърлите този низ във формат DATETIME, 31 ще се третира като ден, докато 12 ще бъде месец по подразбиране. Следователно преобразуването ще бъде успешно, както е показано от изхода:

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

Ако обаче се опитате да преобразувате низа, съдържащ датата 31-12-2020 във формата DATETIME с помощта на US_ENGLISH езикови настройки, ще получите грешка, както е показано по-долу:

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

Грешката възниква, защото езиковите настройки на US_ENGLISH дефинират 31 като месец вместо ден. Като месец стойността не може да бъде по-голяма от 12, получаваме грешка за стойността извън диапазона .

Ако посочите датата като 12-31-2020 и след това преобразувате низа за дата в DATETIME с помощта на настройките US_ENGLISH, ще видите успешното преобразуване:

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

По същия начин, конвертиране на 31.12.2020 Низът за дата под настройката BRITISH език също причинява грешка – 31 се третира като месец, това не може да бъде.

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

За да преобразувате точно датата си, независимо от езиковите настройки, можете да използвате стандарта ISO 8601 за формат на датата. За да се съобразите с този стандарт, посочете датата като гггг-мм-ддЧч:мм:сс .

Например низът за дата 2020-12-31T04:25:30 се преобразува успешно в типа данни DATETIME в настройките на БРИТАНСКИЯ език:

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

Следният скрипт показва същия низ, преобразуван в DATETIME с настройките US_ENGLISH:

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

Съображения за часовата зона

Може да искате да разработите някои приложения за бази данни на SQL Server за глобалната аудитория. За това може да се наложи да добавите информацията за часовата зона към типовете данни за дата и час.

В SQL Server типът данни DATETIMEOFFSET съхранява информацията за датата и часа заедно с изместването на часовата зона. Изместването на часовата зона е посочено като UTC +/- брой часове.

Например, следният скрипт използва метода SYSDATETIMEOFFSET(), за да получи информацията за дата, час и отместване на системата, изпълняваща вашия екземпляр на SQL Server. Стойностите, върнати от функцията SYSDATETIMEOFFSET(), се съхраняват в променливата от типа DATETIMEOFFSET @dateoffset. Стойността на променливата @dateoffset се отпечатва с помощта на оператора SELECT:

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

Изходът по-долу показва текущата дата и час и стойността на отместване. В този случай това е +02:00.

Можете също да получите само стойността на отместване от променливата DATETIMEOFFSET. За да направите това, трябва да предадете променливата от типа DATETIMEOFFSET като втора стойност на параметъра на функцията DATENAME(). Първият параметър на метода DATENAME() трябва да бъде tzoffset .

Следният скрипт връща частта за отместване на времето от текущата системна дата:

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

За да създадете персонализирана променлива DATETIMEOFFSET, посочете стойности за частите за дата, час и изместване на времето. Например в следния скрипт стойността за датата е2015-02-22 , стойността за частта от време е 23:59:59:999 и стойността на изместване на времето е +05:00 .

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

И накрая, можете също да актуализирате информацията за отместването на времето с помощта на SWITCHOFFSET() функция.

Трябва да преминете DATETIMEOFFSET въведете променлива като първа стойност на параметъра и предайте новото времево отместване като стойност на втория параметър на SWITCHOFFSET функция.

Следният скрипт актуализира стойността на изместването на времето за променливата DATETIMEOFFSET от +05:00 до +09:00.

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

Избиране на записи с помощта на оператор BETWEEN с DateTime

МЕЖДУ оператор в SQL сървъра филтрира записите между диапазона от стойности, предадени към него.

Можете да използвате оператора BETWEEN, за да върнете записи между две дати. Въпреки това, трябва да бъдете особено внимателни, докато го използвате за филтриране на записи с дати.

Например следният скрипт създава фиктивно Хостел база данни и добавя единСтудент таблица към него.

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
)

Следващият скрипт добавя някои фиктивни записи към Студент маса. Дата на раждане колона на Студент таблицата съхранява дати. От този сценарий можете да видите, че две ученици Сара и Ник имат еднакви дати на раждане. Въпреки това, времето на раждане е различно:

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

Бихте си помислили, че операторът BETWEEN може да се използва за извличане на записите на всички ученици, родени на 22.02.2015.

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

Но ако изпълните горния скрипт, ще видите, че се връща само един запис, въпреки времето част също е включено.

Причината е, че операторът BETWEEN третира по подразбиране стойността DATETIME на 2015-02-22 като 2015-02-22 00:00:00 . Следователно операторът BETWEEN в горната заявка потърси записите с Дата на раждане стойност между 22.02.2015 00:00:00 и 2015-02-22 00:00:00 .

За да разрешим този проблем, трябва да посочим частта от времето, когато използваме оператор BETWEEN с тип данни DATETIME.

Следният скрипт ще върне всички записи между 2015-02-22 00:00:00 и 2015-02-22 23:59:59:999 . Частът от време за горната граница на датата е 23:59:999.

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

В изхода получаваме два записа за Дата на раждане 22.02.2015г .

Проблеми, свързани с периоди от време

Типът данни DATETIME поддържа само години от 1753 до 9999. Следователно, ако се опитате да съхраните дата със стойност на година, по-голяма от 9999 или по-малка от 1753, ще получите грешка.

Следният скрипт се опитва да преобразува 1392-12-31 низ за дата. 1392 е по-малко от 1753. Следователно имаме грешката в стойността извън диапазона.

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

За съхраняване на годишни стойности по-малко от 1753 , можете да използвате DATETIME2 тип данни. Той съхранява годишни стойности от 0000 до 9999.

Следният скрипт успешно преобразува низа за дата 1392-12-31 в тип данни DATETIME2:

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

Използване на TRY_COVERT за преобразуване на дата и час

Функцията CONVERT в SQL Server преобразува данните от един тип в друг. Можете да го използвате за преобразуване на форматите на данни от тип дата в други формати и обратно. Ако обаче преобразуването е неуспешно, функцията CONVERT издава грешка.

Например, ние преобразуваме низа 2015-31-31 във формат DATETIME:

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

Ако искате да се върне стойност NULL, когато преобразуването е неуспешно, вместо съобщението за грешка, използвайте TRY_CONVERT функция. Този метод няма да позволи на приложението да се срине – той просто връща стойност NULL.

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

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

Заключение

Работейки със SQL Server, може да се сблъскате с много проблеми, които развалят изживяването ви и усложняват задачите. Познаването на най-често срещаните проблеми е, от друга страна, най-ефективният метод за предотвратяване на възникването им. Ето защо посветихме тази статия на отстраняването на подобни неудобства, които могат да възникнат по време на вашата работа с информацията за датите и часовете.

Имайте предвид също, че съвременните инструменти за работа с бази данни на SQL Server могат да направят живота на специалистите по БД много по-лесен. По-специално, dbForge Studio за SQL Server предоставя функцията Visual Data Editor, която да се прилага при работа с дати. Можете да го използвате, за да преглеждате и редактирате датите по най-удобния за потребителя начин.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да използвате оператора BETWEEN в SQL Server

  2. Как се наричат ​​тръби?

  3. 6 функции за получаване на ден, месец и година от дата в SQL Server

  4. Говорим за тесните места в производителността на SQL Server

  5. Матрица на поддържаните версии на SQL Server