Triggerfunktion Ãœbergabevariable

hallo,

ich bin noch relativ neu in postgres und habe gestern das erste mal mit Triggern rum experimentiert. Jedoch wollte das alles nicht so hin hauen.

Mein Ziel ist es in der Funktion einen Wert abzufragen, diesen in eine Variable zu speichern und dann später in der Funktion zu verwenden.
orientiert habe ich mich an diesem Thread http://www.pg-forum.de/trigger-und-funktionen/2885-datensatz-trigger-bergeben-function.html

ich pack euch einfach mal den code rein, vielleicht weiß jemand Rat.

meine Variable soll fsidwert heißen. und dann später mittels der zahl Tabellen und Regeln erstellen.

create or replace function testtrigger() returns TRIGGER AS '
Declare 
  fsidwert integer;
  Begin
    Select currval('fsid') INTO fsidwert;
    
    create table fs_hourly_fsidwert
    CHECK (fsid = fsidwert) INHERITS(fs_hourly);
    
    create rule fs_hourly_fsidwert_rule 
    AS ON INSERT TO fs_hourly
    WHERE fsid = fsidwert
    DO INSTEAD INSERT INTO
    fs_hourly_fsidwert (fsid, datum, mean_used, sum_used, mean_Free, sum_free, n) 
    VALUES (new.fsid, new.datum, new.mean_Used, new.sum_used, new.mean_Free, new.sum_free, new.n); 
    
...
paar mehr sachen
...
  End; 
' LANGUAGE 'plpgsql';

Schonmal vielen dank im vorraus

Das ist keine sinnvolle Fehlerbeschreibung.

Mein Ziel ist es in der Funktion einen Wert abzufragen, diesen in eine Variable zu speichern und dann später in der Funktion zu verwenden.

Dies an sich ist kein Problem.

orientiert habe ich mich an diesem Thread > http://www.pg-forum.de/trigger-und-funktionen/2885-datensatz-trigger-bergeben-function.html

ich pack euch einfach mal den code rein, vielleicht weiß jemand Rat.

meine Variable soll fsidwert heißen. und dann später mittels der zahl Tabellen und Regeln erstellen.

Vorweg: so, wie du das versuchst, kann es nicht gehen. Um das zu machen, mußt Du dynamisches SQL ausführen, also, Du bastelst Dir einen String, der Dein SQL enthält, und führst diesen mittels EXECUTE aus.

create or replace function testtrigger() returns TRIGGER AS ’
Declare
fsidwert integer;
Begin
Select currval(‘fsid’) INTO fsidwert;

create table fs_hourly_fsidwert
CHECK (fsid = fsidwert) INHERITS(fs_hourly);
>

Das ist schon mal so für sich gesehen kein gültiges SQL, um eine Tabelle zu erstellen.

Was genau willst Du erreichen, Table-Partitionierung?
\
\
Andreas

habe ich jetzt auch gemerkt. sry
dann jetzt hoffentlich besser:
also ich versuche die Funktion zu erstellen. sprich ich kopier die gesamt funktion in mein frontend hinein. dann kommt die fehlermeldung:

ERROR: syntax error at or near “fsid” at character 120

das dürfte der zeile:

Select currval('fsid') INTO fsidwert;

entsprechen.

fsid ist in meiner tabelle der pk, fals das wichtig sein sollte.



für mich anscheind schon

damit kann ich grad nicht soviel anfangen
meinst du das?

CREATE TRIGGER tafter 
AFTER INSERT ON hostfsmap 
FOR EACH ROW EXECUTE PROCEDURE testtrigger()



bisher habe ich alle meine Tabellen so erstellt.
und die existieren und funktionieren auch
anstatt fsidwert steht halt nur eine Zahl da.

EDIT
ok mir ist grad aufgefallen dass meine klammern um Check herum fehlen. meintest du das damit?
/EDIT

Was genau willst Du erreichen, Table-Partitionierung?

jopps das wollte ich erreichen und habe ich auch schon.


jedoch sollen die tabellen und regeln halt “automatisch” erstellt werden wenn ein neues filesystem in der parents table hinzugefügt wird

Ja, ist wichtig. CURRVAL erwartet nämlich NICHT den Namen einer Spalte, sondern einer Sequence.

… EXECUTE …
damit kann ich grad nicht soviel anfangen
meinst du das?

PostgreSQL: Documentation: Manuals: PostgreSQL 8.3: Basic Statements


bisher habe ich alle meine Tabellen so erstellt.
und die existieren und funktionieren auch
anstatt fsidwert steht halt nur eine Zahl da.

EDIT
ok mir ist grad aufgefallen dass meine klammern um Check herum fehlen. meintest du das damit?
/EDIT

Das auch.

jedoch sollen die tabellen und regeln halt “automatisch” erstellt werden wenn ein neues filesystem in der parents table hinzugefügt wird

[/quote]

test=# create table debaer(id int);
CREATE TABLE
test=*# create or replace function f_debaer() returns trigger as $$declare sql text; begin sql:='create table t_debaer_' || NEW.id || '( id int)'; execute sql; sql:='insert into t_debaer_' || NEW.id || ' values (' || NEW.id || ');'; execute sql; return NULL; end; $$language plpgsql;
CREATE FUNCTION
test=*# create trigger trg_debaer before insert on debaer for each row execute procedure f_debaer();
CREATE TRIGGER
test=*# insert into debaer values (1);
INSERT 0 0
test=*# select * from debaer;
 id
----
(0 rows)

test=*# select * from t_debaer_1;
 id
----
  1
(1 row)

Zu schauen, ob die Tabelle schon existiert, und dann diese nicht anzulegen, überlasse ich Dir zur Übung.


Andreas

na dann habe ich ja jetzt erstmal was zu tun


vielen dank

würde dass funktionieren?

Declare 
  fsidwert integer;
  sql text;
  Begin
    sql := Select fsid INTO fsidwert from hostfsmap order by fsid desc limit 1;
    execute sql;
    
    sql := create table fs_hourly_fsidwert (CHECK (fsid = fsidwert)) INHERITS(fs_hourly);
    execute sql;

kann ich so überhaupt in der variable fsidwert das ergebnis aus dem select speichern?

habe noch nicht so ganz verstanden an welcher stelle die || hinkommen. sonst glaube ich, habe ich dein Beispiel verstanden

Nein.


kann ich so überhaupt in der variable fsidwert das ergebnis aus dem select speichern?

So nicht. Wie es geht, steht aber in der Doku.

habe noch nicht so ganz verstanden an welcher stelle die || hinkommen. sonst glaube ich, habe ich dein Beispiel verstanden

Dort, wo fixer Text (das, was in ‘’ steht und bei Dir fehlt) mit Variablen zu verbinden ist.


Andreas

ok das mit der variable habe ich gefunden

select blub into var 'variablenname'

würde das denn laufen?

sql := 'Select' || fsid || 'INTO var' || 'fsidwert' || 'from' || hostfsmap || 'order by' || fsid || 'desc limit' || 1;
    execute sql;

Warum probierst Du es nicht?

Hint: Leerzeichen sind oft unentbehrlich…, hier, um z.B. Dein ‘Select’ von fsid zu trennen…

Hint2: in der Doku steht u.a.:

EXECUTE command-string [ INTO [STRICT] target ];

Man beachte hierbei insbesondere, wo das INTO steht.


Andreas

hat natürlich nicht funktioniert :wink:
aber das wusstest du bestimmt ja.

habe jetzt alles abgeändert und getestet --> es läuft :astonished:


hier nochmal der code fals andere ein ähnliches problem mal haben

create or replace function testtrigger() returns TRIGGER AS '
Declare 
  fsidwert integer;
  sql text;
  Begin
    sql := '' Select fsid from hostfsmap order by fsid desc limit 1'';
    execute sql into fsidwert;

    raise notice ''deine fsid: %'', fsidwert;
    
    sql := ''create table fs_hourly_''||fsidwert||'' (CHECK (fsid ='' || fsidwert || '')) INHERITS(fs_hourly)'';
    execute sql;     
    
    sql := ''create rule fs_hourly_''||fsidwert||''_rule 
    AS ON INSERT TO fs_hourly
    WHERE fsid = '' || fsidwert || 
    '' DO INSTEAD INSERT INTO
    fs_hourly_''||fsidwert||'' (fsid, datum, mean_used, sum_used, mean_Free, sum_free, n) 
    VALUES (new.fsid, new.datum, new.mean_Used, new.sum_used, new.mean_Free, new.sum_free, new.n)''; 
    execute sql;
    return null;    
  End; 
