21
declare @str_datetime varchar(50)
set @str_datetime='30-04-2012 19:01:45' -- 30th April 2012
declare @dt_datetime datetime
select @dt_datetime=@str_datetime

これにより、次のエラーが発生します。

メッセージ242、レベル16、状態3、4行
目varcharデータ型を日時データ型に変換すると、値が範囲外になりました。

私の質問は、SQLServerが暗黙の日時変換に使用する形式をどのように決定するかです。

4

3 に答える 3

30

これは、オペレーティングシステムの地域設定、現在のユーザーの言語、日付形式の設定など、さまざまな要因によって異なります。デフォルトでは、Windowsはを使用しUS English、ユーザーの設定はとです。US EnglishMDY

しかし、これがどのように変化するかを示すいくつかの例があります。

ユーザーはイギリス英語の設定を使用しています。

-- works:
SET LANGUAGE BRITISH;
SELECT CONVERT(DATETIME, '30-04-2012 19:01:45');

-- fails:
SELECT CONVERT(DATETIME, '04/13/2012');
GO

(エラー)

メッセージ242、レベル16、状態3、5行
目varcharデータ型を日時データ型に変換すると、値が範囲外になりました。

ユーザーはFrançaisを使用しています:

-- works:
SET LANGUAGE FRENCH;
SELECT CONVERT(DATETIME, '30-04-2012 19:01:45');

-- fails:
SELECT CONVERT(DATETIME, '04/13/2012');
GO

(エラー)

Msg 242、レベル16、状態3、行
1La変換d'untypededonnéesvarcharentypededonnees日時acrééunevaleurhorslimites。

ユーザーは再びFrançaisを使用しています:

SET LANGUAGE FRENCH;

-- fails (proving that, contrary to popular belief, YYYY-MM-DD is not always safe):
SELECT CONVERT(DATETIME, '2012-04-30');
GO

(エラー)

Msg 242、レベル16、状態3、行
1La変換d'untypededonnéesvarcharentypededonnees日時acrééunevaleurhorslimites。

ユーザーがMDYの代わりにDMYを使用しています。

SET LANGUAGE ENGLISH;
SET DATEFORMAT DMY;

-- works:
SELECT CONVERT(DATETIME, '30-04-2012 19:01:45');

-- fails:
SELECT CONVERT(DATETIME, '04-30-2012');
GO

(エラー)

メッセージ242、レベル16、状態3、2行目
varcharデータ型を日時データ型に変換すると、値が範囲外になりました。

常に最善の策は、ISO標準、非地域、安全、明確な日付形式を使用することです。私が通常お勧めする2つは次のとおりです。

YYYYMMDD                  - for date only.
YYYY-MM-DDTHH:MM:SS[.mmm] - for date + time, and yes that T is important.

これらのどれも失敗しません:

SET DATEFORMAT MDY;
SET LANGUAGE ENGLISH;
SELECT CONVERT(DATETIME, '20120430');
SELECT CONVERT(DATETIME, '2012-04-30T19:01:45');
SET LANGUAGE FRENCH;
SELECT CONVERT(DATETIME, '20120430');
SELECT CONVERT(DATETIME, '2012-04-30T19:01:45');
SET LANGUAGE BRITISH;
SELECT CONVERT(DATETIME, '20120430');
SELECT CONVERT(DATETIME, '2012-04-30T19:01:45');
SET DATEFORMAT DMY;
SELECT CONVERT(DATETIME, '20120430');
SELECT CONVERT(DATETIME, '2012-04-30T19:01:45');

したがって、ユーザーがフリーテキストの日付形式を入力できるようにする(または信頼性の低い形式を自分で使用する)のではなく、入力文字列を制御して、これらの安全な形式の1つに準拠していることを確認することを強くお勧めします。そうすれば、ユーザーがどのような設定を持っているか、または基礎となる地域の設定が何であるかは関係ありません。日付は常に意図された日付として解釈されます。現在、ユーザーがフォームのテキストフィールドに日付を入力できるようにしている場合は、それを停止し、カレンダーコントロールまたは少なくとも選択リストを実装して、SQLServerに返される文字列形式を最終的に制御できるようにします。

背景については、TiborKarasziの「日時データ型の究極のガイド」と私の投稿「キックへの悪習:日付/範囲クエリの誤った処理」をお読みください。

于 2012-05-01T15:03:05.227 に答える
1

デフォルトでは、SQL Serverのローカライズ版がインストールされていない限り、 SQLServerの日付形式は米国の日付形式MM/ DD/YYです。この設定は、この機能を必要とするアプリケーションが、アプリケーションが使用されるすべてのプラットフォームと場所で同じ形式で日付が使用および挿入されることを保証する方法で展開される場合に適しています。

ただし、多くの国/地域では米国のデフォルトのMM / DD / YYではなくこの形式を使用しているため、場合によっては日付をDD / MM/YY形式にする必要があります。これは、世界中に配布されている国際的なアプリケーションにとって特に問題です。

ソース

したがって、必要なのは、事前に日付形式を設定することです。

SET DATEFORMAT dmy
GO

そして、クエリが機能します。

于 2012-05-01T14:20:33.853 に答える
1

ログインごと、および/または今後追加されるログインごとに、デフォルトの日付形式を変更することもできます(各セッションで「SETDATEFORMAT」を実行する必要はありません)。

SQL ManagementStudio/セキュリティ/ログインに移動します。ログインを右クリックしてから、[プロパティ]をクリックします。下部に「デフォルト言語」が表示されます。

将来追加されるログインを確認したい場合は、「適切な」言語を使用してください。サーバールートを右クリックし、[プロパティと詳細]ページを右クリックします。新しく作成されたログインに使用される「デフォルト言語」オプションもあります。

于 2014-01-15T16:43:43.423 に答える