Как разграничить имя триггерной процедуры PostgreSQL?

Например, в Perl вы разграничиваете переменную следующим образом:

${foo}_bar

У меня есть триггер в PostgreSQL, заимствованный из здесь, который я пытаюсь сделать универсальным для работы с несколькими таблицами. Вот мой код:

CREATE OR REPLACE FUNCTION update_parent_path() RETURNS TRIGGER AS $$
DECLARE
    PATH ltree;
BEGIN
    IF NEW.parent_id IS NULL THEN
        NEW.parent_path = 'root'::ltree;
    ELSEIF TG_OP = 'INSERT' OR OLD.parent_id IS NULL OR OLD.parent_id != NEW.parent_id THEN
        SELECT parent_path || TG_TABLE_NAME_id::text FROM TG_TABLE_NAME WHERE TG_TABLE_NAME_id = NEW.parent_id INTO PATH;
        IF PATH IS NULL THEN
            RAISE EXCEPTION 'Invalid parent_id %', NEW.parent_id;
        END IF;
        NEW.parent_path = PATH;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Каждая таблица, для которой я использую этот триггер, имеет первичный ключ, такой как table_id (например, skill_id, level_id и т. д.). То, что я пытаюсь сделать, это сказать WHERE skill_id = NEW.parent_id (для любой таблицы, против которой он вызывается), поэтому я говорю WHERE TG_TABLE_NAME_id = NEW.parent_id. Мне интересно, как мне отделить TG_TABLE_NAME (триггерную процедуру) от _id?

Или есть лучший способ сделать это? Может быть, я просто говорю об этом неправильно.


person Franz Kafka    schedule 28.09.2015    source источник


Ответы (1)


В PLpgSQL есть одно фундаментальное правило: переменная plpgsql не может использоваться в качестве имени таблицы или имени столбца во встроенном SQL. Но есть динамический SQL - следующий способ, как выполнить SQL-запрос. Динамический SQL — это запрос, сгенерированный во время выполнения из строки (или строкового выражения). Там везде можно использовать переменную PLpgSQL. Итак, ваш фрагмент запроса:

SELECT TG_TABLE_NAME_id::text FROM TG_TABLE_NAME ...

неправильно в большем количестве пунктов и не должно работать никогда. Но динамический запрос (оператор PLpgSQL EXECUTE) должен работать

EXECUTE format('SELECT %I FROM %I ...', 
                TG_TABLE_NAME || '_id', TG_TABLE_NAME) INTO path;

Связанная документация: http://www.postgresql.org/docs/9.4/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN

person Pavel Stehule    schedule 28.09.2015