' LANGUAGE 'plpgsql';

aber eine Frage habe ich noch
wenn ich es mit $$ probiere am Anfang und am ende bekomme ich einen fehler

monitoring=> create or replace function testtrigger() returns TRIGGER AS $$
monitoring-> Declare
monitoring-> fsidwert integer;
ERROR: unterminated dollar-quoted string at or near "$$

musste es daher mit ’ schreiben… woran könnte dieser fehler liegen?



VIELEN VIELEN DANK für deine Hilfe

Das Dollar-Quoting ist zu bevorzugen, weil Du dann innerhalb der Funktion keine doppelten ’ verwenden mußt. Macht die Sache übersichtlicher. Und erklärt auch Deinen Fehler.


Andreas

Das ich dann keine doppelten ’ verwenden muss ist mir klar. Habe ich bei dem Test auch nicht. Trotzdem kam dieser Fehler. Wollte das ja gerne mit Dollar-Quting machen nur dann kam ja halt der Fehler und ich musste alles auf ‘’ ändern und das Dollar-Quoting entfernen.

Weil da auch am Ende ein $$ stehen muss …

ich bin zwar nen Anfänger in sachen postgres und triggern… aber die hatte ich auch am Ende drin


kann ja spaßenshalber ma kurz was testen

create or replace function testtrigger() returns TRIGGER AS $$
Declare 
  fsidwert integer;
  sql text;
  Begin
    sql := ' Select fsid from hostfsmap order by fsid desc limit 1';
    execute sql into fsidwert;


    
    sql := 'create table fs_hourly_'||fsidwert||' (CHECK (fsid =' || fsidwert || ')) INHERITS(fs_hourly)';
    execute sql;     
    
    sql := 'create rule fs_hourly_'||fsidwert||'_rule 
    AS ON INSERT TO fs_hourly
    WHERE fsid = ' || fsidwert || 
    ' DO INSTEAD INSERT INTO
    fs_hourly_'||fsidwert||' (fsid, datum, mean_used, sum_used, mean_Free, sum_free, n) 
    VALUES (new.fsid, new.datum, new.mean_Used, new.sum_used, new.mean_Free, new.sum_free, new.n)'; 
    execute sql;
    
    return null;    
  End; 
$$ LANGUAGE 'plpgsql';

Fehler:

monitoring=> create or replace function testtrigger() returns TRIGGER AS $$
monitoring-> Declare
monitoring->   fsidwert integer;
ERROR:  unterminated dollar-quoted string at or near "$$
Declare
  fsidwert integer;" at character 61
monitoring=>   sql text;
ERROR:  syntax error at or near "sql" at character 3
monitoring=>   Begin
monitoring->     sql := ' Select fsid from hostfsmap order by fsid desc limit 1'
;
ERROR:  syntax error at or near "sql" at character 13
monitoring=>     execute sql into fsidwert;
ERROR:  syntax error at or near "into" at character 17
monitoring=>
monitoring=>
monitoring=>
monitoring=>     sql := 'create table fs_hourly_'||fsidwert||' (CHECK (fsid =' |
| fsidwert || ')) INHERITS(fs_hourly)';
ERROR:  syntax error at or near "sql" at character 5
monitoring=>     execute sql;
ERROR:  prepared statement "sql" does not exist
monitoring=>
monitoring=>     sql := 'create rule fs_hourly_'||fsidwert||'_rule
monitoring'>     AS ON INSERT TO fs_hourly
monitoring'>     WHERE fsid = ' || fsidwert ||
monitoring->     ' DO INSTEAD INSERT INTO
monitoring'>     fs_hourly_'||fsidwert||' (fsid, datum, mean_used, sum_used, mea
n_Free, sum_free, n)
monitoring'>     VALUES (new.fsid, new.datum, new.mean_Used, new.sum_used, new.m
ean_Free, new.sum_free, new.n)';
ERROR:  syntax error at or near "sql" at character 5
monitoring=>     execute sql;
ERROR:  prepared statement "sql" does not exist
monitoring=>
monitoring=>     return null;
ERROR:  syntax error at or near "return" at character 5
monitoring=>   End;
WARNING:  there is no transaction in progress
COMMIT
monitoring=> $$ LANGUAGE 'plpgsql';
ERROR:  unterminated dollar-quoted string at or near "$$ LANGUAGE 'plpgsql';" at
 character 1
