【发布时间】:2017-08-30 09:17:18
【问题描述】:
我使用的是 PostgreSQL 9.6。我有以下序列和表格:
CREATE SEQUENCE measure_id_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
CREATE TABLE measure (
id integer NOT NULL DEFAULT nextval('measure_id_seq'::regclass),
time_stp timestamp with time zone NOT NULL,
val double precision NOT NULL,
pollutant character varying(255) NOT NULL,
station character varying(255) NOT NULL,
CONSTRAINT measure_pkey PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
“measure”表根据“pollutant”和“station”列的值划分为不同的表。
为此,我有一个在将新数据插入表之前执行的触发器:
CREATE OR REPLACE FUNCTION before_insert_on_measure()
RETURNS TRIGGER LANGUAGE plpgsql as $$
DECLARE format_station TEXT := lower(replace(new.station, ' ', ''));
DECLARE format_pollutant TEXT := lower(replace(new.pollutant, ' ', ''));
BEGIN
EXECUTE format(
$f$
CREATE TABLE IF NOT EXISTS %I (
check (station = %L AND pollutant = %L)
) INHERITS (measure)
$f$,
concat('partition_measure_', format_station, '_', format_pollutant),
new.station,
new.pollutant);
EXECUTE format(
$f$
INSERT INTO %I (time_stp, val, pollutant, station)
VALUES (%L, %L, %L, %L)
$f$,
concat('partition_measure_', format_station, '_', format_pollutant),
new.time_stp,
new.val,
new.pollutant,
new.station
);
RETURN NULL;
END $$;
CREATE TRIGGER before_insert_on_measure
BEFORE INSERT ON measure
FOR EACH ROW EXECUTE PROCEDURE before_insert_on_measure();
将新数据插入“measures”表会创建正确的子表。例如当我插入以下数据时:
INSERT INTO measure (time_stp, val, pollutant, station)
VALUES ('2015-01-01 01:00:00', 32.4, 'O3', 'Station 1');
INSERT INTO measure (time_stp, val, pollutant, station)
VALUES ('2016-01-01 01:00:00', 54, 'NO2', 'Station 2');
它创建表格:
- partition_measure_station1_o3
- partition_measure_station2_no2
我遇到的问题是我的“id”列增加了 2
id time_stp val pollutant station
2 "2015-01-01 01:00:00+04" 32.4 "O3" "Station 1"
4 "2016-01-01 01:00:00+04" 54 "NO2" "Station 2"
相反,我想要:
id ...
1 ...
2 ...
nextval('measure_id_seq') 似乎在每个 INSERT 上执行了两次。
有什么建议吗?
编辑:JGH 提供的答案是正确的。作为参考,这里是编辑的触发器:
CREATE OR REPLACE FUNCTION before_insert_on_measure()
RETURNS TRIGGER LANGUAGE plpgsql as $$
DECLARE format_station TEXT := lower(replace(new.station, ' ', ''));
DECLARE format_pollutant TEXT := lower(replace(new.pollutant, ' ', ''));
BEGIN
EXECUTE format(
$f$
CREATE TABLE IF NOT EXISTS %I (
check (station = %L AND pollutant = %L)
) INHERITS (measure)
$f$,
concat('partition_measure_', format_station, '_', format_pollutant),
new.station,
new.pollutant);
EXECUTE format(
$f$
INSERT INTO %I
VALUES (%L, %L, %L, %L, %L)
$f$,
concat('partition_measure_', format_station, '_', format_pollutant),
new.id,
new.time_stp,
new.val,
new.pollutant,
new.station
);
RETURN NULL;
END $$;
CREATE TRIGGER before_insert_on_measure
BEFORE INSERT ON measure
FOR EACH ROW EXECUTE PROCEDURE before_insert_on_measure();
【问题讨论】:
标签: postgresql