2015-11-02 4 views
1

Как установить значение в имени столбца переменной? В некотором контексте я пишу функцию, которая будет использоваться в качестве триггера, который устанавливает столбец переменной в постоянное значение. Для того, чтобы использовать следующим образом:Как установить значение в имени столбца переменной?

CREATE TRIGGER always_6_trigger 
    BEFORE INSERT 
    ON table 
    FOR EACH ROW 
    EXECUTE PROCEDURE always_6('col1'); 

выше приведет следующих строк, имеющих все col1 значение 6. Так, например:

INSERT INTO table (col1, col2) VALUES (6, 2), (null, 9), (null, 10), (7, 2); 

приведет ли:

| col1 | col2 | 
--------------- 
| 6 | 2 | 
| 6 | 9 | 
| 6 | 10 | 
| 6 | 2 | 

Или если используется следующий пусковой механизм:

CREATE TRIGGER always_6_trigger 
    BEFORE INSERT 
    ON table 
    FOR EACH ROW 
    EXECUTE PROCEDURE always_6('col2'); 

И та же вставка:

INSERT INTO table (col1, col2) VALUES (6, 2), (null, 9), (null, 10), (7, 2); 

таблица будет выглядеть следующим образом:

| col1 | col2 | 
--------------- 
| 6 | 6 | 
| null | 6 | 
| null | 6 | 
| 7 | 6 | 

Как бы написать функцию always_6?

Редактировать: Чтобы лучше объяснить случай использования, постоянным значением будет current_setting('user_id') (или что-то подобное). И название столбца будет таким, как author_id и user_id. Мысль о том, что пользователь никогда не может добавить данные, которые не были их собственными.

+1

Можете ли вы привести пример или две из различных реализаций того, как вы будете использовать это и ожидаемый результат? – Hambone

+0

Хорошо, приведем примеры. Это хорошо или вам нужно больше? – Calebmer

+0

Да, это замечательная деталь. Написание функции always_6 кажется выполнимым, но я не понимаю, как вы контролируете, какой триггер используется. Вы уже это разработали? Будет ли только один триггер, который будет существовать в любой момент? – Hambone

ответ

3

Вы можете определить вашу функцию для производства dynamically generated SQL.

С помощью команды EXECUTE принимает строку в качестве входных данных и выполняет его как SQL, так что это будет выглядеть примерно так:

EXECUTE FORMAT('UPDATE mytable SET %I='constantvalue' WHERE condition', colname); 

Здесь я использовал функцию FORMAT подготовить строку со значением colname замещенного в котором будет указано имя столбца. condition - это некоторые действующие предложения WHERE для выбора записи для обновления.

Если значение colname может поступать из внешнего источника (то есть с предоставленных пользователем данных), тогда вам нужно быть очень осторожным, чтобы проверить его заранее, иначе вы можете создать вектор инъекции SQL.

+0

Будет ли это работать, чтобы изменить значение на объекте NEW? – Calebmer

+0

Если вы собираетесь использовать 'FORMAT', вы должны использовать соответствующий формат escaping, который является'% I' для идентификатора. Поэтому 'FORMAT ('UPDATE mytable SET% I =' constantvalue 'WHERE condition', colname);' Использование '% s' не лучше, чем объединение строки вместе с' || ' – IMSoP

0

Вы можете использовать динамический запрос для этого с условной проверкой переданного значения параметра входному параметру хранимой процедуры.

+0

Поскольку это необходимо для вставки, могу ли я использовать это на объекте NEW? – Calebmer

0

Я думаю, что я упростил задачу, основанную на первоначальном описании, но что-то вроде этой работы? Вы не можете передать параметр функции триггера, но вы упомянули, что параметр был результатом другой функции current_setting('user_id'), так что можно объединить две концепции вместе?

CREATE OR REPLACE FUNCTION always_6() 
    RETURNS trigger AS 
$BODY$ 
DECLARE 
    current_user_id varchar; 
BEGIN 

    current_user_id := current_setting('user_id'); 

    if current_user_id = 'test1' then 
    new.col_1 := 6; 
    elsif current_user_id = 'test2' then 
    new.col_2 := 6; 
    end if; 

    return NEW; 
END; 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 
+0

Извините за любую путаницу, вместо 6 будет использоваться 'current_setting'. Таким образом, это не сработает. Также есть много других таблиц, которые усложняют ситуацию. – Calebmer

+0

А я вижу. Являются ли данные заполняемыми через приложение, или пользователи сами делают вставки через psql? – Hambone

+0

Короткий ответ: вставка пользователя для себя. Длинный ответ: я использую библиотеку API HTTP REST [PostgREST] (https://github.com/begriffs/postgrest), где пользователь будет вставлять для себя. – Calebmer

Смежные вопросы