monitoring=>



test=# create or replace function testtrigger() returns TRIGGER AS $$
test$# Declare
test$#   fsidwert integer;
test$#   sql text;
test$#   Begin
test$#     sql := ' Select fsid from hostfsmap order by fsid desc limit 1';
test$#     execute sql into fsidwert;
test$#
test$#
test$#
test$#     sql := 'create table fs_hourly_'||fsidwert||' (CHECK (fsid =' || fsidwert || ')) INHERITS(fs_hourly)';
test$#     execute sql;
test$#
test$#     sql := 'create rule fs_hourly_'||fsidwert||'_rule
test$#     AS ON INSERT TO fs_hourly
test$#     WHERE fsid = ' || fsidwert ||
test$#     ' DO INSTEAD INSERT INTO
test$#     fs_hourly_'||fsidwert||' (fsid, datum, mean_used, sum_used, mean_Free, sum_free, n)
test$#     VALUES (new.fsid, new.datum, new.mean_Used, new.sum_used, new.mean_Free, new.sum_free, new.n)';
test$#     execute sql;
test$#
test$#     return null;
test$#   End;
test$# $$ LANGUAGE 'plpgsql';
CREATE FUNCTION

Copy&Paste von Dir…

Andreas

interessant…
woran kann das dann liegen, dass der bei mir so rum zickt?

habs eben extra nochma alles in eine zeile gepackt sodass der keine zeilenumbrüche oder so hat


monitoring=> create or replace function testtrigger() returns TRIGGER AS $$ Decl
are  fsidwert integer; sql text; Begin sql := ' Select fsid from hostfsmap order
 by fsid desc limit 1'; execute sql into fsidwert; sql := 'create table fs_hourl
y_'||fsidwert||' (CHECK (fsid =' || fsidwert || ')) INHERITS(fs_hourly)'; execut
e sql; sql := 'create rule fs_hourly_'||fsidwert||'_rule AS ON INSERT TO fs_hour
ly WHERE fsid = ' || fsidwert || ' DO INSTEAD INSERT INTO fs_hourly_'||fsidwert|
|' (fsid, datum, mean_used, sum_used, mean_Free, sum_free, n) VALUES (new.fsid,
new.datum, new.mean_Used, new.sum_used, new.mean_Free, new.sum_free, new.n)';  e
xecute sql; return null; End; $$ LANGUAGE 'plpgsql';
ERROR:  unterminated dollar-quoted string at or near "$$ Declare  fsidwert integ
er;" at character 61
ERROR:  syntax error at or near "sql" at character 2
ERROR:  syntax error at or near "sql" at character 8
ERROR:  syntax error at or near "into" at character 14
ERROR:  syntax error at or near "sql" at character 2
ERROR:  prepared statement "sql" does not exist
ERROR:  syntax error at or near "sql" at character 2
ERROR:  prepared statement "sql" does not exist
ERROR:  syntax error at or near "return" at character 2
WARNING:  there is no transaction in progress
COMMIT
ERROR:  unterminated dollar-quoted string at or near "$$ LANGUAGE 'plpgsql';" at
 character 2
monitoring=>

Ich mach ja ungern soviel Werbung, aber dieses Thema behandle ich nächste Woche ausführlich in München. Ansonsten zeigte akretschmer schon, dass deine Funktion eigentlich funktioniert.

Ach, echt?

Andreas

wenn du mir die 2.000 euro erlässt gerne… als azubi is sowas noch nicht drin

Pssst: ads und ich machen manchmal sogar kostenlose Workshops…

Andreas