Как да разгранича името на процедурата за задействане на 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