在plpgsql函数中将表名和列名定义为参数?
它一定很简单,但我正在做我的第一步到Postgres函数,我找不到任何工作…
我想创build一个函数,将修改表和/或列,我找不到指定我的表和列作为我的函数参数的正确方法。
就像是:
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;
有没有可能做到这一点?
每当将用户input转换为代码时,您都必须防范SQL注入 。 这包括来自系统目录或来自直接用户input的表和列名称。 这样你也可以防止使用非标准标识符的简单例外。 基本上有三种内置的方法:
1. format()
第一个查询,消毒:
CREATE OR REPLACE FUNCTION foo(_t text) RETURNS void AS $func$ BEGIN EXECUTE format(' ALTER TABLE %I ADD COLUMN c1 varchar(20) , ADD COLUMN c2 varchar(20)', _t); END $func$ LANGUAGE plpgsql;
format()
需要Postgres 9.1或更高版本。 与%I
格式说明符一起使用。
单独的表名可能是不明确的。 您可能必须提供模式名称,以避免意外更改错误的表格。 有关:
- 在触发器函数中插入dynamic表名
- search_path如何影响标识符parsing和“当前模式”
另外: 使用单个ALTER TABLE
命令添加多个列更便宜。
regclass
您也可以使用regclass
types转换为已注册的类( regclass
)来处理现有表名的特殊情况。 可选模式限定。 这对于主叫用户无效且可见的表名称立即失败。 第一个查询用一个regclass
为regclass
:
CREATE OR REPLACE FUNCTION foo(_t regclass) RETURNS void AS $func$ BEGIN EXECUTE 'ALTER TABLE '|| _t ||' ADD COLUMN c1 varchar(20) , ADD COLUMN c2 varchar(20)'; END $func$ LANGUAGE plpgsql;
呼叫:
SELECT foo('table_name');
要么:
SELECT foo('my_schema.table_name'::regclass);
另外:考虑只使用text
而不是varchar(20)
。
3. quote_ident()
第二个查询已过滤:
CREATE OR REPLACE FUNCTION foo(_t regclass, _c text) RETURNS void AS $func$ BEGIN EXECUTE 'UPDATE '|| _t ||' -- sanitized with regclass SET '|| quote_ident(_c) ||' = ''This is a test'''; END $func$ LANGUAGE plpgsql;
对于多个连接/插值, format()
更清晰。
相关答案:
- 表名称作为PostgreSQL函数参数
- Postgres函数与准备的查询
区分大小写!
请注意,未加引号的标识符在这里不会转换为小写。 在SQL中用作标识符时Postgres自动转换为小写 。 但是在这里,我们为dynamicSQL传递string 。 当像已经certificate的那样转义时,CaMel-case标识符(如UserS
)将通过双引号( "UserS"
)保存,就像其他非标准名称,如"name with space"
"SELECT"
等。因此,名称区分大小写上下文。
我的build议是专门使用合法的小写字母标识符,而不用担心。
另外: 值的单引号,标识符的双引号 。