audit trigger postgres - sql

I want to store my old records in a table when something has changed. I tried to do it with this documentation. But i still get a error. The error is: relation serie doesn't exist.
The original table:
CREATE TABLE "Terra_nub_v1"."Serie"
(
uuid uuid NOT NULL, -- t.b.v. pakbon
serie_nr integer NOT NULL,
aantal_slijpplaten integer,
producent text,
locatie text,
klaar boolean,
onderzocht boolean,
gerapporteerd boolean,
opmerking text,
verwijzing_hoofdrapportage text,
verwijzing_overige_rapportages text,
onderzoeksgebied polygon,
CONSTRAINT "Serie_pkey" PRIMARY KEY (serie_nr)
)
The archive table:
CREATE TABLE "Terra_nub_v1".serie_history
(
uuid uuid NOT NULL,
serie_nr integer NOT NULL,
aantal_slijpplaten integer,
producent text,
locatie text,
klaar boolean,
onderzocht boolean,
gerapporteerd boolean,
opmerking text,
verwijzing_hoofdrapportage text,
verwijzing_overige_rapportages text,
onderzoeksgebied polygon,
datumtijd_wijziging timestamp without time zone,
aangepast_door text,
CONSTRAINT serie_history_pkey PRIMARY KEY (serie_nr)
)
I make the trigger function this way:
CREATE OR REPLACE FUNCTION "Terra_nub_v1".serie_history_trigger()
RETURNS trigger AS $BODY$
BEGIN
IF (TG_OP ='UPDATE') THEN
INSERT INTO Terra_nub_v1.serie_history SELECT OLD.*,NOW(), USER ;
RETURN OLD;
ELSEIF (TG_OP = 'DELETE') THEN
INSERT INTO Terra_nub_v1.serie_history SELECT OLD.*,NOW(), USER ;
RETURN OLD;
END IF;
RETURN NULL;
END;
$BODY$ LANGUAGE plpgsql VOLATILE;
Create Trigger serie_history_trigger
BEFORE UPDATE OR DELETE ON Terra_nub_v1.serie
FOR EACH ROW EXECUTE PROCEDURE process_emp_audit();
I m using postgres
Greetings

Related

How to put argument (table name) of function?

I am using PostgreSQL 14.4 . My script
-- 0.
DROP TABLE IF EXISTS tenant;
CREATE TABLE tenant
(
id smallint primary key,
company_tax_code character varying(14),
period character varying(16), -- 2021070420220705
created timestamp with time zone
);
CREATE OR REPLACE FUNCTION set_id_tenant()
RETURNS trigger AS
$$
DECLARE
BEGIN
new.id = (select coalesce(max(id), -32769) from tenant) + 1;
RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';
CREATE TRIGGER trigger_insert_without_id_tenant
BEFORE INSERT
ON tenant
FOR EACH ROW
EXECUTE PROCEDURE set_id_tenant();
CREATE INDEX tenant_idx ON tenant (id);
COMMIT;
--------------------------------------------------------------------------------
-- 4.
DROP TABLE IF EXISTS account_object_bank_account;
CREATE TABLE account_object_bank_account
(
id smallint,
account_object_id smallint not null,
bank_account character varying(64),
bank_name character varying(128),
bank_id smallint,
sort_order smallint,
bank_branch_name character varying(256),
province character varying(128),
tenant_id smallint,
PRIMARY KEY (id, tenant_id),
CONSTRAINT fk_tenant FOREIGN KEY (tenant_id) REFERENCES tenant (id)
);
CREATE OR REPLACE FUNCTION account_object_bank_account_setId()
RETURNS trigger AS
$$
DECLARE
BEGIN
new.id = (select coalesce(max(id), -32769) from account_object_bank_account where tenant_id = new.tenant_id) + 1;
RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';
CREATE TRIGGER account_object_bank_account_trig_insertWithoutId
BEFORE INSERT
ON account_object_bank_account
FOR EACH ROW
EXECUTE PROCEDURE account_object_bank_account_setId();
CREATE INDEX account_object_bank_account_idx ON account_object_bank_account (id, tenant_id);
COMMENT ON TABLE public.account_object_bank_account IS 'Bảng lưu tài khoản ngân hàng của khách hàng';
COMMENT ON COLUMN public.account_object_bank_account.id IS 'PK';
COMMENT ON COLUMN public.account_object_bank_account.account_object_id IS 'FK';
COMMENT ON COLUMN public.account_object_bank_account.bank_account IS 'Số TK ngân hàng';
COMMENT ON COLUMN public.account_object_bank_account.bank_name IS 'Tên ngân hàng';
COMMIT;
--------------------------------------------------------------------------------
-- 5.
DROP TABLE IF EXISTS account_object_belong_to_group;
CREATE TABLE account_object_belong_to_group
(
id smallint,
account_object_id smallint,
account_object_group_id smallint,
tenant_id smallint,
PRIMARY KEY (id, tenant_id),
CONSTRAINT fk_tenant FOREIGN KEY (tenant_id) REFERENCES tenant (id)
);
CREATE OR REPLACE FUNCTION account_object_belong_to_group_setId()
RETURNS trigger AS
$$
DECLARE
BEGIN
new.id = (select coalesce(max(id), -32769) from account_object_belong_to_group where tenant_id = new.tenant_id) + 1;
RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';
CREATE TRIGGER account_object_belong_to_group_trig_insertWithoutId
BEFORE INSERT
ON account_object_belong_to_group
FOR EACH ROW
EXECUTE PROCEDURE account_object_belong_to_group_setId();
CREATE INDEX account_object_belong_to_group_idx ON account_object_belong_to_group (id, tenant_id);
COMMIT;
--------------------------------------------------------------------------------
I want re-use this custom function, then put argument of function is table name:
account_object_bank_account_setId()
account_object_belong_to_group_setId()
to
set_id( table_name )
argument sample: account_object_bank_account, account_object_belong_to_group.
How to do?
update your 2 triggers with set_id('table_name')
and use TG_ARGV[] to retrieve the parameter in the trigger function
https://www.postgresql.org/docs/14/plpgsql-trigger.html

Postgres string formatting for record ID

I am trying to create a table to keep an archive of dad jokes in Postgres. For the title record, I would like the value to by-default be the joke ID, but formatted in a way where if the id is 7, the record's title is Joke #7. Here is my query to create the table:
CREATE TABLE public.jokes (
id int NOT null primary KEY,
user_id int NOT NULL DEFAULT 1,
title varchar NULL DEFAULT FORMAT("Joke #%s", ), -- the title that I would like to be formatted
body varchar NOT NULL,
CONSTRAINT jokes_fk FOREIGN KEY (user_id) REFERENCES public."Users"(id)
);
You need to create a trigger function that will change the title if it is not set
create function change_title() returns trigger as $$
begin
if new.title is null then
new.title := format('joke #%s', new.id);
end if;
return new;
end; $$ language plpgsql;
create trigger change_title_jokes before insert on jokes for each row execute procedure change_title();
Demo in sqldaddy.io

MARIADB and routine : error on declaring routine

I use HeidiSQL to make a stored procedure into my MariaDB DB.
Here's my DB.
MariaDB 10.5, centos 7, HeidiSQL 10.3.0.5771. I do not understand the error message.
CREATE TABLE HostName (
ID_HostName INT NOT NULL AUTO_INCREMENT,
Name TEXT,
Platform TEXT,
PRIMARY KEY (ID_HostName)
);
CREATE TABLE UserName (
ID_UserName INT NOT NULL AUTO_INCREMENT,
SAMAccountName TEXT,
FirstName TEXT,
GivenName TEXT,
PRIMARY KEY (ID_UserName)
);
CREATE TABLE EventData (
ID_EventData INT NOT NULL AUTO_INCREMENT,
ObjectType TEXT,
AccessList TEXT,
ObjectName TEXT,
MessageFull TEXT,
ID_UserName INT NOT NULL,
ID_HostName INT NOT NULL,
FOREIGN KEY (ID_UserName) REFERENCES UserName(ID_UserName),
FOREIGN KEY (ID_HostName) REFERENCES HostName(ID_HostName),
PRIMARY KEY (ID_EventData)
);
CREATE TABLE Event (
ID_Event INT NOT NULL AUTO_INCREMENT,
Heure TEXT,
Provider TEXT,
Code TEXT,
Action TEXT,
OutCome TEXT,
Niveau TEXT,
ID_EventData INT NOT NULL,
FOREIGN KEY (ID_EventData) REFERENCES EventData(ID_EventData),
PRIMARY KEY (ID_Event)
);
Here's my stored procedure, i would like to fill database with JDBC (Logstash jdbc output).
DELIMITER $$
CREATE PROCEDURE `LOGTOMDB`(
IN `in_Name` TEXT,
IN `in_Platform` TEXT,
IN `in_SAMAccountName` TEXT,
IN `in_ObjectType` TEXT,
IN `in_AccessList` TEXT,
IN `in_ObjectName` TEXT,
IN `in_MessageFull` TEXT,
IN `in_Heure` TEXT,
IN `in_Provider` TEXT,
IN `in_Code` TEXT,
IN `in_Action` TEXT,
IN `in_Outcome` TEXT,
IN `in_Niveau` TEXT
)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
COMMENT ''
BEGIN
IF NOT EXISTS ( SELECT Name FROM HostName WHERE Name = in_Name ) THEN
BEGIN
INSERT INTO HostName (Name, Platform) VALUES (in_Name, in_Platform);
END;
IF NOT EXISTS ( SELECT SAMAccountName FROM UserName WHERE SAMAccountName = in_SAMAccountName ) THEN
BEGIN
INSERT INTO UserName (SAMAccountName) VALUES (in_SAMAccountName);
END;
INSERT INTO EventData (ObjectType, AccessList, ObjectName, MessageFull, ID_UserName, ID_HostName) VALUES( in_ObjectType, in_AccessList, in_ObjectName, in_MessageFull, ID_UserName, ID_HostName );
INSERT INTO Event (Heure, Provider, Code, Action, Outcome, Niveau, ID_EventData) VALUES( in_Heure, in_Provider, in_Code, in_Action, in_Outcome, in_Niveau, ID_EventData );
END $$
DELIMITER ;
When i save my procedure, i get this error
Can you help me?
Regards.
You need to END your IF statements
DELIMITER $$
CREATE PROCEDURE `LOGTOMDB`(
IN `in_Name` TEXT,
IN `in_Platform` TEXT,
IN `in_SAMAccountName` TEXT,
IN `in_ObjectType` TEXT,
IN `in_AccessList` TEXT,
IN `in_ObjectName` TEXT,
IN `in_MessageFull` TEXT,
IN `in_Heure` TEXT,
IN `in_Provider` TEXT,
IN `in_Code` TEXT,
IN `in_Action` TEXT,
IN `in_Outcome` TEXT,
IN `in_Niveau` TEXT
)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
COMMENT ''
BEGIN
IF NOT EXISTS ( SELECT Name FROM HostName WHERE Name = in_Name ) THEN
INSERT INTO HostName (Name, Platform) VALUES (in_Name, in_Platform);
END IF;
IF NOT EXISTS ( SELECT SAMAccountName FROM UserName WHERE SAMAccountName = in_SAMAccountName ) THEN
INSERT INTO UserName (SAMAccountName) VALUES (in_SAMAccountName);
END IF;
INSERT INTO EventData (ObjectType, AccessList, ObjectName, MessageFull, ID_UserName, ID_HostName) VALUES( in_ObjectType, in_AccessList, in_ObjectName, in_MessageFull, ID_UserName, ID_HostName );
INSERT INTO Event (Heure, Provider, Code, Action, Outcome, Niveau, ID_EventData) VALUES( in_Heure, in_Provider, in_Code, in_Action, in_Outcome, in_Niveau, ID_EventData );
END $$
DELIMITER ;

