Динамическое имя таблицы для запроса INSERT INTO

Я пытаюсь выяснить, как написать INSERT INTO запрос с именем таблицы и именем столбца источника в качестве параметра.

Для начала я просто пытался параметризовать имя исходной таблицы. Я написал следующий запрос. Сейчас я объявляю и присваиваю значение переменной tablename напрямую, но в реальном примере это будет из какого-то другого источника / списка. Целевая таблица имеет только один столбец.

CREATE OR REPLACE FUNCTION foo()
RETURNS void AS
$$
DECLARE
    tablename text;
BEGIN
   tablename := 'Table_1';
   EXECUTE 'INSERT INTO "Schemaname"."targettable"
   SELECT "Col_A"
   FROM "schemaname".'
   ||quote_ident(tablename);
END
$$ LANGUAGE PLPGSQL;

Хотя запрос выполняется без каких-либо ошибок, изменения не отражаются в целевой таблице. При выполнении запроса я получаю следующий вывод.

Запрос в порядке, затронуто 0 строк (время выполнения: 296 мс; общее время: 296 мс)

Я хочу, чтобы изменения были отражены в целевой таблице. Я не знаю, как решить проблему.

1 ответ

Проверенный код

CREATE OR REPLACE FUNCTION foo()
   RETURNS void AS
$func$
DECLARE
   _tbl text := 'Table_1';  -- or 'table_1'?
BEGIN       
   EXECUTE 'INSERT INTO schemaname.targettable(column_name)
   SELECT  "Col_A"
   FROM    schemaname.' || quote_ident(_tbl);  -- or "Schemaname"?
END
$func$  LANGUAGE plpgsql;
  • Всегда используйте явный список целей для постоянного INSERT заявления.

  • Вы можете назначить переменные во время объявления.

  • Это широко распространенная глупость - использовать идентификаторы в двойных кавычках, чтобы сохранить иное незаконное написание. Вы должны держать двойные кавычки имя до конца его существования. Кажется, одна или несколько из этих ошибок проникли в ваш код: "Schemaname" или же "schemaname"? Table_1 или же "Table_1"?

  • Когда вы предоставляете идентификатор, такой как имя таблицы, как text параметр и избежать его с quote_ident(), он чувствителен к регистру!
    Идентификаторы в коде SQL приводятся к нижнему регистру, если не заключены в двойные кавычки. Но quote-ident() (который вы должны использовать для защиты от SQL-инъекций) сохраняет написанное вами слово в двойных кавычках, где это необходимо.

Функция с параметром

CREATE OR REPLACE FUNCTION foo(_tbl text)
   RETURNS void AS
$func$
BEGIN       
   EXECUTE 'INSERT INTO schemaname.targettable(column_name)
   SELECT  "Col_A"
   FROM    schemaname.' || quote_ident(_tbl);
END
$func$  LANGUAGE plpgsql;

Вызов:

SELECT foo('tablename');  -- tablename is case sensitive

Есть и другие способы:

Другие вопросы по тегам