(Nota:. Aggiornato con risposta adottata sotto)PostgreSQL: UPDATE implica muoversi tra le partizioni
Per un PostgreSQL 8.1 (o successivo) tabella partizionata, come si fa a definire un UPDATE
grilletto e procedura per "spostare" un record da una partizione all'altra, se lo UPDATE
implica una modifica al campo vincolato che definisce la separazione della partizione?
Per esempio, ho un record tabella partizionata in record attivi e inattivi in questo modo:
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;
I INSERT
di trigger e il lavoro funzionano bene: nuovi record attivi vengono messe in una tabella, e nuovi record inattivi in un altro. Vorrei UPDATE
s nel campo ACTIVE per "spostare" un record da una tabella discendente all'altra, ma sto riscontrando un errore che suggerisce che ciò potrebbe non essere possibile.
trigger messaggio:
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"
Giocando con la procedura di attivazione (ritorno NULL e così via) mi fa pensare che il vincolo viene controllato, e l'errore sollevato, prima che il mio grilletto viene richiamato, il che significa che il mio attuale approccio non funzionerà. Questo può essere fatto funzionare?
UPDATE/RISPOSTA
La procedura seguente UPDATE
grilletto ho finito per usare la stessa procedura assegnato a ciascuna delle partizioni. Il credito è interamente a Bell, la cui risposta mi ha dato l'intuizione chiave per attivare sulle partizioni:
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;
Il tuo "esempio" è incompleta: definizione mancante per "partitioned_records"; si definisce un trigger per "partitioned_records" ma si seleziona e si aggiorna "RECORDS". –
@ Milen, grazie - errori cut'n'paste. Rimedi. – pilcrow
Qual è il punto di utilizzo di una partizione in questo contesto quando è possibile utilizzare un indice parziale? – kalu