variable declarar postgresql plpgsql assignment-operator

declarar variables en postgresql



El operador de asignación olvidado "=" y el lugar común ":=" (4)

La documentación para PL / pgSQL dice que la declaración y asignación a variables se hace con := . Pero un simple, más corto y más moderno (ver pie de página) = parece funcionar como se esperaba:

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

Tenga en cuenta que Pl / pgSQL puede distinguir la asignación y la comparación claramente como se muestra en la línea

WHILE NOT i = 25 LOOP

Entonces, las preguntas son:

  • ¿No encontré alguna sección en los documentos que menciona y / o explica esto?
  • ¿Hay alguna consecuencia conocida usando = lugar de := ?

Editar / nota al pie:

Por favor, tome la parte "más moderna" con un guiño como en Breve, Incompleto, y la mayoría de las malas historia de lenguajes de programación :

1970 - Niklaus Wirth crea Pascal, un lenguaje de procedimiento. Los críticos denuncian inmediatamente a Pascal porque usa la sintaxis "x: = x + y" en lugar de la más familiar como "x = x + y". Esta crítica ocurre a pesar del hecho de que C aún no se ha inventado.

1972 - Dennis Ritchie inventa una poderosa arma que dispara simultáneamente hacia adelante y hacia atrás. No satisfecho con el número de muertes y mutilaciones permanentes de esa invención inventa C y Unix.


Q1

Esto finalmente se ha agregado a la documentación oficial con Postgres 9.4 :

Una asignación de un valor a una variable PL / pgSQL se escribe como:

variable { := | = } expression;

[...] Equal ( = ) se puede usar en lugar de PL / SQL-compatible := .

Q2

¿Hay alguna consecuencia conocida usando = lugar de := ?

, tuve un caso con graves consecuencias : Llamada de función con parámetros nombrados , que está relacionado pero no es exactamente lo mismo.

Estrictamente hablando, la distinción en este caso se hace en código SQL . Pero eso es una diferenciación académica para el programador desprevenido. 1

Considera la función:

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;

Aparte: observe el uso (correcto) de = en la definición de la función. Esa es una asignación de SQL . 2

Llamada de función con notación con nombre:

SELECT * FROM f_oracle(is_true := TRUE);

Postgres identifica := como asignación de parámetros y todo está bien. Sin embargo:

SELECT * FROM f_oracle(is_true = TRUE);

Dado que = es el operador de igualdad de SQL, Postgres interpreta is_true = TRUE como expresión de SQL en el contexto de la instrucción de llamada e intenta evaluarla antes de pasar el resultado como parámetro de posición sin nombre . Busca un identificador is_true en el ámbito externo. Si eso no se puede encontrar:

ERROR: column "is_true" does not exist

Ese es el caso afortunado y, afortunadamente, también el común.

Cuando is_true se puede encontrar en el ámbito externo, is_true = TRUE es una expresión válida con un resultado boolean aceptado por la función. No hay error Claramente, esta es la intención del programador que usa el operador de igualdad de SQL = ...

Este SQL Fiddle demuestra el efecto.

Muy difícil de depurar si no conoce la distinción entre = y := .
Siempre use el operador correcto.

1 Cuando se utiliza la notación con nombre en las llamadas a funciones , solamente := es el operador de asignación correcto. Esto se aplica a las funciones de todos los idiomas, no solo a PL / pgSQL, hasta e incluyendo la página 9.4. Vea abajo.

2 Se puede usar = (o DEFAULT ) para definir los valores predeterminados para los parámetros de la función . Eso no está relacionado con el problema en cuestión de ninguna manera. Está muy cerca del caso de uso incorrecto.

Postgres 9.0 - 9.4: Transición de := a =>

El estándar de SQL para la asignación a parámetros de función nombrados es => (y PL / SQL de Oracle lo usa . Postgres no pudo hacer lo mismo, dado que el operador había sido previamente reservado, por lo que está utilizando el operador de asignación PL / pgSQL := lugar. lanzamiento de Postgres 9.0 el uso de => para otros fines ha sido desaprobado. Por notas de la versión :

Despreciar el uso de => como nombre de operador (Robert Haas)

Las versiones futuras de PostgreSQL probablemente rechazarán este nombre de operador por completo, para admitir la notación estándar de SQL para los parámetros de función nombrados. Por el momento, todavía está permitido, pero se emite una advertencia cuando se define dicho operador.

Si debe usar => para otra cosa, cese y desista. Se romperá en el futuro.

Postgres 9.5: use => ahora

Comenzando con esta versión, se usa el operador estándar SQL => . := todavía es compatible con compatibilidad con versiones anteriores. Pero use el operador estándar en el nuevo código que no necesita ejecutarse en versiones anteriores.

Nota importante: Esto solo se aplica a la asignación de parámetros nombrados en llamadas a funciones (ámbito SQL), no al operador de asignación := en código plpgsql, que permanece sin cambios.


En el analizador PL / PgSQL, el operador de asignación se define como

assign_operator : ''='' | COLON_EQUALS ;

Esta es una característica heredada, presente en el código fuente desde 1998, cuando se introdujo, como podemos ver en el repositorio PostgreSQL Git .

A partir de la versión 9.4 está documentado oficialmente .

Esta idiosincrasia - de tener dos operadores para lo mismo - se planteó en la lista de usuarios de pgsql, y algunas personas solicitaron su eliminación, pero aún se mantiene en el núcleo porque el corpus justo del código heredado se basa en ella.

Vea este mensaje de Tom Lane (desarrollador principal de Pg) .

Por lo tanto, para responder a sus preguntas directamente:

¿No encontré alguna sección en los documentos que menciona y / o explica esto?

No lo encontraste porque no estaba documentado, lo cual se corrigió a partir de la versión 9.4.

¿Hay alguna consecuencia conocida usando = en lugar de: =.

No hay consecuencias secundarias de usar = , pero debe usar : = para la asignación para hacer que su código sea más legible, y (como un efecto secundario) más compatible con PL / SQL.

Actualización: puede haber una consecuencia secundaria en escenarios raros (ver la respuesta de Erwin)

ACTUALIZACIÓN: respuesta actualizada gracias a la entrada de Daniel, Sandy y otros.


Lectura de la documentación de Postgresql 9:

Esta página muestra "=" como un operador de asignación en la tabla de precedencia del operador.

Pero, curiosamente, esta página (documentación del operador de asignación) no lo menciona.


Una respuesta parcial a mi propia pregunta:

La sección PL / pgSQL Obtención del estado del resultado muestra dos ejemplos usando una sintaxis especial:

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

Intenté ambos := y = y funcionan ambos.

Pero GET DIAGNOSTICS es una sintaxis especial, por lo que se puede argumentar, que esta tampoco es una operación de asignación PL / pgSQL normal.