Zapomniany operator przypisania " = "i pospolite": ="

Dokumentacja dla PL / pgSQL mówi, że deklaracja i przypisanie do zmiennych odbywa się za pomocą :=. Ale prosty, krótszy i bardziej nowoczesny (patrz przypis)= wydaje się działać zgodnie z oczekiwaniami:

    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

Należy pamiętać, że Pl / pgSQL może wyraźnie odróżnić przypisanie i porównanie, jak pokazano w linii

      WHILE NOT i = 25 LOOP

Więc pytania są następujące:

  • czy nie znalazłem jakiejś sekcji w dokumentach, które wspominają i / lub wyjaśniają to?
  • czy są jakieś znane konsekwencje używając = zamiast :=?

Edytuj / Przypis:

Proszę wziąć "bardziej nowoczesną" część z przymrużeniem oka, jak w krótka, niekompletna i w większości błędna Historia języków programowania : {11]}

1970-Niklaus Wirth tworzy Pascal, język proceduralny. Krytycy natychmiast wypowiedź Pascala, ponieważ używa składni "x: = X + y" zamiast bardziej znanego C-jak "x = x + y". Ta krytyka dzieje się pomimo faktu to C jeszcze nie zostało wynalezione. 1972-Dennis Ritchie wymyśla potężną broń, która strzela do przodu i do tyłu jednocześnie. Nie zadowolony z liczby zgonów i permanentne okaleczenia z tego wynalazku wymyśla C i Unix.
Author: Erwin Brandstetter, 2011-09-18

4 answers

W parserze PL / PgSQL operator przypisania jest zdefiniowany jako

assign_operator : '='
                | COLON_EQUALS
                ;

Jest to funkcja dziedziczona, obecna w kodzie źródłowym od 1998 roku, kiedy została wprowadzona - jak widać w PostgreSQL Git repo .

Począwszy od wersji 9.4 jest to oficjalnie udokumentowane .

Ten idiosynkrazja-posiadania dwóch operatorów dla tego samego - został podniesiony na liście użytkowników pgsql, a niektórzy prosili o jego usunięcie, ale nadal jest trzymany w rdzeniu, ponieważ fair corpus of legacy code opiera się na nim.

Zobacz wiadomość od Toma Lane ' a (głównego programisty Pg) .

Więc odpowiadając na twoje pytania wprost:

Czy nie znalazłem jakiejś sekcji w dokumentach, która wspomina i / lub wyjaśnia to?

Nie znalazłeś go, ponieważ był nieudokumentowany, co jest poprawione od wersji 9.4.

Czy są jakieś znane konsekwencje używania = zamiast:=.

Nie ma skutków ubocznych stosowania =, ale powinieneś użyć := do przypisania, aby Twój kod był bardziej czytelny i (jako efekt uboczny) bardziej kompatybilny z PL/SQL.

Aktualizacja: w rzadkich scenariuszach może być poboczna konsekwencja (zobacz odpowiedź Erwina)


Aktualizacja: odpowiedź zaktualizowana dzięki informacjom od Daniela, Sandy i innych.

 36
Author: filiprem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-29 09:21:00

Q1

To zostało w końcu dodane do oficjalnej dokumentacji z Postgres 9.4:

Przypisanie wartości do zmiennej PL / pgSQL jest zapisywane jako:

variable { := | = } expression;

[...] Equal (=) może być używany zamiast zgodnego z PL / SQL :=.

Q2

Czy są jakieś znane konsekwencje używania = zamiast :=?

Tak , miałem sprawę z ciężką consequences: wywołanie funkcji z nazwanymi parametrami - co jest powiązane, ale nie dokładnie to samo.

Ściśle mówiąc, rozróżnienie w tym przypadku dokonuje się w kodzie SQL . Ale to akademickie rozróżnienie od niczego nie podejrzewającego programisty.1

Rozważmy funkcję:

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;

Na bok: zwróć uwagę na prawidłowe użycie = w definicji funkcji. To część składni CREATE FUNCTION - W Stylu SQL przypisanie.2

Wywołanie funkcji z nazwaną notacją :

