salida recorrer procedimientos procedimiento pasar parametros ejemplo ejecutar array almacenados almacenado sql postgresql stored-procedures plpgsql

sql - recorrer - Pasar una matriz de un tipo compuesto al procedimiento almacenado



procedimiento almacenado sql server ejemplo (2)

Probablemente estoy haciendo algo mal con la formación del literal. Supongamos que tengo un procedimiento almacenado simple como este:

CREATE OR REPLACE FUNCTION do_something(input_array composite_type[]) RETURNS SETOF text AS $BODY$ DECLARE temp_var composite_type; BEGIN FOR temp_var IN SELECT unnest(input_array) LOOP return next temp_var.message; END LOOP; END $BODY$ LANGUAGE plpgsql;

El composite_type se define como:

CREATE TYPE composite_type AS (message text, amount numeric(16,2));

Realizando una consulta como esta:

SELECT * FROM do_something(''{"(test,11)","(test2,22)"}'')

Produce este conjunto de resultados:

(test,11.00) (test2,22.00)

En lugar de:

test test2

¿Hay algo mal con mi literal o debería acceder al campo de message de una manera diferente? Gracias por cualquier sugerencia.


La forma en que especifique su entrada parece estar bien, ya que se observa el mismo comportamiento con la sintaxis del constructor de filas y matrices:

SELECT * FROM do_something( ARRAY[ ROW(''test'',11), ROW(''test2'',22) ]::composite_type[] );

Y:

SELECT ARRAY[ ROW(''test'',11), ROW(''test2'',22) ]::composite_type[];

produce:

''{"(test,11.00)","(test2,22.00)"}''

Si agrega un:

RAISE NOTICE ''!%!'',temp_var;

dentro del ciclo la salida es:

NOTICE: !("(test,11.00)",)! NOTICE: !("(test2,22.00)",)!

mostrando que en realidad está obteniendo una tupla con "mensaje" como el texto en tupla que esperaba y una "cantidad" nula.

Asi que. ¿Por qué?

Es un poco sutil. Estás usando:

SELECT unnest(input_array)

que parece hacer lo que quieres, ¿verdad?

regress=> SELECT unnest( ARRAY[ ROW(''test'',11), ROW(''test2'',22) ]::composite_type[] ); unnest --------------- (test,11.00) (test2,22.00) (2 rows)

... pero en realidad, está devolviendo una sola columna del tipo composite_type . La asignación de tipo compuesto PL / PgSQL espera una columna por columna de tipo en su lugar. Entonces, el coll individual se está metiendo en ''mensaje'' y no hay un segundo col.

En cambio, escribe:

SELECT * FROM unnest(input_array)

para desempaquetar el compuesto para la asignación. Entonces funciona como se esperaba:

regress=> SELECT * FROM do_something( ARRAY[ ROW(''test'',11), ROW(''test2'',22) ]::composite_type[] ); do_something -------------- test test2 (2 rows)

Si el primer campo de composite_type fuera de tipo no textual, obtendría un error que era bastante más informativo sobre esto.


Craig explicó bien una razón para este comportamiento: la variable de asignación = valor dentro de la instrucción FORDE espera cero anidamiento. Entonces deberías hacer:

CREATE OR REPLACE FUNCTION do_something(input_array composite_type[]) RETURNS SETOF text AS $BODY$ DECLARE temp_var record; BEGIN -- unnesting FOR temp_var IN SELECT (unnest(input_array)).* LOOP RETURN NEXT temp_var.message; END LOOP; RETURN; END $BODY$ LANGUAGE plpgsql;

o - preferible - uso más reciente SetReturnedFunction dentro de "lista de columnas"

CREATE OR REPLACE FUNCTION do_something(input_array composite_type[]) RETURNS SETOF text AS $BODY$ DECLARE temp_var record; BEGIN -- SELECT FROM FOR temp_var IN SELECT * FROM unnest(input_array) LOOP RETURN NEXT temp_var.message; END LOOP; RETURN; END $BODY$ LANGUAGE plpgsql;