相关疑难解决方法(0)

在触发器函数中使用动态表名INSERT

我不确定如何实现以下内容:

CREATE OR REPLACE FUNCTION fnJobQueueBEFORE() RETURNS trigger AS $$
    DECLARE
        shadowname varchar := TG_TABLE_NAME || 'shadow';
    BEGIN
        INSERT INTO shadowname VALUES(OLD.*);
        RETURN OLD;
    END;
$$
LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

即将值插入到具有动态生成名称的表中.
执行上面的代码会产生:

ERROR:  relation "shadowname" does not exist
LINE 1: INSERT INTO shadowname VALUES(OLD.*)
Run Code Online (Sandbox Code Playgroud)

它似乎表明变量不会作为表名扩展/允许.我在Postgres手册中没有发现这个.

我已经尝试过EXECUTE这样的事情:

  EXECUTE 'INSERT INTO ' || quote_ident(shadowname) || ' VALUES ' || OLD.*;
Run Code Online (Sandbox Code Playgroud)

但没有运气:

ERROR:  syntax error at or near ","
LINE 1: INSERT INTO personenshadow VALUES (1,sven,,,)
Run Code Online (Sandbox Code Playgroud)

RECORD类型似乎失去了:OLD.*似乎被转换为字符串,并得到的重新解析,导致各种各样的类型的问题(例如NULL值). …

postgresql triggers dynamic-sql plpgsql

31
推荐指数
1
解决办法
2万
查看次数

使用PL/pgsql中的EXECUTE从通用触发器插入NEW.*

我有许多使用Postgres"Partitioning"功能的表.我想在每个表上定义一个常见的BEFORE INSERT OF ROW触发器,1)如果针对父表发生插入,则动态创建分区; 2)对分区重新执行插入.

就像是:

CREATE OR REPLACE FUNCTION partition_insert_redirect( )
RETURNS trigger AS $BODY$
BEGIN
  ... create the new partition and set up the redirect Rules ...

  /* Redo the INSERT dynamically.  The new RULE will redirect it to the child table */
  EXECUTE 'INSERT INTO ' || quote_ident(TG_TABLE_SCHEMA) || '.' || quote_ident(TG_TABLE_NAME) ||
          ' SELECT NEW.*'
END
Run Code Online (Sandbox Code Playgroud)

但是在EXECUTE SQL中看不到"NEW"记录.我怎样才能尽可能简单地完成这项工作?

作为替代方案,我可以以某种方式迭代新记录中的字段吗?

我想过使用临时表:

EXECUTE 'CREATE TEMPORARY TABLE new_row (LIKE ' ||
        quote_ident(TG_TABLE_SCHEMA) || '.' || quote_ident(TG_TABLE_NAME) ||
        ') ON …
Run Code Online (Sandbox Code Playgroud)

postgresql triggers plpgsql

15
推荐指数
2
解决办法
1万
查看次数

自我管理PostgreSQL分区表

我正在尝试使用Postgres进行自我管理的分区表设置.这一切都围绕着这个功能,但我似乎无法让Postgres接受我的表名.自我管理分区表触发器功能的任何想法或示例?

我目前的职能:

DECLARE
day integer;
year integer;
tablename text;
startdate text;
enddate text;
BEGIN
day:=date_part('doy',to_timestamp(NEW.date));
year:=date_part('year',to_timestamp(NEW.date));
tablename:='pings_'||year||'_'||day||'_'||NEW.id;
-- RAISE EXCEPTION 'tablename=%',tablename;
PERFORM 'tablename' FROM pg_tables WHERE 'schemaname'=tablename;
-- RAISE EXCEPTION 'found=%',FOUND;
IF FOUND <> TRUE THEN
    startdate:=date_part('year',to_timestamp(NEW.date))||'-'||date_part('month',to_timestamp(NEW.date))||'-'||date_part('day',to_timestamp(NEW.date));
    enddate:=startdate::timestamp + INTERVAL '1 day';
    EXECUTE 'CREATE TABLE $1 (
        CHECK ( date >= DATE $2 AND date < DATE $3 )
    ) INHERITS (pings)' USING quote_ident(tablename),startdate,enddate;
END IF;
EXECUTE 'INSERT INTO $1 VALUES (NEW.*)' USING quote_ident(tablename);
RETURN NULL;
END;
Run Code Online (Sandbox Code Playgroud)

我希望它自动创建一个名为的表,pings_YEAR_DOY_ID但它始终失败: …

postgresql inheritance plpgsql database-partitioning

3
推荐指数
1
解决办法
5671
查看次数

如何在触发器函数中将 NEW.* 传递给 EXECUTE

我有一个简单的任务是将巨大的 MD5 值插入到表(分区表)中,并创建了一个触发器和一个触发器函数来代替INSERT操作。在函数中,我检查了前两个字符NEW.md5以确定应插入哪个表。

DECLARE
  tb text;
BEGIN
  IF TG_OP = 'INSERT' THEN
    tb = 'samples_' || left(NEW.md5, 2);
    EXECUTE(format('INSERT INTO %s VALUES (%s);', tb, NEW.*)); <- WRONG
  END IF;
  RETURN NULL;
END;
Run Code Online (Sandbox Code Playgroud)

问题是如何连接NEW.*到SQL语句中?

postgresql triggers dynamic-sql plpgsql

1
推荐指数
1
解决办法
2817
查看次数