postgresql:在EXECUTE的动态命令中使用NEW。*

时间:2010-07-16 09:20:58

标签: postgresql inheritance triggers partitioning plpgsql

我尝试为postgresql 8.3创建一个plpgsql触发器,它在插入之前自动对表进行分区 由id列

如果目标表不存在,将创建它,插入到那里

所以我创建了带有新表名的insert语句,如此

exec_insert := 'INSERT INTO '||TG_TABLE_SCHEMA||'.'||TG_RELNAME||'_'||destinationid||' VALUES('||NEW.*||')';
EXECUTE exec_insert;

导致错误:

ERROR:  NEW used in query that is not in a rule

我有两个问题:

  1. 甚至可以在EXECUTE中使用NEW,还是在声明中有错误?
  2. 如果它不可能,任何人都知道如何从NEW中获取值,所以我可以在声明中使用它们?我唯一想到的是使用information_schema检索主表的列名,然后尝试动态访问NEW的值 - 我也不知道如何:(
  3. THX

2 个答案:

答案 0 :(得分:3)

您可以使用

...
_sql varchar(100)= 'insert into some_table values ($1.*)';
...
execute _sql using new;
...

我发现这隐藏在一些偏远地区:D。我正在使用9.1

答案 1 :(得分:0)

此设置在这里工作正常(版本8.4和9.0):

CREATE TABLE customer
(
  id bigserial NOT NULL,
  name text,
  datecreated timestamp with time zone DEFAULT now(),
  CONSTRAINT customer_pkey PRIMARY KEY (id) USING INDEX TABLESPACE pg_default
);

CREATE OR REPLACE FUNCTION test_trigger()
  RETURNS trigger AS
$BODY$
declare
    query   text;
begin
    query := 'INSERT INTO customer_' || substring(NEW.name,1,1) || ' VALUES(' || NEW.id || ','''|| NEW.name||''')';
    EXECUTE query;

    RETURN NULL;

    EXCEPTION
        WHEN undefined_table THEN
            query := 'CREATE TABLE "customer_' || substring(NEW.name,1,1) || 
            '"( CONSTRAINT "customer_' || substring(NEW.name,1,1) ||'_name_check" CHECK (lower(substring(name, 1, 1)) = ''' || substring(NEW.name,1,1) || '''::text)
            ) INHERITS (customer); CREATE INDEX "i_customer_' || substring(NEW.name,1,1) ||'_name" ON customer_' || substring(NEW.name,1,1) ||' USING btree(name);';
            EXECUTE query;

            query := 'INSERT INTO customer_' || substring(NEW.name,1,1) || ' VALUES(' || NEW.id || ','''|| NEW.name||''')';
            EXECUTE query;

            query := 'ANALYZE "customer_' || substring(NEW.name,1,1) || '"';
            EXECUTE query;

            RETURN NULL;

end;
$BODY$
  LANGUAGE plpgsql VOLATILE STRICT
  COST 100;

CREATE TRIGGER t_customer
  BEFORE INSERT OR UPDATE OR DELETE
  ON customer
  FOR EACH ROW
  EXECUTE PROCEDURE test_trigger();

CREATE TABLE customer
(
  id bigserial NOT NULL,
  name text,
  datecreated timestamp with time zone DEFAULT now(),
  CONSTRAINT customer_pkey PRIMARY KEY (id) USING INDEX TABLESPACE pg_default
);

CREATE OR REPLACE FUNCTION test_trigger()
  RETURNS trigger AS
$BODY$
declare
    query   text;
begin
    query := 'INSERT INTO customer_' || substring(NEW.name,1,1) || ' VALUES(' || NEW.id || ','''|| NEW.name||''')';
    EXECUTE query;

    RETURN NULL;

    EXCEPTION
        WHEN undefined_table THEN
            query := 'CREATE TABLE "customer_' || substring(NEW.name,1,1) || 
            '"( CONSTRAINT "customer_' || substring(NEW.name,1,1) ||'_name_check" CHECK (lower(substring(name, 1, 1)) = ''' || substring(NEW.name,1,1) || '''::text)
            ) INHERITS (customer); CREATE INDEX "i_customer_' || substring(NEW.name,1,1) ||'_name" ON customer_' || substring(NEW.name,1,1) ||' USING btree(name);';
            EXECUTE query;

            query := 'INSERT INTO customer_' || substring(NEW.name,1,1) || ' VALUES(' || NEW.id || ','''|| NEW.name||''')';
            EXECUTE query;

            query := 'ANALYZE "customer_' || substring(NEW.name,1,1) || '"';
            EXECUTE query;

            RETURN NULL;

end;
$BODY$
  LANGUAGE plpgsql VOLATILE STRICT
  COST 100;

CREATE TRIGGER t_customer
  BEFORE INSERT OR UPDATE OR DELETE
  ON customer
  FOR EACH ROW
  EXECUTE PROCEDURE test_trigger();

INSERT INTO customer(name) VALUES ('john'), ('peter');