首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PostgreSQL plpgsql -变量列名

PostgreSQL plpgsql -变量列名
EN

Stack Overflow用户
提问于 2017-07-21 06:50:56
回答 3查看 9.3K关注 0票数 8

我正在创建一个触发器,它使用列的动态名称。

代码语言:javascript
复制
NEW.name:=2222; -- works fine !

代码语言:javascript
复制
dynamic_column:='name';
EXECUTE '$1.'||dynamic_column||':=2222 ' USING NEW; -- raises error

给出错误:

错误:"$1“行1处或附近的语法错误:$1.name:=2222

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-07-21 11:01:58

我在这里找到了信息:Assign to NEW by key in a Postgres trigger

如果我们通过以下方式启用模块hstore:

代码语言:javascript
复制
CREATE EXTENSION hstore;

我们可以这样做:

代码语言:javascript
复制
dynamic_column:='name';    
temp_sql_string:='"'||dynamic_column||'"=>"2222"';
NEW := NEW #= temp_sql_string::hstore;

现在将记录NEW.name设置为值2222。

感谢您努力寻找解决方案@Laurenz

票数 8
EN

Stack Overflow用户

发布于 2017-07-21 08:45:49

问题是,这不是一个有效的SQL语句。

可以使用动态SQL访问new中的列,如下所示:

代码语言:javascript
复制
EXECUTE 'SELECT $1.id' INTO v_id USING NEW;

NEW中更改单个列是不合适的。

您可以使用TG_RELID获取表的OID,查询列的pg_attribute,组成由NEW中的值和新值组成的行文本字符串,将其转换为表类型,并将结果分配给NEW。挺累赘的。

下面是这样做的示例代码(我对其进行了测试,但可能还会留下bug):

代码语言:javascript
复制
CREATE OR REPLACE FUNCTION dyntrig() RETURNS trigger
   LANGUAGE plpgsql AS
$$DECLARE
   colname text;
   colval text;
   newrow text := '';
   fieldsep text := 'ROW(';
BEGIN
   /* loop through the columns of the table */
   FOR colname IN
      SELECT attname
      FROM pg_catalog.pg_attribute
      WHERE attrelid = TG_RELID
        AND attnum > 0
        AND NOT attisdropped
      ORDER BY attnum
   LOOP
      IF colname = 'name' THEN
         colval = '2222';
      ELSE
         /* all other columns than 'name' retain their value */
         EXECUTE 'SELECT CAST($1.' || quote_ident(colname) || ' AS text)'
            INTO colval USING NEW;
      END IF;

      /* compose a string that represents the new table row */
      IF colval IS NULL THEN
         newrow := newrow || fieldsep || 'NULL';
      ELSE
         newrow := newrow || fieldsep || '''' || colval || '''';
      END IF;
      fieldsep := ',';
   END LOOP;
   newrow := newrow || ')';

   /* assign the new table row to NEW */
   EXECUTE 'SELECT (CAST(' || newrow || ' AS '
           || quote_ident(TG_TABLE_SCHEMA) || '.' || quote_ident(TG_TABLE_NAME)
           || ')).*'
      INTO NEW;

   RETURN NEW;
END;$$;
票数 5
EN

Stack Overflow用户

发布于 2017-07-22 02:16:20

你已经找到 on dba.SE了。您也可能对以下相应的参考答案感兴趣:

由于您从变量构造辅助hstore值,所以我建议使用简单函数hstore()

代码语言:javascript
复制
CREATE OR REPLACE FUNCTION dyn_trigger_func()
  RETURNS TRIGGER AS
$func$
DECLARE
   dyn_col_name text := 'name';
   dyn_col_val  text := '2222';
BEGIN
   NEW := NEW #= hstore(dyn_col_name, dyn_col_val);
   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

这样更快/更简单/更清晰/更安全。

或者,由于它显然是一个触发器函数,所以您可能希望在CREATE TRIGGER语句中传递列名和值:

代码语言:javascript
复制
CREATE OR REPLACE FUNCTION dyn_trigger_func()
  RETURNS TRIGGER AS
$func$
BEGIN
   NEW := NEW #= hstore(TG_ARGV[0], TG_ARGV[1]);
   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

和:

代码语言:javascript
复制
CREATE TRIGGER ins_bef
BEFORE INSERT ON tbl
FOR EACH ROW EXECUTE PROCEDURE dyn_trigger_func('name', '2222');

提供不带引号和区分大小写的列名.

相关信息:

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45230881

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档