Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 468307
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 12, 20262026-05-12T23:40:07+00:00 2026-05-12T23:40:07+00:00

(Note: updated with adopted answer below.) For a PostgreSQL 8.1 (or later) partitioned table,

  • 0

(Note: updated with adopted answer below.)

For a PostgreSQL 8.1 (or later) partitioned table, how does one define an UPDATE trigger and procedure to "move" a record from one partition to the other, if the UPDATE implies a change to the constrained field that defines the partition segregation?

For example, I’ve a table records partitioned into active and inactive records like so:

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;

The INSERT trigger and function work well: new active records get put in one table, and new inactive records in another. I would like UPDATEs to the ACTIVE field to "move" a record from one one descendant table to the other, but am encountering an error which suggests that this may not be possible.

Trigger specification and error message:

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"

Playing with the trigger procedure (returning NULL and so forth) suggests to me that the constraint is checked, and the error raised, before my trigger is invoked, meaning that my current approach won’t work. Can this be gotten to work?

ADDITIONAL ANSWER

pg’s [list partitioning][2] appears to be the easiest way to accomplish this:

-- untested!
create table RECORDS (..., ACTIVE boolean...)
partition by list(ACTIVE) (
  partition   ACTIVE_RECORDS values (true),
  partition INACTIVE_RECORDS values (false)
) 

UPDATE/ANSWER

Below is the UPDATE trigger procedure I ended up using, the same procedure assigned to each of the partitions. Credit is entirely to Bell, whose answer gave me the key insight to trigger on the 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;
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-12T23:40:08+00:00Added an answer on May 12, 2026 at 11:40 pm

    It can be made to work, the trigger that does the move just needs to be defined for each partition, not the whole table. So start as you did for table definitions and the INSERT trigger

    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);
    
    CREATE OR REPLACE FUNCTION record_insert()
    RETURNS TRIGGER AS $$
    BEGIN
      IF (TRUE = NEW.active) THEN
        INSERT INTO active_records VALUES (NEW.*);
      ELSE
        INSERT INTO inactive_records VALUES (NEW.*);
      END IF;
      RETURN NULL;
    END;
    $$
    LANGUAGE plpgsql;
    
    CREATE TRIGGER record_insert_trigger
     BEFORE INSERT ON records
     FOR EACH ROW EXECUTE PROCEDURE record_insert();
    

    … let’s have some test data …

    INSERT INTO records VALUES ('FirstLittlePiggy', TRUE);
    INSERT INTO records VALUES ('SecondLittlePiggy', FALSE);
    INSERT INTO records VALUES ('ThirdLittlePiggy', TRUE);
    INSERT INTO records VALUES ('FourthLittlePiggy', FALSE);
    INSERT INTO records VALUES ('FifthLittlePiggy', TRUE);
    

    Now the triggers on the partitions. The if NEW.active = OLD.active check is implicit in checking the value of active since we know what’s allowed to be in the table in the first place.

    CREATE OR REPLACE FUNCTION active_partition_constraint()
      RETURNS TRIGGER AS $$
        BEGIN
          IF NOT (NEW.active) THEN
            INSERT INTO inactive_records VALUES (NEW.*);
            DELETE FROM active_records WHERE record = NEW.record;
            RETURN NULL;
          ELSE
            RETURN NEW;
          END IF;
        END;
        $$
        LANGUAGE plpgsql;
    
    CREATE TRIGGER active_constraint_trigger
      BEFORE UPDATE ON active_records
      FOR EACH ROW EXECUTE PROCEDURE active_partition_constraint();
    
    CREATE OR REPLACE FUNCTION inactive_partition_constraint()
      RETURNS TRIGGER AS $$
        BEGIN
          IF (NEW.active) THEN
            INSERT INTO active_records VALUES (NEW.*);
            DELETE FROM inactive_records WHERE record = NEW.record;
            RETURN NULL;
          ELSE
            RETURN NEW;
          END IF;
        END;
        $$
        LANGUAGE plpgsql;
    
    CREATE TRIGGER inactive_constraint_trigger
      BEFORE UPDATE ON inactive_records 
      FOR EACH ROW EXECUTE PROCEDURE inactive_partition_constraint();
    

    … and test the results …

    scratch=> SELECT * FROM active_records;
          record      | active 
    ------------------+--------
     FirstLittlePiggy | t
     ThirdLittlePiggy | t
     FifthLittlePiggy | t
    (3 rows)
    
    scratch=> UPDATE records SET active = FALSE WHERE record = 'ThirdLittlePiggy';
    UPDATE 0
    scratch=> SELECT * FROM active_records;
          record      | active 
    ------------------+--------
     FirstLittlePiggy | t
     FifthLittlePiggy | t
    (2 rows)
    
    scratch=> SELECT * FROM inactive_records;
          record       | active 
    -------------------+--------
     SecondLittlePiggy | f
     FourthLittlePiggy | f
     ThirdLittlePiggy  | f
    (3 rows)
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 248k
  • Answers 249k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer You may want to define whatever element your header is… May 13, 2026 at 8:59 am
  • Editorial Team
    Editorial Team added an answer Try something like the following instead (and replace the <hr>… May 13, 2026 at 8:59 am
  • Editorial Team
    Editorial Team added an answer First I'd check if it really isn't one of the… May 13, 2026 at 8:59 am

Related Questions

I am working on a Math related web page and am looking for a
(NOTE: I've updated this question from the initial inquiry about child containers towards creating
[Note : I've simplified my example for clarity] Let's say that I have a
I'm building a UI for a program, and I can't figure out why my

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.