Динамическое имя таблицы для запроса 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
Есть и другие способы: