Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
#126 Re : PL/pgSQL » trigger or rule on delete » 01/03/2017 17:10:27
Merci pour votre réponse qui confirme mes recherches.
Je m'en suis tiré avec :
stmt := 'update public.'
|| quote_ident(TG_TABLE_NAME)
|| ' set deleted_when = now() ,deleted_by = '
|| ''''
|| current_user
|| '''';
case TG_TABLE_NAME
when 'tblActions' then execute stmt using old."ActionID";
when 'tblBlankRows' then execute stmt using old."BlankRowID";
.../...(Je n'ai pas pu choisr la pk dans le tuple old comme décrit dans le post précédent.
et un trigger before delete.
Encore une petite question.
L'application front-end en VB Access ne veut voir que les records non effacés. J'ai donc crée des vues comme vous l'avez indiqué.
Mais peut-on faire librement des insert, update et delete sur ces vues ?
Et le front-end saura-t-il retrouver les relations pk/fk des tables sous-jacentes.
Encore merci pour votre attention.
#127 PL/pgSQL » trigger or rule on delete » 01/03/2017 10:23:14
- Michel Depiesse
- Réponses : 4
Bonjour,
Je voudrais faire un trigger ou un rule on delete pour
- ne pas effacer physiquement l'enregistrement
- mettre à jour dans l'enregistrement un champ 'deleted'
Il faut que ce code marche pour toutes les tables d'une db.
Toutes mes tentatives précédentes ont échoués.
Merci pour votre attention,
Mchl
#128 PL/pgSQL » Trigger + variable old. + sql dynamique » 28/02/2017 13:54:04
- Michel Depiesse
- Réponses : 11
Bonjour,
Je veux écrire un trigger qui fasse un delete logique en non physique.
Mais je me heurte à un problème avec la variable now dans un sql dynamique (voir <-------------) J'ai essayé plusieurs syntaxes mais çà ne marche jamais.
Peut-être dois-je essayer un autre design ?
Merci pour votre attention
create or replace function public.get_pk_name(table_name name) returns varchar as $$
declare
stmt varchar;
pk_column_name varchar;
begin
stmt := 'select kc.column_name '
|| ' from information_schema.table_constraints tc'
....
if stmt is not null then execute stmt into pk_column_name; end if;
return pk_column_name;
end; $$ language 'plpgsql';
create or replace function public.mark_as_deleted() returns trigger as $$
declare
stmt varchar;
pk_column_name varchar;
pk_value integer;
begin
stmt := 'select public.get_pk_name('
|| ''''
|| TG_TABLE_NAME
|| ''''
|| ');';
if stmt is not null then execute stmt into pk_column_name; end if;
if pk_column_name is not null then
stmt := 'update public.'
|| quote_ident(TG_TABLE_NAME)
|| ' set deleted_when = now() ,deleted_by = '
|| ''''
|| current_user
|| ''''
|| ' where "'
|| pk_column_name
|| '" = '
|| old.pk_column_name <--------------------------------------------------------------------------------------------
|| ';';
if stmt is not null then execute stmt; end if;
end if;
end;
end; $$ language 'plpgsql'; #129 Re : PL/pgSQL » trigger on delete » 20/02/2017 15:29:04
Merci pour cette réponse pleine de sagesse
Mais la db n'est pas grosse et il n'y a pas bcp de users, alors je fais faire l'instead of.
Très cordialement,
mchl
#130 Re : PL/pgSQL » execute into » 20/02/2017 15:20:53
un grand merci pour toutes ces précisions qui tombent à pic.
A plus
#131 PL/pgSQL » trigger on delete » 20/02/2017 10:37:04
- Michel Depiesse
- Réponses : 2
Bonjour,
J'aimerais faire un trigger qui lorsque on veut faire un delete d'un record :
- fait un update de deux champs du record
- mais NE fait PAS de delete physique du record
Est-ce possible ?
Merci pour votre attention
#132 Re : PL/pgSQL » execute into » 20/02/2017 10:31:11
Un grand merci ?
et le if not found marchera ?
#133 Re : PL/pgSQL » execute into » 16/02/2017 13:43:53
Merci pour ces éclaircissements.
Quelle est la méthode la plus sûre pour tester la présence d'un record dans une table ?
Est-ce que
select "ContactID" into this_pk from public."tblContacts" where audit_id = r.audit_id;
if not found then
...marchera dans tous les cas ?
Par ailleurs, la migration se passe bien. On garde MS Access comme front-end et les performances sont très bonnes. Merci pg !
#134 Re : PL/pgSQL » execute into » 15/02/2017 14:49:00
Cher collègue,
Tu fais :
execute stmt into this_audit_id;
get diagnostics rcount = ROW_COUNT;
if rcount = 0 thenet l'affaire est dans le sac.
#135 PL/pgSQL » execute into » 15/02/2017 13:31:44
- Michel Depiesse
- Réponses : 7
Bonjour,
Je veux tester la présence d'un record dans une table avec
stmt := 'select audit_idid from public.' || quote_ident(r.table_name) || ' where audit_id = ' || r.audit_id || ';';
execute stmt into this_audit_id;si le record est là, tout va bien. Mais si le record n'est pas là
info := 'this_audit_id = ' || this_audit_id;
insert into sync_log values (schema_name, info);ne m'écrira même pas 'this_audit_id' !? J'ai essayé plusieurs trucs avec coalesce mais je pédale dans la choucroute...
Par ailleurs, puis-je être² assuré que
select "ContactID" into this_pk from public."tblContacts" where audit_id = r.audit_id;
if not found thenfonctionnera dans tous les cas.
#136 Re : PL/pgSQL » nom de schema comme argument d'une fonction » 14/02/2017 16:58:40
effectivement !
create or replace function sync_client2server(schema_name varchar) returns void as $$
declare
r audit_history%ROWTYPE;
begin
for r in execute format('select * from %I.audit_history',schema_name) loop
case r.operation
when 'INSERT' then perform sync_insert(schema_name, r.*);
when 'UPDATE' then perform sync_update(schema_name, r.*);
when 'DELETE' then perform sync_delete(schema_name, r.*);
end case;
end loop;
end $$ language 'plpgsql';execute pour le curseur, perform pour le call des fonctions et bonne chance à tous !
Encore merci à vous
#137 Re : PL/pgSQL » nom de schema comme argument d'une fonction » 14/02/2017 16:26:46
j'ai contourné le problème
merci
#138 Re : PL/pgSQL » nom de schema comme argument d'une fonction » 14/02/2017 16:15:59
ca va non plus...
je reçois le même message d'horreur
#139 Re : PL/pgSQL » nom de schema comme argument d'une fonction » 14/02/2017 16:04:00
mais ça ne marche pas !
quand je fais :
declare
r audit_history%ROWTYPE;
begin
for r in execute format('select * from %I.audit_history',schema_name) loop
.../...je reçois
psql:sync_client2server.sql:92: ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.Il va de soi que la table audit_history a la même structure dans les 2 schemas.
Merci pour votre attention et votre patience
#140 Re : PL/pgSQL » nom de schema comme argument d'une fonction » 14/02/2017 15:10:55
Merci à tous les deux !
Avec une préférence pour la seconde solutuin;
#141 PL/pgSQL » nom de schema comme argument d'une fonction » 13/02/2017 12:45:15
- Michel Depiesse
- Réponses : 9
Bonjour,
J'aimerais écrire dans le schema public une procédure qui va chercher ses données dans un autre schéma de la db. Le nom du schema est donc un parmètre de la fonction. Mais je ne peux pas tout simplement écrire :
create function sync_client2server(schema_name varchar) returns void as $$
declare
r record;
begin
for r in select * from schema_name.audit_history loop
...
end loop;
end
$$ language 'plpgsql'Que faire ?
Merci pour votre attention
#142 PSQL » cet horrible $$ dans le create function » 10/02/2017 13:53:08
- Michel Depiesse
- Réponses : 3
Bonjour,
Je veux mettre un create function dans un script bash (un désir naturel et légitime, me semble-t-il) :
if [ $# -ne 2 ]
then
echo "usage : $0 database_name schema_name"
exit
fi
database_name=$1
schema_name=$2
psql -qAt $database_name <<EOF
set search_path to $schema_name;
---------------------------------------------------------------------------------------------------------------------------------------------
-- create db objects
---------------------------------------------------------------------------------------------------------------------------------------------
drop table if exists audit_history;
create table audit_history (
...
---------------------------------------------------------------------------------------------------------------------------------------------
-- generic function for all triggers
---------------------------------------------------------------------------------------------------------------------------------------------
create or replace function populate_audit_history() returns trigger as $$
begin
...Mais bien sûr, bash interprét $$ comme étant le pid.
Et si j'écris
psql -qAt $database_name <<'EOF'alors là, c'est
set search_path to $schema_name;qui ne marche plus.
Quel flip !
Que faire ?
Merci pour votre attention
#143 Re : PSQL » ERROR: invalid input syntax for integer: » 09/02/2017 17:08:55
y pas à dire
les dalibiens sont vachement balèzes
merci
#144 PSQL » ERROR: invalid input syntax for integer: » 09/02/2017 15:28:53
- Michel Depiesse
- Réponses : 2
Bonjour,
Je fais avec psql un export en csv d'un table :
\copy (select * from audit_history) to audit_history.csv with csv;et ensuite, toujours avec psql, un import :
\copy sync.audit_history(id_audit_history ,table_name ,operation ,audit_id ,user_name ,insertion_date) from 'audit_history.csv';et je reçois le message :
psql:.work/_import_modifs.sql:1: ERROR: invalid input syntax for integer: "1,tblContacts,DELETE,1,rubin,2017-02-08 11:56:41.979212"
CONTEXT: COPY audit_history, line 1, column id_audit_history: "1,tblContacts,DELETE,1,rubin,2017-02-08 11:56:41.979212"Alors que les deux tables ont exactement la même structure !
Voici le record qui est dans le fichier :
1,tblContacts,DELETE,1,rubin,2017-02-08 11:56:41.979212Que faire ?
Merci
#145 Re : PL/pgSQL » trigger before delete et foreign key constraint on delete cascade » 08/02/2017 12:07:03
j'ai trouvé
when (pg_trigger_depth() < 1)
merci
excusez-moi d'avoir écrit si vite...
j'ai un client un peu stressant ;-))
#146 Re : PL/pgSQL » trigger before delete et foreign key constraint on delete cascade » 08/02/2017 12:03:22
oops : audit_id doit être bigserial
mais ça ne change rien au problème
#147 PL/pgSQL » trigger before delete et foreign key constraint on delete cascade » 08/02/2017 11:59:57
- Michel Depiesse
- Réponses : 2
Bonjour,
Quand je delete le pk de app_table, les records correspondants de app_table_ref sont délétés mais le trigger pre delete n'est pas déclenché et il n'y a donc pas de records écrits dans record_tracking.
Que faire ?
Merci pour votre attention
---------------------------------------------------------------------------------------------------------------------------------------------
-- this script must be played on the tablet just after the database has been copied
---------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------
-- create db objects
---------------------------------------------------------------------------------------------------------------------------------------------
drop table if exists record_tracking;
create table record_tracking (
id_record_tracking serial
,table_name text
,operation text
,pk_value bigint
,user_name text
,insertion_date timestamp default now()
);
drop sequence if exists record_tracking_seq;
create sequence record_tracking_seq;
drop table if exists app_table_ref;
drop table if exists app_table;
create table app_table (
pk integer primary key
,info varchar
,audit_id bigint
);
create table app_table_ref (
pk integer primary key
,info varchar
,fk integer references app_table(pk) on delete cascade
,audit_id bigint
);
---------------------------------------------------------------------------------------------------------------------------------------------
-- generic function for all triggers
---------------------------------------------------------------------------------------------------------------------------------------------
create or replace function record_tracking() returns trigger as $$
begin
if (TG_OP = 'INSERT' or TG_OP = 'UPDATE') then
insert into record_tracking
(table_name, operation, pk_value, user_name)
values
(TG_TABLE_NAME, TG_OP, new.audit_id, current_user);
return new;
else
insert into record_tracking
(table_name, operation, pk_value, user_name)
values
(TG_TABLE_NAME, TG_OP, old.audit_id, current_user);
return old;
end if;
end;
$$ language 'plpgsql';
---------------------------------------------------------------------------------------------------------------------------------------------
-- create triggers
---------------------------------------------------------------------------------------------------------------------------------------------
create or replace function create_audit_triggers() returns void as $$
declare
r record;
stmt varchar;
begin
for r in select table_name from information_schema.tables where table_name like 'app_table%' loop
stmt := 'create trigger '
|| quote_ident(r.table_name || '_audit_after_iu')
|| ' after insert or update on '
|| quote_ident(r.table_name)
|| ' for each row when (pg_trigger_depth() < 1) execute procedure record_tracking();';
execute stmt;
stmt := 'create trigger '
|| quote_ident(r.table_name || '_audit_before_d')
|| ' before delete on '
|| quote_ident(r.table_name)
|| ' for each row when (pg_trigger_depth() < 1) execute procedure record_tracking();';
execute stmt;
end loop;
end;
$$ language 'plpgsql';
select create_audit_triggers();
insert into app_table values(23,'record 23');
insert into app_table values(56,'record 56');
insert into app_table values(71,'record 71');
insert into app_table values(82,'record 82');
insert into app_table values(85,'record 85');
insert into app_table values(91,'record 91');
insert into app_table values(94,'record 94');
insert into app_table values(97,'record 97');
insert into app_table values(99,'record 99');
update app_table set info = 'modified' where pk = 23;
update app_table set info = 'modified' where pk = 56;
update app_table set info = 'modified' where pk = 97;
delete from app_table where pk = 71;
insert into app_table values(101,'record 101');
insert into app_table values(121,'record 121');
insert into app_table values(167,'record 167');
update app_table set info = 'modified' where pk = 101;
delete from app_table where pk = 121;
insert into app_table_ref values(1, 'ref1', 23);
insert into app_table_ref values(2, 'ref2', 23);
insert into app_table_ref values(3, 'ref3', 82);
delete from app_table where pk = 23;
select * from app_table order by pk;
select * from app_table_ref order by pk;
select * from record_tracking;#148 Re : PL/pgSQL » new.[nom de colonne calculé par programme] » 07/02/2017 11:16:06
finalement, je m'en suis tiré comme ça :
select get_pk_name(TG_TABLE_NAME) into pk_column_name;
if (TG_OP = 'INSERT' or TG_OP = 'UPDATE') then
execute 'select $1.' || quote_ident(pk_column_name) using new into pk_value;
else
execute 'select $1.' || quote_ident(pk_column_name) using old into pk_value;
end if;#149 Re : PL/pgSQL » new.[nom de colonne calculé par programme] » 06/02/2017 20:39:41
c'est effectivement ravissant
mais ce qui me faut, c'est la valeur de la pk du record
n'était-ce ce
pk_value := old.pk_column_name; <------------------------------------------------------------------- Horreur !tout irait bien
une petite idée ?
merci pour votre patience et votre dévouement
en fait, je viens de recevoir mes premiers bouquins sur pg seulement aujourd'hui
bonne soirée
#150 PL/pgSQL » new.[nom de colonne calculé par programme] » 06/02/2017 18:59:23
- Michel Depiesse
- Réponses : 3
Bonjour,
Pour un système d'audit, j'ai écrit
---------------------------------------------------------------------------------------------------------------------------------------------
-- create db objects
---------------------------------------------------------------------------------------------------------------------------------------------
drop table if exists record_tracking;
create table record_tracking (
id_record_tracking serial
,table_name varchar
,operation varchar
,pk_value varchar
,user_name varchar
,insertion_date timestamp default now()
);
drop sequence if exists record_tracking_seq;
create sequence record_tracking_seq;
drop table if exists app_table;
create table app_table (
pk integer primary key
,info varchar
);
---------------------------------------------------------------------------------------------------------------------------------------------
-- generic functions for triggers
---------------------------------------------------------------------------------------------------------------------------------------------
create or replace function get_pk_value(this_table_name name) returns varchar as $$
declare
pk_column_name varchar;
begin
select
c.column_name
into
pk_column_name
from
information_schema.table_constraints tc
join
information_schema.constraint_column_usage ccu
using
(constraint_schema, constraint_name)
join
information_schema.columns c
on
c.table_schema = tc.constraint_schema
and
tc.table_name = c.table_name
and
ccu.column_name = c.column_name
where
constraint_type = 'PRIMARY KEY'
and
tc.table_name = this_table_name;
return pk_column_name;
end;
$$ language 'plpgsql';
create or replace function record_tracking() returns trigger as $$
declare
pk_column_name varchar;
pk_value varchar;
begin
select get_pk_value(TG_TABLE_NAME) into pk_column_name;
pk_value := old.pk_column_name; <------------------------------------------------------------------- Horreur !
insert into record_tracking
(table_name, operation, pk_value_type, user_name)
values
(TG_TABLE_NAME, TG_OP, pk_value, current_user);
return new;
end;
$$ language 'plpgsql';
---------------------------------------------------------------------------------------------------------------------------------------------
-- create after insert trigger
---------------------------------------------------------------------------------------------------------------------------------------------
create trigger trg_app_table_record_tracking after insert or update or delete on app_table
for each row execute procedure record_tracking();je ne vois pas comment, je pourrais résoudre ce problème.
Merci pour votre attention