Microsoft SQL Serverデータベースには、日付と時刻の情報がさまざまな形式で格納されています。それらの中で最も一般的なのはDateTime 、 DateTime2 、および日付 。すべてのタイプのデータで発生するように、問題は何度も発生する可能性があります。この記事では、SQLの時刻と日付のデータ型を操作するときに直面する可能性のある最も一般的な問題のトラブルシューティングに焦点を当てます。
地域によって異なる日付形式に関連する問題
日付の形式は世界的に異なります。たとえば、英国の書き込み日付はdd-mm-yyyyですが、アメリカの書き込み日付はmm-dd-yyyy形式です。このように、同じ日付である2020年12月31日は、英国の日付形式では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 US_ENGLISHを使用してDATETIME形式に変換します 言語設定を行うと、以下のようなエラーが発生します:
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として指定し、US_ENGLISH設定を使用して日付文字列をDATETIMEに変換すると、変換が成功したことがわかります。
SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '12-31-2020 04:25:30';
SELECT CAST(@date AS DATETIME);
同様に、 12-31-2020を変換します BRITISH言語設定の日付文字列もエラーを引き起こします– 31は月として扱われ、それはできません。
SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '12-31-2020 04:25:30';
SELECT CAST(@date AS DATETIME);
言語設定に関係なく日付を正確に変換するために、日付形式にISO標準8601を使用できます。この標準に準拠するには、日付を yyyy-mm-ddThh:mm:ssとして指定します。 。
たとえば、日付文字列2020-12-31T04:25:30は、英国の言語設定でDATETIMEデータ型に正常に変換されます。
SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '2020-12-31T04:25:30';
SELECT CAST(@date AS DATETIME);
次のスクリプトは、US_ENGLISH設定でDATETIMEに変換された同じ文字列を示しています。
SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '2020-12-31T04:25:30';
SELECT CAST(@date AS DATETIME);
タイムゾーンに関する考慮事項
世界中のユーザー向けにSQLServerデータベースアプリケーションを開発することをお勧めします。そのためには、タイムゾーン情報を追加する必要がある場合があります 日付と時刻のデータ型に。
SQL Serverでは、DATETIMEOFFSETデータ型は、タイムゾーンオフセットとともに日付と時刻の情報を格納します。タイムゾーンオフセットは、UTC+/-時間数として指定されます。
たとえば、次のスクリプトはSYSDATETIMEOFFSET()メソッドを使用して、SQL Serverインスタンスを実行しているシステムの日付、時刻、およびオフセット情報を取得します。 SYSDATETIMEOFFSET()関数によって返される値は、DATETIMEOFFSET型変数@dateoffsetに格納されます。 @dateoffset変数の値は、SELECTステートメントを使用して出力されます。
DECLARE @dateoffset DATETIMEOFFSET = SYSDATETIMEOFFSET();
SELECT @dateoffset
以下の出力は、現在の日時とオフセット値を示しています。この場合は+02:00です。
DATETIMEOFFSET変数からオフセット値のみを取得することもできます。そのためには、DATETIMEOFFSET型変数を2番目のパラメーター値として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に合格する必要があります 最初のパラメータ値として変数を入力し、2番目のパラメータ値として新しい時間オフセットを SWITCHOFFSETに渡します 機能。
次のスクリプトは、DATETIMEOFFSET変数のタイムオフセット値を+05:00から+09:00に更新します。
DECLARE @dateoffset DATETIMEOFFSET = '2015-02-22 23:59:59:999 +05:00';
SELECT SWITCHOFFSET(@dateoffset, '+09:00');
DateTimeでBETWEEN演算子を使用してレコードを選択する
BETWEEN SQL Serverの演算子は、渡された値の範囲の間でレコードをフィルタリングします。
BETWEEN演算子を使用して、2つの日付の間のレコードを返すことができます。ただし、日付のあるレコードのフィルタリングに使用する場合は、特に注意する必要があります。
たとえば、次のスクリプトはダミーのホステルを作成します データベースを作成し、1人の学生を追加します それにテーブル。
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
)
次のスクリプトは、いくつかのダミーレコードを Student に追加します テーブル。 BirthDate 学生の列 テーブルには日付が格納されます。このスクリプトから、2人の学生SaraとNikの生年月日が同じであることがわかります。ただし、生年月日は異なります:
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演算子を使用して、2015-02-22に生まれたすべての学生の記録を取得できると思います。
SELECT * FROM Student
WHERE BirthDate BETWEEN '2015-02-22' AND '2015-02-22'
ただし、上記のスクリプトを実行すると、時間にもかかわらず、1つのレコードのみが返されることがわかります。 一部 も含まれています。
その理由は、BETWEEN演算子は、デフォルトで 2015-02-22のDATETIME値を処理するためです。 2015-02-22 00:00:00 。したがって、上記のクエリのBETWEEN演算子は、 BirthDateのレコードを検索しました。 2015-02-2200:00:00と2015-02-2200:00:00の間の値 。
この問題を解決するには、DATETIMEデータ型でBETWEEN演算子を使用するときに時間部分を指定する必要があります。
次のスクリプトは、 2015-02-22 00:00:00の間のすべてのレコードを返します。 および2015-02-2223:59:59:999 。 日付の上限の時間部分は23:59:999です。
SELECT * FROM Student
WHERE BirthDate BETWEEN '2015-02-22' AND '2015-02-22 23:59:59:999';
出力では、 BirthDateの2つのレコードを取得します – 2015-02-22 。
日付範囲に関連する問題
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を使用する
SQL ServerのCONVERT関数は、データをあるタイプから別のタイプに変換します。日付型のデータ形式を他の形式に、またはその逆に変換するために使用できます。ただし、変換が失敗した場合、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データベースを操作するための最新のツールを使用すると、DBスペシャリストの作業がはるかに簡単になることにも注意してください。特に、dbForge Studio for SQL Serverは、日付を処理するときに適用するVisualDataEditor機能を提供します。これを使用して、最もユーザーフレンドリーな方法で日付を表示および編集できます。