Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function 是否将表名和列名定义为plpgsql函数中的参数?_Function_Postgresql_Variables_Plpgsql_Dynamic Sql - Fatal编程技术网

Function 是否将表名和列名定义为plpgsql函数中的参数?

Function 是否将表名和列名定义为plpgsql函数中的参数?,function,postgresql,variables,plpgsql,dynamic-sql,Function,Postgresql,Variables,Plpgsql,Dynamic Sql,它一定很简单,但我正在进入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

它一定很简单,但我正在进入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;
有可能做到这一点吗?

当您将用户输入转换为代码时,您必须进行防御。其中包括来自系统目录或直接用户输入的表名和列名。通过这种方式,您还可以防止非标准标识符的琐碎异常。基本上有三种内置方法:

1. 第一个查询,已消毒:

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$;
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()
需要Postgres 9.1或更高版本。将其与
%I
格式说明符一起使用

表名本身可能不明确。您可能必须提供架构名称,以避免意外更改错误的表。相关的:

旁白:添加更便宜

2. 对于现有表名的特殊情况,也可以对注册类(
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$;
电话:

或:

旁白:考虑使用.

3. 已清除第二个查询:

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$;
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()
更干净

有关答案:


区分大小写! 请注意,此处未加引号的标识符不会转换为小写。在SQL中用作标识符时[Postgres自动转换为小写][7]。但这里我们传递动态SQL的字符串。如图所示进行转义时,驼峰大小写标识符(如
用户
)将通过双引号(
“用户”
)来保留,就像其他非标准名称一样,如
“带空格的名称”
“选择”等。因此,名称在此上下文中区分大小写

我的长期建议是只使用合法的小写标识符,不要担心这一点

旁白:单引号表示值,双引号表示标识符。见:

看一看。