fgc*_*hix 16 postgresql variables function dynamic-sql plpgsql
它必须简单,但我正在迈出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)
Run Code Online (Sandbox Code Playgroud)
在另一种情况下,我想要一个改变某个表中某个列的函数:
CREATE OR REPLACE FUNCTION foo(t table, c column)
RETURNS void AS $$
BEGIN
UPDATE t SET c = "This is a test";
END;
$$ LANGUAGE PLPGSQL;
Run Code Online (Sandbox Code Playgroud)
有可能吗?
Erw*_*ter 30
每当您将用户输入转换为代码时,您必须防御SQL注入.这包括来自系统目录或来自直接用户输入的表名和列名.这样,您还可以防止使用非标准标识符的普通异常.基本上有三种内置方法:
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;
Run Code Online (Sandbox Code Playgroud)
format()
需要Postgres 9.1或更高版本.将它与%I
格式说明符一起使用.
仅表格名称可能不明确.您可能必须提供架构名称以避免意外更改错误的表.有关:
除此之外:使用单个命令添加多个列ALTER TABLE
更便宜.
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;
Run Code Online (Sandbox Code Playgroud)
呼叫:
SELECT foo('table_name');
Run Code Online (Sandbox Code Playgroud)
要么:
SELECT foo('my_schema.table_name'::regclass);
Run Code Online (Sandbox Code Playgroud)
除此之外:考虑使用text
而不是varchar(20)
.
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;
Run Code Online (Sandbox Code Playgroud)
对于多个连接/插值,format()
更清晰......
相关答案:
请注意,此处不会将未加引号的标识符强制转换为小写.当在SQL Postgres中用作标识符时自动转换为小写.但是在这里我们传递动态SQL的字符串.当演示转义时,CaMel案例标识符(如UserS
)将由doublequoting()保存"UserS"
,就像其他非标准名称一样"name with space"
"SELECT"
.因此,名称在此上下文中区分大小写.
我的常设建议是专门使用合法的小写标识符,从不担心这一点.
旁白:值的单引号,标识符的双引号.
归档时间: |
|
查看次数: |
19341 次 |
最近记录: |