eu tenho uma mesa chamada livro
CREATE TABLE book
(
id smallint NOT NULL DEFAULT 0,
bname text,
btype text,
bprices numeric(11,2)[],
CONSTRAINT key PRIMARY KEY (id )
)
e uma função 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;
agora quando eu chamo a função
SELECT save_book('(179,the art of war,fiction,{190,220})'::book);
eu recebo o erro
ERROR: malformed array literal: "{190"
SQL state: 22P02
Character: 18
Eu não entendo porque não vejo nenhum erro no formato da matriz, alguma ajuda?
ave_book((179,the art of war,fiction,'{190,220}')::book
. A linha construída não precisa de aspas.ERROR: syntax error at or near "art"
ave_book((179, 'the art of war', 'fiction', '{190,220}')::book
, como Andriy disse.Respostas:
Esse tipo de coisa fica complicado. Estou trabalhando em alguns projetos relacionados no momento. O ajuste básico é que o PostgreSQL usa um formato que usa aspas duplas internamente na representação de tupla para representar valores literais, portanto:
Deveria trabalhar. Em essência, um truque interessante é criar um csv e incluir identificadores de tupla ou matriz. O grande problema é que você precisa lidar com a fuga (duplicando aspas em todos os níveis, conforme necessário). Portanto, o seguinte é exatamente equivalente:
A segunda abordagem é usar um construtor de linha:
A primeira solução tem a vantagem óbvia de poder tirar proveito das estruturas de programação existentes para geração e escape de CSV. O segundo é o mais limpo no SQL. Eles podem ser misturados e combinados.
fonte
Se você já se perguntou sobre a sintaxe correta para um tipo de linha, pergunte ao Postgres. Deve saber:
O que retornará uma representação de texto da sua linha em formato válido:
Os valores das colunas são representados como uma lista sem aspas, separada por vírgulas, entre parênteses.
Aspas duplas são usadas em torno de valores, se houver ambiguidade - incluindo texto com espaço em branco. Enquanto nesse caso específico as aspas duplas
"the art of war"
são opcionais, as aspas duplas"{190,220}"
são necessárias para uma matriz.Coloque a sequência entre aspas simples, modifique e teste:
Função revisada
Considere o que discutimos na pergunta anterior relacionada:
Problema com o tipo composto em uma função UPSERT
Um separado bloco (
BEGIN .. END;
) só é útil se você quiser pegar aEXCEPTION
umINSERT
aumento de força. Como um bloco com exceção carrega alguma sobrecarga, faz sentido ter um bloco separado que talvez nunca seja inserido:Senão, simplifique :
Eu também simplifiquei sua
INSERT
declaração. É seguro omitir a lista de colunas do INSERT sob as circunstâncias especificadas.fonte
Embora eu não veja a real vantagem da sua solução, quero dizer passar uma linha para a função em vez de passar os valores individuais como em
De qualquer forma, sua solução também funcionará se você chamar a função corretamente:
Ou seja, a expressão de registro não precisa ser citada, enquanto os valores de texto e a matriz literal precisam.
fonte