Ошибка вставки в секционированную таблицу для Postgres 9.6 - PullRequest
0 голосов
/ 19 июня 2019

У меня есть огромная таблица, которую нам нужно разбивать на разделы ежемесячно. Эта таблица в настоящее время является дочерней по отношению к другой таблице. Я пытаюсь создать раздел на этой таблице, и эти разделы будут унаследованы от исходной родительской таблицы. Я создал триггер и функцию, а старая дочерняя таблица содержит триггер для создания разделов.

Tables:
parent_table (Partitioned tables are going to be inherited from this table)
old_child_table (This holds the trigger, code will try to insert here)

CREATE OR REPLACE FUNCTION temp.partition_insert_function()
RETURNS TRIGGER
AS $$
DECLARE
partition_month TEXT;
partition_schema TEXT;
partition_name TEXT;
start_of_month TEXT;
end_of_month TEXT;
BEGIN
partition_month := to_char(NEW.created_dtm,'YYYY_MM'); ---This column  has a default of now() and it is of timestamp with timezone
partition_schema := 'temp';
partition_name := 'partition_' || partition_month;
start_of_month := to_char((NEW.created_dtm),'YYYY-MM'|| '-01');
end_of_month := to_char((NEW.created_dtm + interval '1 month'),'YYYY-MM'|| '-01');

EXECUTE format('INSERT INTO %I.%I VALUES($1.*) ON CONFLICT (primary_key) DO NOTHING', partition_schema, partition_name) using NEW;
---I want to try to insert first rather than checking every time if the partition exists or not.

RETURN NULL;

EXCEPTION WHEN SQLSTATE '42P01' THEN

RAISE NOTICE 'RELNAME %', TG_TABLE_NAME;

IF NOT EXISTS  ---If the insert fails for above SQLSTATE then I want to check if the partition exists or not
(SELECT 1
 FROM   information_schema.tables
 WHERE  table_name = partition_name
 AND table_schema = partition_schema) 
THEN
EXECUTE 'CREATE TABLE ' || partition_schema || '.' || partition_name || ' (check (created_dtm >= ''' || start_of_month || ''' and created_dtm < ''' || end_of_month || ''' ), ' || 'LIKE temp.old_child_table  INCLUDING ALL)  INHERITS (temp.parent_table)';
EXECUTE 'ALTER TABLE ' || partition_schema || '.' || partition_name || ' OWNER TO owner';
EXECUTE 'GRANT SELECT ON TABLE ' || partition_schema || '.' || partition_name || ' TO user_ro';
EXECUTE 'GRANT INSERT, SELECT, UPDATE, DELETE ON TABLE ' || partition_schema || ' . ' || partition_name || ' TO user_rw';
EXECUTE 'ALTER TABLE ' || partition_schema || '.' || partition_name || '  ADD CONSTRAINT ' || partition_name || '_fkey1 FOREIGN KEY(random_key) REFERENCES temp.random(random_key)';
EXECUTE 'CREATE TRIGGER ' || partition_name || '_trigger1  BEFORE INSERT OR UPDATE ON ' || partition_schema || '.' || partition_name || ' FOR EACH  ROW EXECUTE PROCEDURE temp.trigger_function()';
RAISE NOTICE 'A partition has been created %.%', partition_schema, partition_name;
RAISE NOTICE 'All FK constraints are created on %.%', partition_schema, partition_name;
RAISE NOTICE 'All necessary indices are created on %.%', partition_schema, partition_name;
RAISE NOTICE 'All triggers are created on %.%', partition_schema, partition_name;
END IF;

EXECUTE format('INSERT INTO %I.%I VALUES($1.*) ON CONFLICT (primary_key) DO NOTHING', partition_schema, partition_name) using NEW;

RETURN NULL;
END
$$
LANGUAGE plpgsql;

CREATE TRIGGER insert_trigger
BEFORE INSERT
ON temp.old_child_table
FOR EACH ROW
EXECUTE PROCEDURE temp.partition_insert_function();

It gives me below error;
ERROR:  new row for relation "partition_2018_04" violates check constraint "partition_2018_04_created_dtm_check"

Я также пытался создать представление для old_child_table и создать триггер для представления, но это вызывало ту же ошибку. В идеале мы хотим создать его в представлении, потому что мы хотим получить возвращаемый primary_key. В функции я также попытался заменить RETURN NULL или RETURN NEW, и ошибка осталась прежней.

Примечание. Эта ошибка возникает при самой первой вставке, и из-за этой ошибки не создаются разделы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...