SELECT * FROM f_oracle(is_true := TRUE);

Postgres identyfikuje := jako przypisanie parametrów i wszystko jest dobrze. jednakże :

SELECT * FROM f_oracle(is_true = TRUE);

Od = jest operatorem równości SQL, Postgres interpretuje is_true = TRUE jako wyrażenie SQL w kontekście wywołującej instrukcji i próbuje je ocenić przed przekazaniem wyniku jako nienazwany parametr pozycyjny . Poszukuje identyfikator is_true w zakresie zewnętrznym. Jeśli tego nie można znaleźć:

ERROR:  column "is_true" does not exist

To szczęśliwy przypadek i, na szczęście, również ten powszechny.

Kiedy is_true Można {[66] } znaleźć w zewnętrznym zakresie (i typy danych są kompatybilne), is_true = TRUE jest poprawnym wyrażeniem z wynikiem boolean, który jest akceptowany przez funkcję. Nie występuje błąd. Oczywiście jest to intencja programisty używającego SQL Operator równości =...

To SQL Fiddle demonstruje efekt.

Bardzo trudne do debugowania, jeśli nie jesteś świadomy różnicy między = i :=.
zawsze używaj właściwego operatora.


1 podczas używania notacji nazwanej w wywołaniach funkcji , tylko := jest prawidłowym operatorem przyporządkowania. Dotyczy to funkcji wszystkich języków, nie tylko PL / pgSQL, do pg 9.4 włącznie. Zobacz też poniżej.

2 Można użyć = (or DEFAULT), aby zdefiniować wartości domyślne dla parametrów funkcji. To w żaden sposób nie jest związane z problemem. Jest po prostu niezwykle blisko błędnego przypadku użycia.

Postgres 9.0-9.4: przejście z := na =>

Standard SQL przypisywania do nazwanych parametrów funkcji to => (i Oracle PL / SQL używa go . Postgres nie mógł zrobić tego samego, ponieważ operator był wcześniej nieograniczony, używa więc zamiast niego operatora przypisania PL/pgSQL :=. Wraz z wydaniem Postgres 9.0 użycie => do innych celów zostało wycofane. uwagi do wydania :

Przestarzałe użycie = > jako nazwy operatora (Robert Haas)

Przyszłe wersje PostgreSQL prawdopodobnie odrzucą tę nazwę operatora całkowicie, w celu obsługi standardowej notacji SQL dla nazwanych parametry funkcji. Na moment, jest to nadal dozwolone, ale ostrzeżenie jest emitowane, gdy taki operator jest zdefiniowany.

Jeśli powinieneś używać => do czegoś innego, przestań. Pęknie w przyszłości.

Postgres 9.5: użyj => teraz

Począwszy od tego wydania, standardowy operator SQL=> jest używany. := jest nadal wspierana dla zgodności wstecznej. Ale użyj standardowego operatora w nowym kodzie, który nie musi działać na bardzo starym wersje.

Dotyczy to przypisania nazwanych parametrów w wywołaniach funkcji (zakres SQL), a nie operatora przypisania := w kodzie plpgsql, który pozostaje bez zmian.

 28
Author: Erwin Brandstetter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-19 13:55:42

Częściowa odpowiedź na moje pytanie:

Sekcja PL/pgSQL uzyskanie statusu wyniku pokazuje dwa przykłady przy użyciu specjalnej składni:

GET DIAGNOSTICS variable = item [ , ... ]; 
GET DIAGNOSTICS integer_var = ROW_COUNT;
Próbowałem obu := i = i działają oba.

Ale GET DIAGNOSTICS jest specjalną składnią, więc można argumentować, że nie jest to również normalna operacja przypisania PL / pgSQL.

 2
Author: A.H.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-22 19:38:13

Czytanie dokumentacji Postgresql 9:

Ta strona wymienia "=" jako operator przypisania w tabeli o pierwszeństwie operatora.

Ale o dziwota strona (Dokumentacja operatora przydziału) o tym nie wspomina.

 1
Author: Mike Sokolov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-22 19:00:11