Ich habe einen Tisch namens Buch
CREATE TABLE book
(
id smallint NOT NULL DEFAULT 0,
bname text,
btype text,
bprices numeric(11,2)[],
CONSTRAINT key PRIMARY KEY (id )
)
und eine Funktion 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;
jetzt, wenn ich die Funktion aufrufe
SELECT save_book('(179,the art of war,fiction,{190,220})'::book);
Ich bekomme den Fehler
ERROR: malformed array literal: "{190"
SQL state: 22P02
Character: 18
Ich verstehe nicht, weil ich keinen Fehler im Format des Arrays sehe, irgendeine Hilfe?
ave_book((179,the art of war,fiction,'{190,220}')::book
. Die konstruierte Zeile benötigt keine Anführungszeichen.ERROR: syntax error at or near "art"
ave_book((179, 'the art of war', 'fiction', '{190,220}')::book
, genau wie Andriy gesagt hat.Antworten:
So etwas wird kompliziert. Ich arbeite gerade an einigen verwandten Projekten. Die grundlegende Optimierung besteht darin, dass PostgreSQL ein Format verwendet, das intern doppelte Anführungszeichen in der Tupeldarstellung verwendet, um Literalwerte darzustellen.
sollte arbeiten. Im Wesentlichen besteht ein netter Trick darin, eine CSV zu erstellen und Tupel- oder Array-IDs einzuschließen. Das große Problem ist, dass Sie sich mit dem Entkommen auseinandersetzen müssen (Anführungszeichen auf jeder Ebene nach Bedarf verdoppeln). Das Folgende ist also genau gleichbedeutend:
Der zweite Ansatz besteht darin, einen Zeilenkonstruktor zu verwenden:
Die erste Lösung hat den offensichtlichen Vorteil, dass vorhandene Programmierframeworks für die CSV-Generierung und das Entkommen genutzt werden können. Der zweite ist in SQL am saubersten. Sie können gemischt und angepasst werden.
quelle
Wenn Sie sich jemals über die richtige Syntax für einen Zeilentyp Gedanken machen, fragen Sie Postgres. Es sollte wissen:
Dadurch wird eine Textdarstellung Ihrer Zeile im gültigen Format zurückgegeben:
Spaltenwerte werden als nicht in Anführungszeichen stehende, durch Kommas getrennte Liste dargestellt, die in Parethesen eingeschlossen ist.
Doppelte Anführungszeichen werden um Werte verwendet, wenn Mehrdeutigkeiten auftreten können - einschließlich Text mit Leerzeichen. Während in diesem speziellen Fall die doppelten Anführungszeichen
"the art of war"
optional sind, sind die doppelten Anführungszeichen"{190,220}"
für ein Array erforderlich.Schließen Sie die Zeichenfolge in einfache Anführungszeichen ein, ändern und testen Sie:
Funktion überprüft
Überlegen Sie, was wir unter der entsprechenden vorhergehenden Frage besprochen haben:
Problem mit dem zusammengesetzten Typ in einer UPSERT-Funktion
Ein separater Block (
BEGIN .. END;
) ist nur dann sinnvoll , wenn Sie die fangen wollenEXCEPTION
eineINSERT
Macht erhöhen. Da ein Block mit Ausnahme einen gewissen Overhead mit sich bringt, ist es sinnvoll, einen separaten Block zu haben, der möglicherweise nie eingegeben wird:Sonst vereinfachen :
Ich habe auch Ihre
INSERT
Aussage vereinfacht . Unter den gegebenen Umständen ist es sicher, die Spaltenliste in INSERT wegzulassen.quelle
Obwohl ich den wirklichen Vorteil Ihrer Lösung nicht sehe, meine ich, eine Zeile an die Funktion zu übergeben, anstatt die einzelnen Werte wie in zu übergeben
Auf jeden Fall funktioniert Ihre Lösung auch, wenn Sie die Funktion korrekt aufrufen:
Das heißt, der Datensatzausdruck muss nicht in Anführungszeichen gesetzt werden, während dies bei den Textwerten und dem Array-Literal der Fall ist.
quelle