将表名和列名定义为 plpgsql 函数中的参数?
Posted
技术标签:
【中文标题】将表名和列名定义为 plpgsql 函数中的参数?【英文标题】:Define table and column names as arguments in a plpgsql function? 【发布时间】:2013-08-25 09:40:19 【问题描述】:这一定很简单,但我正在迈出 Postgres 函数的第一步,但我找不到任何有用的东西...
我想创建一个函数来修改表和/或列,但我找不到将表和列指定为函数中的参数的正确方法。
类似:
CREATE OR REPLACE FUNCTION foo(t table)
RETURNS void AS $$
BEGIN
alter table t add column c1 varchar(20);
alter table t add column c2 varchar(20);
alter table t add column c3 varchar(20);
alter table t add column c4 varchar(20);
END;
$$ LANGUAGE PLPGSQL;
select foo(some_table)
在另一种情况下,我想要一个函数来改变某个表中的某个列:
CREATE OR REPLACE FUNCTION foo(t table, c column)
RETURNS void AS $$
BEGIN
UPDATE t SET c = "This is a test";
END;
$$ LANGUAGE PLPGSQL;
有可能吗?
【问题讨论】:
看看this post。 【参考方案1】:每当您将用户输入转化为代码时,您都必须防御SQL injection。这包括来自系统目录或直接用户输入的表名和列名。这样,您还可以防止使用非标准标识符的琐碎异常。基本上有三个内置方法:
1。 format()
第一个查询,已清理:
CREATE OR REPLACE FUNCTION foo(_t text)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format('
ALTER TABLE %I ADD COLUMN c1 varchar(20)
, ADD COLUMN c2 varchar(20)', _t);
END
$func$;
format()
需要 Postgres 9.1 或更高版本。将其与 %I
格式说明符一起使用。
单独的表名可能不明确。您可能必须提供模式名称以避免意外更改错误的表。相关:
INSERT with dynamic table name in trigger function How does the search_path influence identifier resolution and the "current schema"另外:添加multiple columns with a single ALTER TABLE
command 更便宜。
2。 regclass
对于现有表名的特殊情况,您还可以使用对已注册类 (regclass
) 的强制转换。可选的模式限定。对于调用用户无效且不可见的表名,此操作会立即且正常地失败。第一个查询通过转换为regclass
:
CREATE OR REPLACE FUNCTION foo(_t regclass)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE 'ALTER TABLE ' || _t || ' ADD COLUMN c1 varchar(20)
, ADD COLUMN c2 varchar(20)';
END
$func$;
呼叫:
SELECT foo('table_name');
或者:
SELECT foo('my_schema.table_name'::regclass);
另外:考虑只使用text
instead of varchar(20)
。
3。 quote_ident()
清理了第二个查询:
CREATE OR REPLACE FUNCTION foo(_t regclass, _c text)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE 'UPDATE ' || _t -- sanitized with regclass
|| ' SET ' || quote_ident(_c) || ' = ''This is a test''';
END
$func$;
对于多个连接/插值,format()
更干净...
相关答案:
Table name as a PostgreSQL function parameter Postgres functions vs prepared queries区分大小写!
请注意,未加引号的标识符在此处不转换为小写。在 SQL [Postgres 自动转换为小写][7] 中用作标识符时。但这里我们为动态 SQL 传递 strings。当按照演示转义时,CaMel 大小写标识符(如 UserS
)将通过双引号("UserS"
)保留,就像其他非标准名称如 "name with space"
"SELECT"
etc 一样。因此,在这种情况下,名称区分大小写。
我的一贯建议是只使用合法的小写标识符,不要担心。
除此之外:单引号用于值,双引号用于标识符。见:
https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS【讨论】:
以上是关于将表名和列名定义为 plpgsql 函数中的参数?的主要内容,如果未能解决你的问题,请参考以下文章