2016-06-13 7 views
0

同僚のためにOracle Express g11から一定の日付にデータを取得するクエリを作成しました。 クエリで使用される日付は、昨日(昨日または金曜日)です。オラクルの平日の祝祭日

同じクエリでは、曜日を表す別の番号が返されます。

例:私のコンピュータ上で実行すると

SELECT TRUNC('13June2016') - TRUNC('13June2016', 'D') 
FROM DUAL 

このクエリは0を返しますが、私の同僚のコンピュータ上では1を返します。これは、私たちが利用できるすべてのSQLクライアント/インタフェースで発生します。

私の知る限りでは、DB内のコンピュータとユーザは同じ設定になっていますが、明らかにいくつかの設定はオフです。

率直に言えば、この矛盾はどこから来ているのですか。私は無関係な結果を多く受けました。私は、この違いを説明する設定(または不明なバグ)を探す場所がわからないので、私は失われています。

+3

文字列を日付に正しく解析するためにロケール設定を使用しています。ISO datetime文字列形式を使用するか、明示的に 'TO_DATE()'を呼び出す必要があります。 – mustaccio

+0

あなたのコードから、私はあなたが達成しようとしているものを見ることができません。その2番目のTRUNCは非常に奇妙に見えます - それはTO_CHARであることを意味しましたか? –

+0

このクエリは完全なものからのスニッパです。この部分は、先週の月曜日から何日が経過したかを返すことになっています。最後に私の理解に 'to_char(SYSDATE、 'd')'は 'Trunc(SYSDATE、 'D')'と同じ結果を返します。 – sgp667

答えて

1

Dフォーマット修飾子は、セッションのNLS設定に依存しています:

alter session set nls_territory = 'America'; 
alter session set nls_date_format = 'YYYY-MM-DD'; 

select to_char(date '2016-06-13', 'D') char_d, 
    trunc(date '2016-06-13', 'D') trunc_d, 
    date '2016-06-13' - trunc(date '2016-06-13', 'D') diff1, 
    trunc(sysdate) - trunc(sysdate, 'D') diff2 
from dual; 

C TRUNC_D   DIFF1  DIFF2 
- ---------- ---------- ---------- 
2 2016-06-12   1   1 

alter session set nls_territory = 'United Kingdom'; 
alter session set nls_date_format = 'YYYY-MM-DD'; 

select to_char(date '2016-06-13', 'D') char_d, 
    trunc(date '2016-06-13', 'D') trunc_d, 
    date '2016-06-13' - trunc(date '2016-06-13', 'D') diff1, 
    trunc(sysdate) - trunc(sysdate, 'D') diff2 
from dual; 

C TRUNC_D   DIFF1  DIFF2 
- ---------- ---------- ---------- 
1 2016-06-13   0   0 

(興味深いことにtrunc(date '2016-06-13')を使用しているとき、私はバグ14073795つまずいたことを製造する際に、TRUNCは冗長であり、それは非常に矛盾しているようだ - 列の別名を変更します表示されたり消えたりすることができます - あなたが見ているものとは関係ないと思います)。

あなたとあなたの同僚は異なるロケールにPCを持ち、テストしたクライアントはロケールを継承したり、明示的に地域を設定したりしているようです。 ISO 8601規格で定義されたカレンダーの週の最初の日と週の

同じ日に:ロケールにかかわらず一貫性のある結果を得る/ NLSはそれが与えるとして、あなたが、the 'IW' format element instead of 'D'を使用することができます設定に

、あなたがhow the format models are used in trunc() and round() functionsについての詳細を読み、そしてより一般的には約date format modelsでき月曜日

alter session set nls_territory = 'America'; 
alter session set nls_date_format = 'YYYY-MM-DD'; 

select to_char(date '2016-06-13', 'IW') char_iw, 
    trunc(date '2016-06-13', 'IW') trunc_iw, 
    date '2016-06-13' - trunc(date '2016-06-13', 'IW') diff1, 
    trunc(sysdate) - trunc(sysdate, 'IW') diff2 
from dual; 

CH TRUNC_IW  DIFF1  DIFF2 
-- ---------- ---------- ---------- 
24 2016-06-13   0   0 

alter session set nls_territory = 'United Kingdom'; 
alter session set nls_date_format = 'YYYY-MM-DD'; 

select to_char(date '2016-06-13', 'IW') char_iw, 
    trunc(date '2016-06-13', 'IW') trunc_iw, 
    date '2016-06-13' - trunc(date '2016-06-13', 'IW') diff1, 
    trunc(sysdate) - trunc(sysdate, 'IW') diff2 
from dual; 

CH TRUNC_IW  DIFF1  DIFF2 
-- ---------- ---------- ---------- 
24 2016-06-13   0   0 

です。


暗黙の変換を使用することも良い考えではありません。 TRUNC('13June2016', 'D')は、セッションのNLS_DATE_FORMAT設定を使用して、文字列 '13June2016'を暗黙的に日付に変換しています。セッションを別の設定で実行するとエラーになります。暗黙的に変換された日付は、エラーがなければ、深夜に設定されているため、TRUNC('13June2016')は冗長です。

文字列を明示的に変換してフォーマットモデルを指定する必要があります(例: TRUNC(TO_DATE('13June2016', 'DDMonthYYYY', 'NLS_DATE_LANGUAGE=ENGLISH'), 'D')(セッションの日付の言語が何か他のものである場合に6月が認識されないようにするには3番目の引数が必要です)、より簡単にはDATE '2016-06-13'のようなISOの日付リテラルを使用します。

関連する問題