これまでは、次の構文を使用してタイムスタンプに間隔を追加しました。
_select now() + '5 year';
_
構文エラーが発生する間隔を差し引こうとするまで、これはうまくいきました。
_invalid input syntax for type timestamp with time zone: "5 year"
LINE 1: select now() - '5 year'
_
documentation では、構文は実際には次のとおりであることを学びました。
_select now() - interval '5 year'
_
だから私の質問は:select now() + '5 year'
がなぜまったく機能しないのですか?それは偶然にのみ機能し、将来のPostgresqlリリースで機能しなくなる可能性がありますか?
@a_horseで説明したように、式now() - '5 year'
で使用できる演算子は2つあります。
now()
はtimestamp with time zone
(timestamptz
)を返します。'5 year'
は 型なし文字列リテラル です。SELECT oprleft::regtype, oprname, oprright::regtype
FROM pg_operator
WHERE oprname = '-'
AND oprleft = 'timestamptz'::regtype;
oprleft | oprname | oprright
--------------------------+---------+--------------------------
timestamp with time zone | - | timestamp with time zone
timestamp with time zone | - | interval
(2 rows)
exact選択の理由は、マニュアルの章 演算子のタイプ解決 :
[...]
2.
入力引数の型を正確に受け入れる演算子をチェックします。存在する場合(考慮される演算子のセットで完全に一致するものは1つだけ存在できる)、それを使用します。 [...]
a.
二項演算子呼び出しの1つの引数が不明なタイプである場合、これは他の引数と同じタイプであると想定します小切手。 [...][...]
太字は私のものを強調しています。章全体を読んで、プロセスを完全に理解してください。
同じタイプは、1つの引数タイプが不明であり、一致する演算子が利用可能な場合に推奨されます。 timestamptz - timestamptz
、ビンゴの演算子があります。演算子はここで解決されます。 幸いにも、「[5年]」はtimestamptz
への不正な入力です。それ以外の場合は、混乱を招く可能性があります。
演算子は、明示的な型キャストを追加した後、timestamptz - interval
に解決されます。
now() - interval '5 year' -- always the way to go
私の推測(!)は:
タイムスタンプの+
演算子は、間隔の追加のみをサポートしています(timestamp + interval
)。したがって、文字列値'5 year'
を(暗黙的に)interval
に変換する必要があることは明らかです。
一方、-
演算子は2つの異なる組み合わせをサポートします。
timestamp - timestamp
timestamp - interval
。どうやらPostgresはtimestamp - timestamp
オプションの使用を好み、'5 year'
をタイムスタンプに(暗黙的に)変換しようとしますが、もちろん失敗します。