Ich habe eine Funktion in PostgreSQL 9.1 aufgerufen fun_test
. Es hat einen zusammengesetzten Typ als Eingabeparameter und ich erhalte immer wieder einen Casting-Fehler, wenn ich ihn aufrufe.
CREATE OR REPLACE FUNCTION netcen.fun_test(myobj netcen.testobj)
RETURNS boolean AS
$BODY$
DECLARE
tmp_code smallint;
cur_member refcursor;
BEGIN
-- Check if the member exists first
OPEN cur_member FOR
EXECUTE 'SELECT testkey FROM netcen.test WHERE testkey=' || myobj.testkey ;
FETCH cur_member INTO tmp_code;
CLOSE cur_member;
CASE tmp_code
WHEN COALESCE(tmp_code,0)=0 THEN
-- Record not found INSERT a new record
-- will skip user defined validation for now
insert into netcen.test values(myobj.testkey,
myobj.tes,
myobj.testname);
ELSE
-- Record found UPDATE the record
update netcen.test set
test=myobj.test,
testname=myobj.testname WHERE testkey=myobj.testkey;
END CASE;
END;$BODY$
LANGUAGE plpgsql;
Unten ist der Typ testobj
CREATE TYPE netcen.testobj AS
(testkey smallint,
tes text,
testname text);
Wenn ich die Funktion aufrufe:
SELECT netcen.fun_test('(3,[email protected],khaendra)':: netcen.testobj);
.. Ich erhalte folgende Fehlermeldung:
ERROR: operator does not exist: smallint = boolean
LINE 1: SELECT "__Case__Variable_8__" IN (COALESCE(tmp_code,0)=0)
^
HINT: No operator matches the given name and argument type(s).
You might need to add explicit type casts.
QUERY: SELECT "__Case__Variable_8__" IN (COALESCE(tmp_code,0)=0)
CONTEXT: PL/pgSQL function "fun_test" line 11 at CASE
Wo soll ich gießen?
Definition der Tabelle netcen.test
:
CREATE TABLE netcen.test (
testkey smallint NOT NULL DEFAULT 0,
tes netcen.dom_email_validation,
testname text,
CONSTRAINT key PRIMARY KEY (testkey)
)
@ Erwin, danke für die Links. Ich habe meine Funktion gelesen und habe sie geändert. Bitte gehen Sie sie durch und sagen Sie mir, ob sie mit mehreren Clients, die dieselbe Funktion gleichzeitig aufrufen, gut funktioniert.
CREATE OR REPLACE FUNCTION netcen.fun_test_modified(myobj netcen.test)
RETURNS boolean AS
$BODY$
DECLARE
myoutput boolean :=false;
BEGIN
update netcen.test set
tes=myobj.tes,
testname=myobj.testname WHERE testkey=myobj.testkey;
IF FOUND THEN
myoutput:= TRUE;
RETURN myoutput;
END IF;
BEGIN
INSERT INTO netcen.test values(myobj.testkey,
myobj.tes,
myobj.testname);
myoutput:= TRUE;
EXCEPTION WHEN OTHERS THEN
update netcen.test set
tes=myobj.tes,
testname=myobj.testname WHERE testkey=myobj.testkey;
myoutput:= TRUE;
END;
RETURN myoutput;
END;
$BODY$ LANGUAGE plpgsql;
Ich habe die Typprüfung abgeschafft und nur den Tisch benutzt test
! Ich wusste nicht, dass das funktionieren könnte!
quelle
text
. TU es einfach. Wenn Sie auf Probleme stoßen, posten Sie hier eine andere Frage , keinen Kommentar.Während klin in seiner Antwort zur Behebung Ihrer aktuellen Funktion technisch richtig ist, möchte ich Ihren gesamten Ansatz in Frage stellen. Was Sie erreichen möchten, heißt "UPSERT" und mit PostgreSQL 9.1 (das beschreibbare CTEs bietet ) haben Sie eine sehr einfache Möglichkeit, dies zu erreichen. Ich habe die Funktionsdefinition aus Gründen der Übersichtlichkeit weggelassen, aber Sie können sie leicht in eine Abfragesprachenfunktion einschließen (dh mit der Endung
LANGUAGE sql
):Auf diese Weise können Sie die Verwendung eines teuren Cursors und einer noch teureren
EXCEPTION
Klausel vermeiden .Beachten Sie, dass dies im Grunde die gleiche Lösung ist wie eine der mehreren Erwin-Antworten (aus historischen Gründen wurden zwei Fragen mit all ihren Antworten zu einer zusammengefasst). Die Warnung vor Parallelität gilt also auch für diese.
quelle
Einschub von
verwenden
Beachten Sie, dass "tmp_code" klein ist, während "COALESCE (tmp_code, 0) = 0" boolesch ist.
Eine andere Fehlerfunktion gibt einen Booleschen Wert zurück, hat jedoch keine Rückgabeanweisung.
Wenn netcen.test.testkey ein Primärschlüssel ist, können Sie die Ausnahme (39.6.6) verwenden , insbesondere Beispiel 39-2 - es ist genau das, was Sie tun möchten.
quelle