2016-08-17 9 views
6

Oracle SQLデータベースの上で実行されるBusiness Objectsを使用しています。私はPLやあらゆる種類のSQLコマンドラインにアクセスすることができず、データベースへの書き込みアクセス権も持っていません。私は単一のコマンドとしてクエリを実行することができ、定義された列のセットを出力する必要があります。Oracle SQLでユーザー・プロンプトを日付(または文字列)として渡す

私のようにSQLに表示されるユーザープロンプトからデータを取ることができています:たとえば

@variable('Prompt1') 

私が言うことができます:

SELECT 
    A.SomeDate 
FROM 
    A 
WHERE 
    A.SomeDate BETWEEN @variable('Start') AND @variable('End Date') 

をこれが十分に簡単です。それは走ります。ユーザにいくつかの日付を入力するよう要求する。それらの間にあるすべての一致を返します(両端を含む)。

しかし、問題はBusiness Objectsの "Infoview"システムを使用してクエリを実行し、プロンプトシステムに日付ピッカーが表示されます。デフォルトでは日付の時間部分( "01/01/2016 12:00:00 AM ")。

ユーザーが時間部分を削除しないと、SomeDate値が選択された時間外になるとレコードが失われる可能性があります。たとえば、TODAYのすべてのレコードを取得する場合は、技術的には00:00:00(深夜)から23:59:59までのすべてのレコードが必要です。

WHERE 
    A.SomeDate BETWEEN TRUNC(@variable('Start')) AND TRUNC(@variable('End Date')) 

が...しかし、これはコンパイルエラーが発生します:次のように私は本当に行うことができるようにしたいと思い何

は、クエリ変数の周りに使用TRUNCある「一貫性のないデータ型:予想DATEは、NUMBERを得ました"オラクルがコンパイルする前にプロンプ​​トを数値データ型として扱う理由はわかりません。

@variable値をどのように取って、それを日付値に切り捨てることができるか知っている人はいますか?

私はこれを回避する方法を見つけようとしています。私が覚えていたことは、プロンプト変数をとり、TO_DATEを使って明示的に日付に変換できるかどうかということでした。

編集:TRUNCは効果がないと私は指摘されています。 00:00 AM "はすでに深夜です。だから私はTRUNCを誤解していると思う。真夜中に切り捨てられているように見えますが、日付の時間部分を単に削除すると思っていましたが、00:00:00から23:59:59までの間はいつでも一致が返されます。

私が本当に欲しいのは、SomeDateには11:03などの時間部分がある場合、End Dateプロンプトでその日のみを指定すると、これが確実に含まれるようにする方法はありますか?

+0

日付ピッカーが常に時刻を午前12:00:00としている場合、切り捨てると効果はありません。それはすでに深夜になっています。 –

+0

@Alex Poole - うーん、興味深いです。 SomeDateの値に実際に時間の部分がある場合(11:02など)、私は上記の例を単純化しましたが、実際には日付を見たいと思っています。たとえば、11時02分の予定を含め、今日行われているすべての予定を一覧表示する場合は、「真夜中」検索では選択されません。切り詰めると時間部分が検索されなかったということになります。 –

+0

Oracleの日付には常に時間がありますが、削除することはできません。深夜に設定するだけです。これはtruncのデフォルト設定です。開始日の00:00:00と終了日の23:59:59の間でレコードを一致させたいのですか? –

答えて

1

をあなたが持って終了日を調整することができますどちらかの端にスタート00:00:00と午後11時59分59秒の間SomeDate値と一致する場合その時の代わりに、デフォルトの深夜、またはその代わりbetweenの範囲を使用する:ユーザーが選んだので、もし

WHERE 
    A.SomeDate >= @variable('Start') 
AND 
    A.SomeDate < @variable('End Date') + 1 

+ 1は、あなたの変数値の翌日を与えることOracle date arithmeticを使用しています開始日と終了日の両方で2016-01-01 00:00:00と2016-01-02 00:00:00と評価される "01/01/2016 12:00:00 AM"必要に応じてinterval構文を使用できます。調整終了日2016年より2016年1月1日午前0時00分00秒と少ないSomeDate以上に等しいすべてのレコードに満たないあなたが得る上限の開始日を使用することにより

-01-02 00:00:00 - これは2016-01-01 23:59:59までと同じです。 (または、秒未満の精度のタイムスタンプ列を持つ場合は、最大23:59:59.999 ...)。

パーサは、変数が文字列になりますが、それは実際の日付であると仮定した場合 - 「一貫性のないデータ型」エラーの原因 - あなたはパーサを満たすために、日付にキャストできます。

WHERE 
    A.SomeDate >= CAST(@variable('Start') AS DATE) 
AND 
    A.SomeDate < CAST(@variable('End Date') AS DATE) + 1 

