在Postgres(plpgsql)中用单引号替换双引号

问题描述:

我正在为分区表在plpgsql中构建一个触发函数,并且所有逻辑都可以正常工作,但是在将实际记录插入到表中时遇到了麻烦.

I am building a trigger function in plpgsql for my partitioned table and I've got all of my logic working, but am having trouble inserting the actual record into my table.

我必须通过变量引用来引用我的特定表,以便(据我所知)迫使我使用EXECUTE命令,如下所示:

I have to reference my specific table by a variable reference, so that (as far as I understand) forces me to use an EXECUTE command, as so:

EXECUTE 'INSERT INTO ' || tablename || ' VALUES ' || NEW.*;

但是,这不能以Postgres的INSERT函数可以理解的方式来解压缩存储在NEW中的记录.它将记录转换为字符串,同时保留其中所有的双引号. IE.上面的代码在执行后变成了以下内容:

However, this does not handle unpacking the record stored in NEW in a way that Postgres' INSERT function can understand. It converts the record into a string while preserving all of the double quotes within. I.e. the above turns into the following upon execution:

INSERT INTO cfs_hgt_05152016_05202016
VALUES ("2016-05-16 00:00:00","2016-05-12 06:00:00",HGT,"1000 mb",9,-71,-38.5371)

问题在于Postgres认为由于双引号,这些值现在是列.

The problem with this is Postgres thinks these values are now columns due to the double quotes.

COPY cfs_hgt_master, line 1: ""2016-05-16 00:00:00","2016-05-12 06:00:00","HGT","1000 mb",9,-71,-38.5371"
ERROR:  column "2016-05-16 00:00:00" does not exist

我尝试通过以下方法对此进行补救:

I tried to remedy this by the following:

record_text := regexp_replace(NEW.*, '"', '\'', 'gi');
EXECUTE 'INSERT INTO ' || tablename || ' VALUES ' || record_text;

但是像这样转义单引号会产生错误:

But escaping the single quote like that produces an error:

psql:cfs_hgt_trigger_function.sql:36: ERROR:  unterminated quoted string at or near "' || record_text;
LINE 30: ...  EXECUTE 'INSERT INTO ' || tablename || ' VALUES ' || recor...
                                                              ^

有人可以帮助我弄清楚如何适当地避免使用单引号,或者建议完成我的任务的另一种方法吗?

Could someone help me figure out how to either properly escape that single quote, or suggest an alternative means of accomplishing my task?

完全不要将转换为其文本表示形式 .使用 USING子句传递值的EXECUTE .

Don't convert values to their text representation at all. Pass values with the USING clause of EXECUTE.

并正确转义表名.您可以使用 format() 为此:

And escape table names properly. You can use format() for this:

EXECUTE format('INSERT INTO %I SELECT $1.*', tablename)
USING NEW;

详细信息:

  • INSERT with dynamic table name in trigger function
  • How to pass NEW.* to EXECUTE in trigger function