49

PL/pgSQL のドキュメントによると、変数への宣言と代入は で行われ:=ます。しかし、シンプルで、より短く、より現代的な (脚注を参照) =は、期待どおりに機能するようです:

    CREATE OR REPLACE FUNCTION foo() RETURNS int AS $$
    DECLARE
      i int;
    BEGIN
      i = 0;  
      WHILE NOT i = 25 LOOP
          i = i + 1;
          i = i * i;
      END LOOP;
      RETURN i;
    END;
    $$ LANGUAGE plpgsql;

    > SELECT foo();
    25

Pl/pgSQL は、行に示されているように、代入と比較を明確に区別できることに注意してください。

      WHILE NOT i = 25 LOOP

したがって、質問は次のとおりです。

  • これについて言及および/または説明しているドキュメントのセクションが見つかりませんでしたか?
  • =の代わりに使用する既知の結果はあり:=ますか?

編集/脚注:

A Brief, Incomplete, and Mostly Wrong History of Programming Languages のように、「より現代的な」部分をウィンクしてください。

1970 - Niklaus Wirth が手続き型言語 Pascal を作成。批評家はすぐに Pascal を非難します。それは、Pascal がより馴染みのある C ライクな "x = x + y" ではなく "x := x + y" 構文を使用しているためです。この批判は、C がまだ発明されていないという事実にもかかわらず起こります。

1972 年 - デニス・リッチーが、前方と後方に同時に発砲する強力な銃を発明。彼が C と Unix を発明したことによる死亡者数と恒久的な負傷者数に満足していません。

4

4 に答える 4

54

PL/PgSQL パーサーでは、代入演算子は次のように定義されています。

assign_operator : '='
                | COLON_EQUALS
                ;

これはレガシー機能であり、1998 年に導入されて以来、ソース コードに存在していました。PostgreSQL Git リポジトリで確認できます。

バージョン 9.4 以降、公式に文書化されています。

同じことに対して2つの演算子を持つというこの特異性は、pgsqlユーザーリストで提起され、一部の人々はそれを削除するように要求しましたが、レガシーコードの公平なコーパスがそれに依存しているため、コアに保持されています.

Tom Lane (コア Pg 開発者) からのこのメッセージを参照してください。

だから、あなたの質問にまっすぐに答えるには:

これについて言及および/または説明しているドキュメントのセクションが見つかりませんでしたか?

バージョン 9.4 で修正された文書化されていないため、見つかりませんでした。

:= の代わりに = を使用した既知の結果はありますか?

=を使用しても副作用はありませんが、代入に:=を使用してコードを読みやすくし、(副作用として) PL/SQLとの互換性を高める必要があります。

更新: まれなシナリオで副次的な結果が生じる可能性があります (Erwin の回答を参照)


更新: ダニエル、サンディなどからの入力のおかげで回答が更新されました。

于 2011-10-03T22:10:23.463 に答える
39

Q1

これは最終的にPostgres 9.4の公式ドキュメントに追加されました:

PL/pgSQL 変数への値の割り当ては、次のように記述されます。

variable { := | = } expression;

[...] =PL/SQL準拠の代わりにequal()を使用できます:=

Q2

=の代わりに使用する既知の結果はあり:=ますか?

はい、深刻な結果を招くケースがありました:名前付きパラメーターを使用した関数呼び出し-関連していますが、まったく同じではありません。

厳密に言えば、この場合の区別はSQLコードで行われます。しかし、それは無防備なプログラマーに対する学問的な違いです。1

関数を考えてみましょう:

CREATE FUNCTION f_oracle(is_true boolean = TRUE) -- correct use of "="
  RETURNS text AS
$func$
SELECT CASE $1
          WHEN TRUE  THEN 'That''s true.'
          WHEN FALSE THEN 'That''s false.'
          ELSE 'How should I know?'
       END
$func$  LANGUAGE sql;

余談です=が、関数定義での の正しい使用に注意してください。CREATE FUNCTIONこれは構文の一部であり、 SQL代入のスタイルです。2

名前付き表記による関数呼び出し:

SELECT * FROM f_oracle(is_true := TRUE);

Postgres は:=パラメーター割り当てとして識別され、すべて問題ありません。ただし:

SELECT * FROM f_oracle(is_true = TRUE);

は SQL 等値演算子であるため=、Postgres は呼び出しステートメントのコンテキストで SQL 式として解釈し、結果を名前のない位置パラメーターis_true = TRUEとして渡す前に評価を試みます。外側のスコープで識別子を探します。それが見つからない場合:is_true

ERROR:  column "is_true" does not exist

それは幸運なケースであり、幸運なことに、一般的なケースでもあります。

外側のスコープにある場合(およびデータ型に互換is_true がある場合) は、関数によって受け入れられる結果をis_true = TRUE持つ有効な式です。booleanエラーは発生しません。明らかに、これはSQL等値演算子を使用するプログラマーの意図=です...

このSQL Fiddleはその効果を示しています。

と の違いを認識していないと、デバッグが非常に困難=です:=
常に正しい演算子を使用してください。


1関数呼び出しで名前付き表記を使用する場合:=、正しい代入演算子はだけこれは、PL/pgSQL だけでなく、pg 9.4 までのすべての言語の関数に適用されます下記参照。

2= (またはDEFAULT) を 使用して、関数パラメーターのデフォルト値を定義できます。それは当面の問題とはまったく関係ありません。間違ったユースケースに非常に近いです。

Postgres 9.0 - 9.4: から:=への移行=>

名前付き関数パラメーターへの代入の SQL 標準は=>(そしてOracle の PL/SQL はそれを使用します。Postgres は同じことができませんでした。演算子は以前に予約解除されていたため、:=代わりに PL/pgSQL の代入演算子を使用しています。Postgres 9.0 のリリースにより、=>を他の目的で使用することは推奨されていません。リリース ノートによると:

演算子名としての => の使用を廃止します。 (Robert Haas)

PostgreSQL の将来のバージョンでは、名前付き関数パラメータの SQL 標準表記をサポートするために、おそらくこの演算子名を完全に拒否するでしょう。現時点ではまだ許可されていますが、そのような演算子が定義されている場合は警告が発せられます。

他の目的で使用する場合は、使用=>を中止してください。将来的に壊れます。

Postgres 9.5:=>今すぐ使用

このリリース以降、SQL 標準演算子=>が使用されます。:=下位互換性のために引き続きサポートされています。ただし、非常に古いバージョンで実行する必要のない新しいコードでは、標準演算子を使用してください。

これは、変更されていないplpgsql コードの代入演算子ではなく、関数呼び出し(SQL スコープ) の名前付きパラメーターの代入に適用されます。:=

于 2014-02-24T23:14:38.633 に答える
3

私自身の質問に対する部分的な答え:

PL/pgSQL セクション結果ステータスの取得 は、特別な構文を使用した 2 つの例を示しています。

GET DIAGNOSTICS variable = item [ , ... ]; 
GET DIAGNOSTICS integer_var = ROW_COUNT;

:=私は両方を試しましたが、両方=とも機能します。

しかしGET DIAGNOSTICS、これは特殊な構文であるため、これも通常の PL/pgSQL 割り当て操作ではないと主張できます。

于 2011-09-22T19:33:11.003 に答える
1

Postgresql 9 のドキュメントを読む:

このページでは、演算子の優先順位の表に代入演算子として「=」がリストされています。

しかし、不思議なことに、このページ(代入演算子のドキュメント) はそれについて言及していません。

于 2011-09-22T19:00:11.100 に答える