(Note:. Mise à jour avec la réponse adoptée ci-dessous)PostgreSQL: UPDATE implique déplacent à travers les partitions
Pour PostgreSQL 8.1 (ou version ultérieure) table partitionnée, comment définir un déclencheur UPDATE
et de la procédure de "déplacer" un enregistrement d'une partition à l'autre, si le UPDATE
implique une modification du champ contraint qui définit la séparation de partition?
Par exemple, j'ai enregistrements de table partitionnée dans les dossiers actifs et inactifs comme ceci:
create table RECORDS (RECORD varchar(64) not null, ACTIVE boolean default true);
create table ACTIVE_RECORDS (check (ACTIVE)) inherits RECORDS;
create table INACTIVE_RECORDS (check (not ACTIVE)) inherits RECORDS;
Le puits travail déclenchement et la fonction INSERT
: nouveaux records actifs se mettre dans une table, et de nouveaux enregistrements inactifs en autre. Je voudrais UPDATE
s dans le champ ACTIVE pour "déplacer" un enregistrement d'une table descendante à l'autre, mais je rencontre une erreur qui suggère que cela peut ne pas être possible.
spécification Trigger et message d'erreur:
pg=> CREATE OR REPLACE FUNCTION record_update()
RETURNS TRIGGER AS $$
BEGIN
IF (NEW.active = OLD.active) THEN
RETURN NEW;
ELSIF (NEW.active) THEN
INSERT INTO active_records VALUES (NEW.*);
DELETE FROM inactive_records WHERE record = NEW.record;
ELSE
INSERT INTO inactive_records VALUES (NEW.*);
DELETE FROM active_records WHERE record = NEW.record;
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
pg=> CREATE TRIGGER record_update_trigger
BEFORE UPDATE ON records
FOR EACH ROW EXECUTE PROCEDURE record_update();
pg=> select * from RECORDS;
record | active
--------+--------
foo | t -- 'foo' record actually in table ACTIVE_RECORDS
bar | f -- 'bar' record actually in table INACTIVE_RECORDS
(2 rows)
pg=> update RECORDS set ACTIVE = false where RECORD = 'foo';
ERROR: new row for relation "active_records" violates check constraint "active_records_active_check"
Jouer avec la procédure de déclenchement (retour NULL et ainsi de suite) me donne à penser que la contrainte est vérifiée, et l'erreur soulevée, avant mon déclenchement est invoqué, ce qui signifie que mon approche actuelle ne fonctionnera pas. Cela peut-il fonctionner?
MISE À JOUR/RÉPONSE
Voici la procédure de déclenchement UPDATE
je fini par utiliser la même procédure affectée à chacune des partitions. Le crédit est entièrement à Bell, dont la réponse m'a donné l'idée fondamentale de déclencher sur les partitions:
CREATE OR REPLACE FUNCTION record_update()
RETURNS TRIGGER AS $$
BEGIN
IF ((TG_TABLE_NAME = 'active_records' AND NOT NEW.active)
OR
(TG_TABLE_NAME = 'inactive_records' AND NEW.active)) THEN
DELETE FROM records WHERE record = NEW.record;
INSERT INTO records VALUES (NEW.*);
RETURN NULL;
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
Votre "exemple" est incomplète: définition manquante pour "partitioned_records"; vous définissez un déclencheur pour "partitioned_records" mais sélectionnez et mettez à jour "RECORDS". –
@Milen, merci - erreurs cut'n'paste. Va remédier. – pilcrow
Quel est le point d'utiliser une partition dans ce contexte lorsque vous pourriez utiliser un index partiel? – kalu