j'ai une table appelée livre
CREATE TABLE book
(
id smallint NOT NULL DEFAULT 0,
bname text,
btype text,
bprices numeric(11,2)[],
CONSTRAINT key PRIMARY KEY (id )
)
et une fonction 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;
maintenant quand j'appelle la fonction
SELECT save_book('(179,the art of war,fiction,{190,220})'::book);
j'ai l'erreur
ERROR: malformed array literal: "{190"
SQL state: 22P02
Character: 18
je ne comprends pas car je ne vois aucune erreur dans le format du tableau, une aide?
ave_book((179,the art of war,fiction,'{190,220}')::book
. La ligne construite n'a pas besoin des guillemets.ERROR: syntax error at or near "art"
ave_book((179, 'the art of war', 'fiction', '{190,220}')::book
, comme l'a dit Andriy.Réponses:
Ce genre de chose se complique. Je travaille actuellement sur des projets connexes. Le tweak de base est que PostgreSQL utilise un format qui utilise des guillemets internes en représentation de tuple pour représenter les valeurs littérales, donc:
devrait marcher. En substance, une astuce consiste à créer un csv et à l'enfermer dans des identificateurs de tuple ou de tableau. Le gros problème est que vous devez gérer l'évasion (doubler les devis à chaque niveau selon les besoins). Donc, ce qui suit est exactement équivalent:
La deuxième approche consiste à utiliser un constructeur de lignes:
La première solution présente l'avantage évident de pouvoir tirer parti des cadres de programmation existants pour la génération et l'échappement CSV. Le second est le plus propre en SQL. Ils peuvent être mélangés et assortis.
la source
Si vous vous posez des questions sur la syntaxe correcte pour un type de ligne, demandez à Postgres. Il faut savoir:
Qui renverra une représentation textuelle de votre ligne dans un format valide:
Les valeurs des colonnes sont représentées sous la forme d'une liste non citée, séparée par des virgules, entourée de paréthèses.
Les guillemets doubles sont utilisés autour des valeurs, s'il peut y avoir une ambiguïté - y compris du texte avec un espace blanc. Alors que dans ce cas particulier, les guillemets doubles
"the art of war"
sont facultatifs, les guillemets doubles"{190,220}"
sont nécessaires pour un tableau.Mettez la chaîne entre guillemets simples, modifiez et testez:
Fonction révisée
Considérez ce que nous avons discuté sous la question précédente connexe:
Problème avec le type composite dans une fonction UPSERT
Un bloc séparé (
BEGIN .. END;
) n'est utile que si vous voulez attraper l'EXCEPTION
anINSERT
pourrait augmenter. Puisqu'un bloc avec exception comporte une surcharge, il est logique d'avoir un bloc séparé qui pourrait ne jamais être entré:Sinon, simplifiez :
J'ai également simplifié votre
INSERT
déclaration. Il est sûr d'omettre la liste des colonnes de INSERT dans les circonstances données.la source
Bien que je ne vois pas le véritable avantage de votre solution, je veux dire passer une ligne à la fonction au lieu de passer les valeurs individuelles comme dans
Quoi qu'il en soit, votre solution fonctionne également si vous appelez correctement la fonction:
Autrement dit, l'expression d'enregistrement n'a pas besoin de guillemet, contrairement aux valeurs de texte et au littéral de tableau.
la source