Can I use an SQL statement in assignment inside a PL/pgSQL function?

I've these two tables (Encomenda and Informacaofaturacao) and I'm trying to create a trigger to insert a new line on Informacaofaturacao before insert on Encomenda and put the ID of new line of Informacaofaturacao on new line of Encomenda.
What am I doing wrong?
Thanks
CREATE TABLE Encomenda
(
EncomendaID SERIAL,
ClienteID integer NOT NULL,
MoradaFaturacaoID integer NOT NULL,
MoradaEnvioID integer NOT NULL,
InformacaofaturacaoID integer NULL,
Data timestamp NOT NULL,
Estado EstadoEncomenda NOT NULL DEFAULT 'Em processamento',
CONSTRAINT PK_Encomenda PRIMARY KEY (EncomendaID)
)
;
CREATE TABLE Informacaofaturacao
(
InformacaofaturacaoID SERIAL,
MetodopagamentoID integer NULL,
Portes real NULL,
Iva real NULL,
Total real NULL,
CONSTRAINT PK_Informacaofaturacao PRIMARY KEY (InformacaofaturacaoID)
)
;
CREATE OR REPLACE FUNCTION insert_encomenda()
RETURNS TRIGGER
AS $$
BEGIN
NEW.InformacaofaturacaoID := (INSERT INTO Informacaofaturacao RETURNING InformacaofaturacaoID);
RETURN NEW;
END $$ LANGUAGE plpgsql;
CREATE TRIGGER insert_encomenda_trigger
BEFORE INSERT OR UPDATE ON Encomenda
FOR EACH ROW
EXECUTE PROCEDURE insert_encomenda();
Postgres doesn't accept a data modifying SQL statement (INSERT, UPDATE or DELETE) in assignment. The documentation states:
... the expression in such a statement is evaluated by means of an SQL SELECT command sent to the main database engine.
You should use this form of executing a query with a single-row result instead.
Also, INSERT command must have VALUES part, it can be: DEFAULT VALUES, VALUES(...) or query see the syntax in the documentation.
CREATE OR REPLACE FUNCTION insert_encomenda()
RETURNS TRIGGER
AS $$
BEGIN
INSERT INTO Informacaofaturacao(InformacaofaturacaoID)
VALUES(DEFAULT)
RETURNING InformacaofaturacaoID
INTO NEW.InformacaofaturacaoID;
RETURN NEW;
END $$ LANGUAGE plpgsql;

Stored procedure: get 3 values from a table and save them to another table

I have following database structure:
CREATE TABLE songs (_id SERIAL PRIMARY KEY, _artist TEXT, _name TEXT);
CREATE TABLE cafes (_id SERIAL, _ip TEXT PRIMARY KEY);
CREATE TABLE users (_id SERIAL UNIQUE, _imei TEXT PRIMARY KEY);
CREATE TABLE votes (_id SERIAL PRIMARY KEY, _cafe TEXT, _user INTEGER, _song INTEGER, _vote INTEGER);
I have a stored procedure that checks whether certain rows exist, and if they don't exist creates them.
Stored procedure:
CREATE OR REPLACE FUNCTION testfunc(user_imei text, cafe_ip text, song_artist text, song_name text) RETURNS void AS $$
DECLARE
id_cafe INTEGER;
id_user INTEGER;
id_song INTEGER;
temp_row RECORD;
BEGIN
IF NOT EXISTS (SELECT _id FROM users WHERE _imei = user_imei) THEN
insert into users (_imei) values (user_imei);
END IF;
IF NOT EXISTS (SELECT _id FROM cafes WHERE _ip = cafe_ip) THEN
insert into cafes (_ip) values (cafe_ip);
END IF;
IF NOT EXISTS (SELECT _artist FROM songs WHERE _artist = song_artist AND _name = song_name) THEN
insert into songs (_artist, _name) values (song_artist, song_name);
END IF;
END;
$$ LANGUAGE plpgsql;
After all that I want to insert a new row into table vote, where:
_cafe = cafes._id
_song = songs._id
_user = users._id
Can anybody help to me?
I made a few adjustments.
user is a reserved word, I use usr instead as column name.
Assuming column votes.cafe is integer, not text.
Removed the leading underscores from column names. That's a peculiar naming convention. I usually use that for variables in plpgsql functions, so they never conflicts with column names ..
CREATE OR REPLACE FUNCTION testfunc(
_user_imei text
,_cafe_ip text
,_song_artist text
,_song_name text) RETURNS void AS
$func$
DECLARE
id_cafe integer;
id_user integer;
id_song integer;
BEGIN
-- user
SELECT INTO id_user id FROM users WHERE imei = _user_imei;
IF NOT FOUND THEN
INSERT INTO users (imei) VALUES (user_imei)
RETURNING id INTO id_user;
END IF;
-- cafe
SELECT INTO id_cafe id FROM cafes WHERE ip = _cafe_ip;
IF NOT FOUND THEN
INSERT INTO cafes (ip) VALUES (cafe_ip)
RETURNING id INTO id_cafe;
END IF;
-- song
SELECT INTO id_song id FROM songs
WHERE artist = _song_artist AND name = _song_name;
IF NOT FOUND THEN
INSERT INTO songs (artist, name) VALUES (_song_artist, _song_name)
RETURNING id INTO id_song;
END IF;
INSERT INTO votes (cafe, usr, song) -- What about column vote??
VALUES (id_cafe, id_user, id_song); -- Assuming cafe is type integer
END
$func$ LANGUAGE plpgsql;