column "i" does not exist - sql

I was created a trigger on my table.When insert/update/delete its adds a key i,u,d like that.
And i'm trying to insert this keys on another table but gives me error like that:
ERROR: column "i" does not exist
LINE 1: ...(operation,stamp,userid,empname,salary) VALUES('||i||', now(...
^
QUERY: SELECT dblink_exec('INSERT INTO emp_audit(operation,stamp,userid,empname,salary) VALUES('||i||', now(), user,NEW.*)')
CONTEXT: PL/pgSQL function process_emp_audit() line 14 at PERFORM
********** Error **********
ERROR: column "i" does not exist
SQL state: 42703
Context: PL/pgSQL function process_emp_audit() line 14 at PERFORM
i don't know why it's give me this error.And this is my trigger function
-- Function: process_emp_audit()
-- DROP FUNCTION process_emp_audit();
CREATE OR REPLACE FUNCTION process_emp_audit()
RETURNS trigger AS
$BODY$
BEGIN
PERFORM dblink_connect('dbname=ekders port=5432 user=****** password=*****');
IF (TG_OP = 'DELETE') THEN
PERFORM dblink_exec('INSERT INTO emp_audit "D", now(), user, OLD.*;');
PERFORM dblink_disconnect();
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
PERFORM dblink_exec('INSERT INTO emp_audit "U", now(), user, NEW.*;');
PERFORM dblink_disconnect();
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
PERFORM dblink_exec('INSERT INTO emp_audit(operation,stamp,userid,empname,salary) VALUES('||i||', now(), user,NEW.*)');
PERFORM dblink_disconnect();
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION process_emp_audit()
OWNER TO postgres;

Your code is attempting to concatenate a value i, which doesn't exist, to the string. I suspect what you really wanted to do was escape the single quotes. The below should work:
PERFORM dblink_exec('INSERT INTO emp_audit(operation,stamp,userid,empname,salary) VALUES(''i'', now(), user,NEW.*)');

Related

How can a Postgres trigger `AFTER UPDATE FOR EACH STATEMENT` correlate its `OLD TABLE` and `NEW TABLE`?

After upgrading from Postgres 9.5 to 11, I am trying to replace the following FOR EACH ROW trigger with a FOR EACH STATEMENT trigger which I hope would be more efficient for my specific use-case:
CREATE OR REPLACE FUNCTION audit_update_operations()
RETURNS TRIGGER
AS
$$
DECLARE
audit_user UUID;
data_before TEXT;
data_after TEXT;
BEGIN
audit_user := coalesce(current_setting('audit.AUDIT_USER', TRUE), '77777777-0000-7777-0000-777777777777')::UUID;
data_before := ROW (old.*);
data_after := ROW (new.*);
INSERT INTO dml_audit_log
(changed_at,
user_id,
operation,
table_name,
data_after,
data_before)
VALUES (now(),
audit_user,
'U',
tg_table_name::TEXT,
data_after,
data_before);
RETURN new;
END ;
$$
LANGUAGE plpgsql;
I thought this was pretty easy:
CREATE OR REPLACE FUNCTION audit_update_operations()
RETURNS TRIGGER
AS
$$
DECLARE
user_id UUID;
BEGIN
user_id := coalesce(current_setting('audit.AUDIT_USER', TRUE), '77777777-0000-7777-0000-777777777777')::UUID;
INSERT INTO dml_audit_log
SELECT now() AS changed_at,
user_id,
'U' AS operation,
tg_table_name::TEXT AS table_name,
ROW (new_table.*) AS data_after,
ROW (old_table.*) AS data_before
FROM new_table;
RETURN NULL;
END ;
$$
LANGUAGE plpgsql;
which is called generically for every table via the following trigger:
EXECUTE ('
CREATE TRIGGER trigger_audit_update
AFTER UPDATE ON ' || tablename || '
REFERENCING
OLD TABLE AS old_table
NEW TABLE AS new_table
FOR EACH STATEMENT
EXECUTE PROCEDURE audit_update_operations()');
but an UPDATE statement triggering this function results in the following error:
[42P01] ERROR: missing FROM-clause entry for table "old_table" Where: PL/pgSQL function shared.audit_update_operations() line 7 at SQL statement
The question I am struggling with is:
How can I correlate the old and new rows without making any assumption about the table being changed?
The tables I am triggering on may or may not have a primary key. Even if they do, I would not know its name or column(s) in the trigger function.
Are the rows in OLD TABLE and NEW TABLE guaranteed to be in the same order? I cannot rely on undocumented implementation details that may change.

Trigger not being called, why?

So I have the following function that the trigger calls when I insert rows into a table called 'auxi'. It seems not to work since I have the value 'id_usuario' with NULL on my table and the trigger is supposed to avoid that.
CREATE OR REPLACE FUNCTION firstRestriction() RETURNS Trigger
AS $$
DECLARE
operation boolean = false;
BEGIN
RAISE NOTICE 'HERE %',operation;
operation = operation OR isNULL(new.periodo, 'periodo');
operation = operation OR isNULL(new.id_usuario, 'id_usuario');
operation = operation OR isNULL(new.fecha_hora_retiro, 'fecha_hora_retiro');
operation = operation OR isNULL(new.origen_estacion, 'origen_estacion');
operation = operation OR isNULL(new.destino_estacion, 'destino_estacion');
operation = operation OR isNULL(new.tiempo_uso, 'tiempo_uso');
/*operation = operation OR isLessThanZero(new.tiempo_uso, 'tiempo_uso');*/
IF operation THEN
raise notice 'No se pudo insertar % % % % % %',new.periodo, new.id_usuario, new.fecha_hora_retiro,new.origen_estacion
,new.destino_estacion, new.tiempo_uso;
return NULL;
ELSE
return new;
END IF;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER checkFirstRestriction
BEFORE INSERT ON auxi
FOR EACH ROW
EXECUTE PROCEDURE firstRestriction();
And then I do
CREATE OR REPLACE FUNCTION cond1()
RETURNS VOID AS $$
BEGIN
INSERT INTO auxi
SELECT *
FROM datos_recorrido;
END;
$$ LANGUAGE PLPGSQL;
Also isNull is the following function
CREATE OR REPLACE FUNCTION isNULL(field anyelement, information TEXT) RETURNS boolean
AS $$
BEGIN
IF field IS NULL THEN
raise notice 'El campo % es NULL', information;
return true;
ELSE
return false;
END IF;
END;
$$ LANGUAGE plpgsql;
And then at certain point I call my funciton cond1().
I think my trigger is never being called. Could that be possible?

Accessing current row values in a trigger

I created a function will insert a value into a json for each row inserted in a table.
But when I execute the insert, it says me that the column doesn't exist.
Here is the function :
CREATE OR REPLACE FUNCTION insert_id_function()
RETURNS trigger AS'
BEGIN
NEW.previewcontent = previewcontent || ''{"id":1}'';
RETURN NEW;
END;'
LANGUAGE plpgsql VOLATILE;
Here is the trigger :
CREATE TRIGGER insert_id_trigger
BEFORE INSERT
ON "Telnet"
FOR EACH ROW
EXECUTE PROCEDURE insert_id_function();
Here is the error :
`ERROR: column "previewcontent" does not exist LINE 1: SELECT previewcontent || '{"id":1}'`
Here is my table definition :
This is a column of the NEW record:
NEW.previewcontent = NEW.previewcontent || ''{"id":1}'';
If the type of previewcontent is jsonb use jsonb_build_object() to add the current value of id to the jsonb column:
CREATE OR REPLACE FUNCTION insert_id_function()
RETURNS trigger AS $$
BEGIN
NEW.previewcontent = NEW.previewcontent || jsonb_build_object('id', NEW.id);
RETURN NEW;
END;
$$ LANGUAGE plpgsql VOLATILE;

how to get current row value in plpgsql function

I need to create plpgsql methods which use current row value without passing in parameter in update command.
I tried
create temp table test ( test text, result text ) on commit drop;
insert into test values ('1','');
CREATE OR REPLACE FUNCTION public.gettest() RETURNS text AS $$
DECLARE
comp text := NULL;
BEGIN
EXECUTE 'SELECT ''Current row is '' ||test.test' INTO comp;
RETURN comp;
END; $$ LANGUAGE plpgsql STRICT STABLE;
update test set result = 'Result: ' || gettest();
but got exception
ERROR: missing FROM-clause entry for table "test"
LINE 1: SELECT 'Current row is ' ||test.test
^
QUERY: SELECT 'Current row is ' ||test.test
CONTEXT: PL/pgSQL function gettest() line 6 at EXECUTE statement
********** Error **********
ERROR: missing FROM-clause entry for table "test"
SQL state: 42P01
Context: PL/pgSQL function gettest() line 6 at EXECUTE statement
How to fix ?
How to fix without passing vaue to plpgsql method parameter ?
There is no such thing as an "implicit current row". You have to pass the the function whatever it needs as a parameter. You can however pass a complete row if you want to:
create temp table test (val text, result text ) on commit drop;
insert into test values ('1','');
insert into test values ('2','');
CREATE OR REPLACE FUNCTION gettest(p_test test) RETURNS text AS $$
DECLARE
comp text := NULL;
BEGIN
comp := 'Current row is '||p_test.val;
RETURN comp;
END; $$ LANGUAGE plpgsql STRICT STABLE;
update test set result = 'Result: ' || gettest(test);
I had to rename the column test to something else, otherwise the call gettest(test) would refer to the column not the whole table (=row) and thus it didn't work.

Assign a constant value in a trigger function

I am learning triggers in PostgreSQL.
I have created a trigger function update_name():
CREATE OR REPLACE FUNCTION update_name()
RETURNS trigger AS
$BODY$
BEGIN
NEW.name := "ankit";
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION update_name()
OWNER TO postgres;
My table user_table is:
CREATE TABLE user_table (
name character varying(20) NOT NULL,
password character varying(20),
email character varying(20),
gender character varying(20),
phone bigint,
CONSTRAINT user_table_pkey PRIMARY KEY (name)
);
and the trigger for the table is :
CREATE TRIGGER "change-name"
BEFORE INSERT OR UPDATE
ON user_table
FOR EACH ROW
EXECUTE PROCEDURE update_name();
when I am inserting data to my table using query:
INSERT INTO user_table(name, password, email, gender, phone)
VALUES ('aa', '9874', 'poi#ka.in', 'male', 8978987896);
I've got the error:
ERROR: column "ankit" does not exist
LINE 1: SELECT "ankit"
^
QUERY: SELECT "ankit"
CONTEXT: PL/pgSQL function update_name() line 3 at assignment
********** Error **********
ERROR: column "ankit" does not exist
SQL state: 42703
Context: PL/pgSQL function update_name() line 3 at assignment
What am I doing wrong?
This is about PostgreSQL syntax. I removed irrelevant references to pgAdmin from the question.
In Postgres, literal values (constants) are enclosed in single quotes: 'value'.
Double quotes are reserved for identifiers but optional as long as it consists of legal, lower-case letters: "Odd Name" vs. odd_name.
This is also the SQL standard. Start by reading the chapter "Lexical Structure" in the manual.
The ERROR has gone by changing just:
NEW.name := "ankit";
to
NEW.name := 'ankit';
Why is it so???
CREATE OR REPLACE FUNCTION update_name()
RETURNS trigger AS
$BODY$
BEGIN
RAISE NOTICE 'RECORD IS INSERTED %',NEW.name;
INSERT INTO user_table VALUES("ankit",NEW.password,NEW.email,NEW.gender,NEW.phone);
RETURN NEW;
end if;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION update_name()
OWNER TO postgres;
Try this out this will help you.