tengo una mesa llamada libro
CREATE TABLE book
(
id smallint NOT NULL DEFAULT 0,
bname text,
btype text,
bprices numeric(11,2)[],
CONSTRAINT key PRIMARY KEY (id )
)
y una función save_book
CREATE OR REPLACE FUNCTION save_book(thebook book)
RETURNS text AS
$BODY$
DECLARE
myoutput text :='Nothing has occured';
BEGIN
update book set
bname=thebook.bname,
btype=thebook.btype,bprices=thebook.bprices WHERE id=thebook.id;
IF FOUND THEN
myoutput:= 'Record with PK[' || thebook.id || '] successfully updated';
RETURN myoutput;
END IF;
BEGIN
INSERT INTO book values(thebook.id,thebook.bname,thebook.btype,
thebook.bprices);
myoutput:= 'Record successfully added';
END;
RETURN myoutput;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ahora cuando llamo a la función
SELECT save_book('(179,the art of war,fiction,{190,220})'::book);
me sale el error
ERROR: malformed array literal: "{190"
SQL state: 22P02
Character: 18
No entiendo porque no veo ningún error en el formato de la matriz, ¿alguna ayuda?
ave_book((179,the art of war,fiction,'{190,220}')::book
. La fila construida no necesita las comillas.ERROR: syntax error at or near "art"
ave_book((179, 'the art of war', 'fiction', '{190,220}')::book
, como dijo Andriy.Respuestas:
Este tipo de cosas se complica. Estoy trabajando en algunos proyectos relacionados en este momento. El ajuste básico es que PostgreSQL usa un formato que usa comillas dobles internamente en representación de tuplas para representar valores literales, por lo tanto:
Deberia trabajar. En esencia, un buen truco es crear un csv y encerrarlo en identificadores de tuplas o matrices. El gran problema es que tiene que lidiar con el escape (duplicando las cotizaciones en todos los niveles según sea necesario). Entonces lo siguiente es exactamente equivalente:
El segundo enfoque es usar un constructor de filas:
La primera solución tiene la ventaja obvia de poder aprovechar los marcos de programación existentes para la generación y el escape de CSV. El segundo es más limpio en SQL. Se pueden mezclar y combinar.
fuente
Si alguna vez se pregunta acerca de la sintaxis correcta para un tipo de fila, pregunte a Postgres. Debe saber:
Lo que devolverá una representación de texto de su fila en formato válido:
Los valores de las columnas se representan como una lista sin comillas, separada por comas, encerrada entre paréntesis.
Las comillas dobles se usan alrededor de los valores, si puede haber ambigüedad, incluido el texto con espacios en blanco. Si bien en este caso particular las comillas dobles
"the art of war"
son opcionales, las comillas dobles"{190,220}"
son necesarias para una matriz.Encierre la cadena entre comillas simples, modifique y pruebe:
Función revisada
Considere lo que discutimos en la pregunta anterior relacionada:
Problema con el tipo compuesto en una función UPSERT
Un bloque separado (
BEGIN .. END;
) solo es útil si desea capturarEXCEPTION
unINSERT
aumento de poder. Dado que un bloque con excepción conlleva cierta sobrecarga, tiene sentido tener un bloque separado que nunca podría ingresarse:De lo contrario, simplifique :
También simplifiqué tu
INSERT
declaración. Es seguro omitir la lista de columnas de INSERT en las circunstancias dadas.fuente
Si bien no veo la ventaja real de su solución, me refiero a pasar una fila a la función en lugar de pasar los valores individuales como en
De todos modos, su solución también funciona si llama a la función correctamente:
Es decir, la expresión de registro no necesita comillas, mientras que los valores de texto y la matriz literal sí.
fuente