Autor Zpráva
Jakub156
Profil *
Zdravím, v PgSQL se snazim udelat (svuj prvni) trigger, ktery pri updatu tabulky users zapise do sloupce usr_fulltext v teze tabulce nejaky text. Updatuje se vzdy jen jeden radek. Pouzivam k tomu nasledujici funkci:


CREATE OR REPLACE FUNCTION "public"."update_usr_fulltext" () RETURNS trigger AS
$body$
DECLARE
BEGIN

UPDATE users SET usr_fulltext = 'nejaky text'
WHERE usr_id = OLD.usr_id;

RETURN OLD;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;


Problem je v tom, ze nevim, jak te funkci rict, aby provedla zmenu prave v tom radku, nad kterym byl prave proveden update. Myslel jsem (vycetl ruzne po internetech) ze by mi mely pomoci klicova slova NEW, resp. OLD a ruzne je tedy kombinoval v klauzili WHERE (momentalne tam vidite WHERE usr_id = OLD.usr_id, ale zkousel jsem snad vsechny varianty [i bez new, old])

Vzdy to ale vyhodi nasledujici chybu:

ERROR: record "old" is not assigned yet
DETAIL: The tuple structure of a not-yet-assigned record is indeterminate.
CONTEXT: PL/pgSQL function "update_usr_fulltext" line 4 at SQL statement


pripadne ERROR: record "new" is not assigned yet ... ..zalezi, zda zrovna ve WHERE pouzivam driv NEW.usr_id = .... nebo OLD.usr_id = .....


Napada vas, jakym zpusobem te fci rict, at zapisuje prave do toho zrovna updatovaneho radku? Za kazdou radu predem diky, jsem uz docela zoufalej
Mastodont
Profil
Jak vypadá CREATE TRIGGER?
Jakub156
Profil *
CREATE TRIGGER "trg_update_usr_fulltext" AFTER INSERT OR UPDATE
ON "public"."users" FOR EACH STATEMENT
EXECUTE PROCEDURE "public"."update_usr_fulltext"();
Mastodont
Profil
Jakub156
Máš tam FOR EACH STATEMENT, takže OLD a NEW vůbec nelze používat, protože jsou NULL. Potřebuješ FOR EACH ROW
http://www.postgresql.org/docs/8.1/static/plpgsql-trigger.html
Jakub156
Profil *
to jsem tam samozrejme zkousel taky, vysledek bylo zase to, ze to vypisuje jeden a ten samej error v cyklu (cyklus ukonci asi az postgre nasilne)

jedna se o tento error:

SQL statement "UPDATE users SET usr_fulltext = 'nejaky text' WHERE usr_id = $1 "
PL/pgSQL function "update_usr_fulltext" line 4 at SQL statement
Jakub156
Profil *
omluva, kompletni error vypada takto:

--->ERROR: stack depth limit exceeded
HINT: Increase the configuration parameter "max_stack_depth", after ensuring the platform's stack depth limit is adequate.
CONTEXT: SQL statement "UPDATE users SET usr_fulltext = 'OK, funguje' WHERE usr_id = $1 "


SQL statement "UPDATE users SET usr_fulltext = 'nejaky text' WHERE usr_id = $1 "
PL/pgSQL function "update_usr_fulltext" line 4 at SQL statement


SQL statement "UPDATE users SET usr_fulltext = 'nejaky text' WHERE usr_id = $1 "
PL/pgSQL function "update_usr_fulltext" line 4 at SQL statement


SQL statement "UPDATE users SET usr_fulltext = 'nejaky text' WHERE usr_id = $1 "
PL/pgSQL function "update_usr_fulltext" line 4 at SQL statement

......
Mastodont
Profil
Já si nevšimnul, že to je stejná tabulka!! No to je pak vcelku jasné, že se ti to zacyklí.
NEW.usr_fulltext := 'nejaky text';
RETURN NEW;

A udělej z toho BEFORE trigger. Nemám teď nikde PG po ruce, ale tak nějak to bude :-)
Jakub156
Profil *
mohl by jsi prosim napsat ten kod trosku sirsi? protoze me to pri snaze zmenit trigger na

DECLARE
BEGIN

UPDATE users SET NEW.usr_fulltext := 'nejaky text';

RETURN NEW;
END;


vypise error:

ERROR: syntax error at or near "$1"
LINE 1: UPDATE users SET $1 := 'nejaky text'
^
QUERY: UPDATE users SET $1 := 'nejaky text'
CONTEXT: SQL statement in PL/PgSQL function "update_usr_fulltext" near line 4




jinak tedy nastaveno na BEFORE a na FOR EACH ROW


jinak jsem teda zkusil ciste to

DECLARE
BEGIN

NEW.usr_fulltext := 'nejaky text';


RETURN NEW;
END;

coz vraci zase ten samy error jako prvne (record "new" is not assigned yet)
Mastodont
Profil
CREATE OR REPLACE FUNCTION "public"."update_usr_fulltext" () RETURNS trigger AS
$body$
DECLARE
BEGIN

NEW.usr_fulltext := 'nejaky text';
RETURN NEW;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;

CREATE TRIGGER "trg_update_usr_fulltext" BEFORE INSERT OR UPDATE
ON "public"."users" FOR EACH ROW
EXECUTE PROCEDURE "public"."update_usr_fulltext"();
Jakub156
Profil *
Mastodont: no mazec. Jede to, díky moc! :)
Toto téma je uzamčeno. Odpověď nelze zaslat.