sql Postgres在插入时使用RETURNING进行分区

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sql Postgres在插入时使用RETURNING进行分区相关的知识,希望对你有一定的参考价值。

-- A method to have RETURNING work if you are partitioning data using trigger. 
-- The method to this madness is:
--
-- 1) Use the normal trigger mechanism to insert the data into the child tables, but
--    Instead of the trigger function returning NULL so that the row does not get⋅
--    inserted into the master table, it returns the row inserted into the child
--    table
--
-- 2) Postgres will insert the new row from the trigger into the master table
--
-- 3) Have an 'after insert' trigger on the master table that deletes from the⋅
--    master table with RETURNING.
--
-- This allows for the following type of statement to insert into the master table:
--⋅

INSERT INTO TABLE measurement( city_id, logdate, peaktemp, unitsales )⋅
           VALUES ( 42, 'today'::date, 12, 400 ) RETURNING *;

-- And the row will be partitioned into the appropriate child table

--- Master measurement table
CREATE TABLE measurement (
    id              int not null,
    city_id         int not null,
    logdate         date not null,
    peaktemp        int,
    unitsales       int
);

-- Child partition tables
CREATE SEQUENCE measurement_y2007m02_seq start with 1 increment by 1 minvalue 1 cache 1;
CREATE TABLE measurement_y2007m02 (
    id int nextval('measurement_y2007m02_seq'::regclass),
    CHECK ( logdate >= DATE '2007-02-01' AND logdate < DATE '2007-03-01' )
) INHERITS (measurement);
CREATE SEQUENCE measurement_y2007m03_seq start with 1 increment by 1 minvalue 1 cache 1;
CREATE TABLE measurement_y2007m03 (
    id int nextval('measurement_y2007m03_seq'::regclass),
    CHECK ( logdate >= DATE '2007-03-01' AND logdate < DATE '2007-04-01'
    )   
) INHERITS (measurement);
...
CREATE SEQUENCE measurement_y2009m01_seq start with 1 increment by 1 minvalue 1 cache 1;
CREATE TABLE measurement_y2009m01 (
    id int nextval('measurement_y2009m01_seq'::regclass),
    CHECK ( logdate >= DATE '2009-01-01' AND logdate < DATE '2009-02-01' )
) INHERITS (measurement);
-- Trigger function to split out between the various child partition tables
CREATE OR REPLACE FUNCTION measurement_insert_trigger()
RETURNS TRIGGER AS $$
DECLARE
    r measurement%rowtype;
BEGIN
    IF ( NEW.logdate >= DATE '2007-02-01' AND NEW.logdate < DATE '2007-03-01' ) THEN
        INSERT INTO measurement_y2006m02 VALUES (NEW.*) RETURNING * INTO r;
    ELSIF ( NEW.logdate >= DATE '2007-03-01' AND NEW.logdate < DATE '2007-04-01' ) THEN
        INSERT INTO measurement_y2007m03 VALUES (NEW.*) RETURNING * INTO r;
    ... 
    ELSIF ( NEW.logdate >= DATE '2009-01-01' AND NEW.logdate < DATE '2009-02-01' ) THEN
        INSERT INTO measurement_y2009m01 VALUES (NEW.*) RETURNING * INTO r;
    ELSE
        RAISE EXCEPTION 'Date out of range.  Fix the measurement_insert_trigger() function!';
    END IF;
    RETURN r;
END;
$$
LANGUAGE plpgsql;

-- Trigger to invoke the insert trigger
CREATE TRIGGER insert_measurement_trigger
    BEFORE INSERT ON measurement
    FOR EACH ROW EXECUTE PROCEDURE measurement_insert_trigger();

-- Trigger function to delete from the master table after the insert
CREATE OR REPLACE FUNCTION measurement_delete_master() RETURNS trigger
    AS $$
DECLARE
    r measurement%rowtype;
BEGIN
    DELETE FROM ONLY measurement where id = new.id returning * into r;
    RETURN r;
end;
$$
LANGUAGE plpgsql;

-- Create the after insert trigger
create trigger after_insert_measurement_trigger
    after insert on measurement
    for each row
        execute procedure measurement_delete_master();

以上是关于sql Postgres在插入时使用RETURNING进行分区的主要内容,如果未能解决你的问题,请参考以下文章

SQL 在 Postgres 中插入 file.exe

如何使用 Prisma 为 Postgres 进行 SQL 插入,条件是行数?

Python/postgres/psycopg2:获取刚刚插入的行的 ID

使用触发器将 postgres SQL 插入语句拆分为 2 个表

带有Java的Postgres我无法插入数据

Postgres:如果不存在则插入