かそれは実際にあなたがそれを明示的に変換することができます示した形式の文字列として渡された場合:

WHERE 
    A.SomeDate >= TO_DATE(@variable('Start'), 'DD/MM/YYYY HH:MI:SS AM') 
AND 
    A.SomeDate < TO_DATE(@variable('End Date'), 'DD/MM/YYYY HH:MI:SS AM') + 1 

...あなたは正しい形式を持っていることを確認すること。あなたの例では、DD/MM/YYYYまたはMM/DD/YYYYになります。

+0

解決策は素晴らしいと思われ、完璧な意味があります。しかし、私が試したところ、コンパイルされませんでした。エラーは「不整合なデータ型です:期待された日付はNUMBERになりました」です。これは、2行目がプロンプト値に1を加算することによって引き起こされています。 元の質問に戻ります。これは、迅速なデータ型に関連しています。プロンプトを日付の値に変換する必要があります... –

+0

次に、両方の変数の周りに 'to_date()'が必要な場合があります。問題は、SQLパーサがバインド変数として '@variable()'ビットを見ていて、文字列であると仮定していることです。文字列として*渡された場合は、フォーマットマスクが指定されていればそれを指定する方が良いでしょう。 - to_date(@variable( 'Start') 、 'DD/MM/YYYY HH:MI:SS AM') 'となります。元のクエリは日付として渡されないと暗黙の変換が行われるため、BOはその日付形式をセッションの既定値として設定している可能性があります。 –

1

一緒TO_CHAR()TO_DATE()を使用してみてください:

WHERE 
A.SomeDate > TO_DATE(TO_CHAR(@variable('Prompt1'),'ddmmyyyy'),'ddmmyyyy') 
+0

コンパイルされますが、実行時には「SQL実行中のエラー:ORA-01722:無効な番号」が戻されます。はい、私はddmmyyyyの形式で日付を入力していました。他の考え? –

0

まず、問題はプロンプト値の時間値からではなく、むしろSomeDateの時間値から来ています。それを取り除く(深夜にする)ことで問題が解決されます。

宇宙を変更するオプションがある場合は、別のオブジェクトを作成することをお勧めします。私は、あなたのオブジェクトがであるSomeDateという名前のオブジェクトを持っていると仮定しています。別のオブジェクトを作成し、それをSomeDateOnlyとし、定義をtrunc(a.somedate) * **とします。でWebIでレンダリングする場合、生成されます

trunc(a.somedate) = @variable('Prompt1') 

trunc(a.somedate) = '16-08-2016 00:00:00' 
SomeDateOnlyは常に真夜中の値になりますので

、次のようなSQLが生成されますされ、あなたのプロンプトと等しくなるようにを使用することができます

00:00:00と8/16/2016 23:59:59の間に2012年8月16日からa.somedateのすべてのレコードが返されます。

もちろん、あなたが日付の範囲を選択するために、BETWEEN使用することができます。

trunc(a.somedate) between @variable('Start Date') and @variable('End Date') 

をユニバースへのアクセス権を持っていない場合でも、あなたはまだでWebIの生成されたSQLを変更することによって、上記の構文を使用することができます。 (私はそれがあなたがやってきたことだと思っています、とにかく)。

あなたのために上記の作品は、その後、次は無関係ですが、私はとにかくそれを解決したい場合:

あなたが受けていた「無効な番号」エラーの理由が原因でWebIのために日付をフォーマットする方法であるがSQL。

A.SomeDate = TRUNC(@variable('Prompt1')) 

が、その後でWebI日付文字列と@Variable(...)を交換し、Oracleに送信する前に、次のようにレンダリングされます:

あなたのクエリでは、この文字列を持っている場合
A.SomeDate = TRUNC('16-08-2016 00:00:00') 

これは、実際には日付値であることを示すものがないので、もちろん、TRUNC()関数には意味がありません。

to_date最初にプロンプ​​トが表示されますが、正しい日付形式を使用する必要があります。でWebIは、デフォルト以外のフォーマットに各セッションのNLS_DATE_FORMATを設定しますので、あなたが使用する必要があります:

A.SomeDate = TRUNC(to_date(@variable('Prompt1')),'dd-mm-yyyy hh24:mi:ss') 

をしかし、あなたはsomedateなく、迅速な応答値をTRUNCする必要があるため、再び、これは無関係です。


*より良いまだ、SomeDateTimeSomeDateの名前を変更し、新しいオブジェクトSomeDate

に名前を付ける**これはかなり一般的である - 同じソースのフィールドに複数のオブジェクトを持ちます。時には、特定のトランザクションをリストするための日付/時刻値が必要な場合もありますが、日付を必要とするだけの場合もあります(日付別にトランザクションをカウントする場合)。したがって、両方を利用できることは非常に便利です。

関連する問題