web-dev-qa-db-ja.com

間隔を加算/減算するための異なる構文

これまでは、次の構文を使用してタイムスタンプに間隔を追加しました。

_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リリースで機能しなくなる可能性がありますか?

4
gillesB

@a_horseで説明したように、式now() - '5 year'で使用できる演算子は2つあります。

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
3

私の推測(!)は:

タイムスタンプの+演算子は、間隔の追加のみをサポートしています(timestamp + interval)。したがって、文字列値'5 year'を(暗黙的に)intervalに変換する必要があることは明らかです。

一方、-演算子は2つの異なる組み合わせをサポートします。

  • timestamp - timestamp
  • timestamp - interval

どうやらPostgresはtimestamp - timestampオプションの使用を好み、'5 year'をタイムスタンプに(暗黙的に)変換しようとしますが、もちろん失敗します。