Вопрос:

Унаследованная от PostgreSQL таблица и триггеры вставки

sql postgresql partitioning database-trigger

831 просмотра

1 ответ

4234 Репутация автора

Я пытаюсь следовать совету здесь, чтобы создать вертикально разделенную таблицу для хранения данных временных рядов.

Пока что моя схема выглядит так:

CREATE TABLE events 
(
     topic text, 
     t timestamp, 
     value integer, 
     primary key(topic, t)
);

CREATE TABLE events_2014 
(
     primary key (topic, t), 
     check (t between '2014-01-01' and '2015-01-01') 
) INHERITS (events);

Сейчас я пытаюсь создать INSTEAD OF INSERTтриггер, чтобы события могли быть вставлены в eventsтаблицу, и строка оказалась в правой вложенной таблице. Но в документации говорится, что INSTEAD OF INSERTтриггеры могут быть созданы только для представлений, а не таблиц (или подтаблиц):

CREATE OR REPLACE FUNCTION insert_events () RETURNS TRIGGER AS $insert_events$ BEGIN
  IF new.t between '2014-01-01' and '2015-01-01' THEN
    INSERT INTO events_2014 SELECT new.*;
  ...
  END IF
  RETURN NULL;
END;
$insert_events$ LANGUAGE PLPGSQL;

CREATE TRIGGER insert_events INSTEAD OF INSERT ON events FOR EACH ROW EXECUTE PROCEDURE insert_events();
ERROR:  "events" is a table
DETAIL:  Tables cannot have INSTEAD OF triggers.

Какой правильный способ сделать это?

Автор: Tom Источник Размещён: 22.08.2016 09:26

Ответы (1)


2 плюса

12571 Репутация автора

Решение

Вам нужно объявить BEFORE INSERTтриггеры.

Документация по разделам является отличным источником знаний в этом вопросе и полна примеров.

Пример функции из документов

CREATE OR REPLACE FUNCTION measurement_insert_trigger()
RETURNS TRIGGER AS $$
BEGIN
    IF ( NEW.logdate >= DATE '2006-02-01' AND
         NEW.logdate < DATE '2006-03-01' ) THEN
        INSERT INTO measurement_y2006m02 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2006-03-01' AND
            NEW.logdate < DATE '2006-04-01' ) THEN
        INSERT INTO measurement_y2006m03 VALUES (NEW.*);
    ...
    ELSIF ( NEW.logdate >= DATE '2008-01-01' AND
            NEW.logdate < DATE '2008-02-01' ) THEN
        INSERT INTO measurement_y2008m01 VALUES (NEW.*);
    ELSE
        RAISE EXCEPTION 'Date out of range.  Fix the measurement_insert_trigger() function!';
    END IF;
    RETURN NULL;
END;
$$
LANGUAGE plpgsql;

Пример триггера из документов

CREATE TRIGGER insert_measurement_trigger
    BEFORE INSERT ON measurement
    FOR EACH ROW EXECUTE PROCEDURE measurement_insert_trigger();

При возврате NULLиз BEFOREтриггера родительская таблица останется пустой.

Автор: Kamil Gosciminski Размещён: 22.08.2016 09:29
Вопросы из категории :
32x32