简体   繁体   中英

Execute dynamic prepared statement inside a trigger

I want to use my trigger for logging purposes - every time, when a user inserts something or makes updates, there should appear a new row in my history table. I already have a trigger, which works good. Now it runs every time, when I do inserts. This is how it looks like:

CREATE OR REPLACE FUNCTION public.trigger_history_insert()
    RETURNS trigger AS
$BODY$ 
DECLARE 
    ...
BEGIN
    ... it does a lot of things here and works absolutely correctly
END; 
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION public.trigger_history_insert()
OWNER TO postgres;

Now I want to add logging into this trigger. I tried to follow these two official tutorials ( [1] , [2] ), but ended in failure. This was my first attempt:

DECLARE
    ...
BEGIN
    ... everything remains unchanged except this part
    EXEC SQL BEGIN DECLARE SECTION;
    const char *stmt = 'INSERT INTO history (field1) VALUES (?)';
    EXEC SQL END DECLARE SECTION;        
    EXEC SQL PREPARE mystmt FROM :stmt;
    EXEC SQL EXECUTE mystmt USING new.field1;
END;

In this case I get syntax error pointing to this line of code:

EXEC SQL BEGIN DECLARE SECTION;
^

This was my second attempt:

BEGIN
    ... everything remains unchanged except this part
    BEGIN DECLARE SECTION;
    const char *stmt = 'INSERT INTO history (field1) VALUES (?)';
    END DECLARE SECTION;        
    PREPARE mystmt FROM :stmt;
    EXECUTE mystmt USING new.field1;
END;

Now, I get an error message pointing to this line:

BEGIN DECLARE SECTION;
^

This was my third attempt:

$BODY$
DECLARE
    ...
    const char *stmt = 'INSERT INTO history (field1) VALUES (?)'
BEGIN
    ...
    PREPARE mystmt FROM :stmt;
    EXECUTE mystmt USING new.field1;
END

Now I get an error message pointing to this line:

const char *stmt = 'INSERT INTO history ...
^

This was my last attempt:

$BODY$
DECLARE
    ...
    stmt text := 'INSERT INTO history (field1) VALUES (?)'
BEGIN
    ...
    PREPARE mystmt FROM :stmt;
    EXECUTE mystmt USING new.field1;
END

And in this final case, the error message points to this line:

PREPARE mystmt FROM :stmt;
               ^

So, what am I doing wrong and how can I fix it?

You are mixing up PL/pgSQL , a language for writing functions in the database, and ecpg , which is used for embedding database access in C client code.

The correct solution would look like this:

INSERT INTO history (field1) VALUES (NEW.field1);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM