2015-02-02 2 views
-1

Я пытаюсь иметь динамическую переменную, с которой я могу указать разные столбцы (в зависимости от некоторых операторов if). Разъяснения в коде, я пытаюсь заменить это:Динамические столбцы в выражении SQL

IF (TG_TABLE_NAME='this') THEN INSERT INTO table1 (name_id) VALUES id.NEW END IF; 
IF (TG_TABLE_NAME='that') THEN INSERT INTO table1 (lastname_id) VALUES id.NEW END IF; 
IF (TG_TABLE_NAME='another') THEN INSERT INTO table1 (age_id) VALUES id.NEW END IF; 

С этим:

DECLARE 
varName COLUMN; 
BEGIN 
IF (TG_TABLE_NAME='this') THEN varName = 'name_id'; 
ELSE IF (TG_TABLE_NAME='that') THEN varName = 'lastname_id'; 
ELSE (TG_TABLE_NAME='another') THEN varName = 'age_id'; 
END IF; 

INSERT INTO table1 (varName) VALUES id.NEW; 
END; 

Инструкция INSERT строка это просто пример, на самом деле это что-то больше. Я начинаю на pgSQL. Я видел несколько примеров, но я только больше смущен. Если вы можете предоставить ответ, который также более безопасен для SQL-инъекций, это было бы потрясающе.

+0

Что такое 'pgSQL'? Существует * PostgreSQL * (или * Postgres * для краткости), * psql * (интерфейс командной строки) и * plpgsql * (процедурный серверный язык) ... Очевидно, что вы работаете над функцией триггера. Когда вы спрашиваете о ** функции plpgsql **, всегда предоставляйте * полную * функцию, включая верхний и нижний колонтитулы, которые являются неотъемлемыми частями. –

ответ

0

Один из способов сделать то, что вы ищете, состоит в том, чтобы составлять инструкцию INSERT динамически на основе указанной таблицы. Следующая функция аппроксимирует логику вы выложенную в вопросе:

CREATE OR REPLACE FUNCTION smart_insert(table_name TEXT) RETURNS VOID AS $$ 
    DECLARE 
    target TEXT; 
    statement TEXT; 
    BEGIN 
    CASE table_name 
     WHEN 'this' THEN target := 'name_id'; 
     WHEN 'that' THEN target := 'lastname_id'; 
     WHEN 'another' THEN target := 'age_id'; 
    END CASE; 
    statement := 
     'INSERT INTO '||table_name||'('||target||') VALUES (nextval(''id''));'; 
    EXECUTE statement; 
    END; 
$$ LANGUAGE plpgsql; 

Обратите внимание, что я использую последовательность для заполнения этих таблиц (призыв к nextval). Я не уверен, что это ваш прецедент, но, надеюсь, этот пример достаточно расширяем, чтобы вы могли изменить его в соответствии со своим сценарием. Надуманная демонстрация:

postgres=# SELECT smart_insert('this'); 
smart_insert 
-------------- 

(1 row) 

postgres=# SELECT smart_insert('that'); 
smart_insert 
-------------- 

(1 row) 

postgres=# SELECT name_id FROM this; 
name_id 
--------- 
    101 
(1 row) 

postgres=# SELECT lastname_id FROM that; 
lastname_id 
------------- 
     102 
(1 row) 
0

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

CREATE OR REPLACE FUNCTION smart_insert(table_name TEXT) 
    RETURNS trigger AS 
$func$ 
BEGIN 
    EXECUTE 
    'INSERT INTO table1 (' 
    || CASE TG_TABLE_NAME 
     WHEN 'this' THEN 'name_id' 
     WHEN 'that' THEN 'lastname_id' 
     WHEN 'another' THEN 'age_id' 
     END CASE 
    ||') VALUES ($1)' 
    USING NEW.id; 
END 
$func$ LANGUAGE plpgsql; 
  • Для ссылки на id колонки новый ряд, используйте NEW.id нет id.NEW .

  • Чтобы передать значение в динамический код, используйте the USING clause of EXECUTE. Это быстрее и элегантнее, избегает литья до text и обратно, а также делает невозможным SQL-инъекцию.

  • Не используйте много переменных и назначений в plpgsql, где это сравнительно дорого.

Если перечисленные столбцы таблицы назначения не имеют не по умолчанию по умолчанию столбцов, не нужен даже динамический SQL:

CREATE OR REPLACE FUNCTION smart_insert(table_name TEXT) 
    RETURNS trigger AS 
$func$ 
BEGIN 
    INSERT INTO table1 (name_id, lastname_id, age_id) 
    SELECT CASE WHEN TG_TABLE_NAME = 'this' THEN NEW.id END 
     , CASE WHEN TG_TABLE_NAME = 'that' THEN NEW.id END 
     , CASE WHEN TG_TABLE_NAME = 'another' THEN NEW.id END; 
END 
$func$ LANGUAGE plpgsql; 

CASE выражения без ELSE оговорки по умолчанию будет NULL , который является стандартным столбцом по умолчанию.

Оба варианта безопасны для SQL-инъекций.

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