有効期限列をnow()
と比較するクエリを使用してクエリを実行している複数のデータベースサーバーがあります。問題は、サーバーの有効期限列の1つがtimestamp with time zone
であり、残りはすべてdate
であるということです。管理アクセス権がないため、これを変更することはできません。実際、ビューをクエリするだけです。 Postgresは私にとってかなり新しいものなので、日付と時刻が互いにどのように連携するのか私にはよくわかりません。
timestamp
をdate
としてキャストすることにより、timestamp with time zone
を使用してサーバーにクエリを実行すると、次のようになります。
...
WHERE
(
status_code = '30000'
OR status_code = '30005'
)
AND CAST(expiration AS DATE) > now()
機能しますが、expiration
がすでにdate
であるサーバーで同じクエリを使用すると失敗します。
[エラー]エラー:タイプ日付の無効な入力構文:「終了日なし」
手助けをいただければ幸いですが、実際には、この1つのDBサーバーの例外をハードコードしないでください。
これは決して失敗しないはずです(私は少し簡略化しました):
_WHERE status_code IN ('30000','30005')
AND expiration > now()
_
PostgreSQLは date
とtimestamp
(タイムゾーンの有無にかかわらず) を自動的に比較できます。 date
の場合は、自動的にtimestamp
にキャストされます(0:0時間)。
エラーメッセージは別の話を伝えます。無効な構文でdate
を入力しようとしています。
最近、PostgreSQLのタイムゾーンの有無に関係なくタイムスタンプの処理について詳細な回答を書きました。
結局のところ、expiration
はtext
列です。 date
またはtimestamp
(必要に応じて)にキャストする必要があります。有効な形式の場合:
_...
AND expiration::timestamptz > now()
_
そのテキスト列に「終了日なし」などの無効な文字列がある場合、ソースをクリーンアップするか、CASE
構成で特別に処理する必要があります。
_...
AND CASE WHEN expiration::text = 'No End Date' THEN 'infinity'::timestamp
WHEN expiration::text = 'foo' THEN '-infinity'::timestamp
ELSE expiration::timestamp
END > now()
_
テキストへのキャスト(_::text
_)はtext
と冗長ですが、式はdate
/timestamp
値でも機能します。
タイムスタンプリテラルの形式があいまいな場合は、to_date()
またはto_timestamp()
を使用して、形式を明示的に定義します。
_to_date('07/08/2013', 'DD/MM/YYYY')
_
expiration
がanotherタイムゾーンのローカルタイムスタンプであると想定されている場合は、 _AT TIME ZONE
_構文 を使用します。
_expiration::timestamp AT TIME ZONE 'UTC' -- desired time zone here
_
expiration
があいまいな/非標準の形式の場合、 to_timestamp()
を使用します。
_to_timestamp(expiration::text, 'yyyy-mm-dd')
_