更新表逻辑

时间:2012-08-03 07:12:21

标签: postgresql postgresql-8.4

我有两个带触发器的表。

第一

CREATE OR REPLACE FUNCTION update_table()
RETURNS trigger AS
$BODY$
 BEGIN
IF    TG_OP = 'UPDATE' THEN
    UPDATE filedata SET id=NEW.id,myData=NEW.myData,the_geom=ST_TRANSFORM(NEW.the_geom,70066) WHERE num=NEW.num;
    RETURN NEW;
ELSEIF TG_OP = 'INSERT' THEN
    INSERT INTO filedata(num,id,myData,the_geom) VALUES (NEW.num,NEW.id,NEW.myData,ST_TRANSFORM(NEW.the_geom,70066));
    INSERT INTO filestatus(id,name,status) VALUES (NEW.num,NEW.myData,'Не подтвержден');
    RETURN NEW;
END IF;

 END;
$BODY$
LANGUAGE plpgsql VOLATILE

第二

CREATE OR REPLACE FUNCTION update_table_temp()
RETURNS trigger AS
$BODY$
 BEGIN
IF    TG_OP = 'INSERT' THEN
    INSERT INTO filedata_temp(num,id,myData,the_geom) VALUES (NEW.num,NEW.id,NEW.myData,ST_TRANSFORM(NEW.the_geom,900913));
    RETURN NEW;
ELSEIF TG_OP = 'DELETE' THEN
    DELETE FROM filedata_temp WHERE num=OLD.num;
    RETURN OLD;
END IF;

 END;
$BODY$
LANGUAGE plpgsql VOLATILE

我有一个问题。如果我在第一个表中插入数据,它的触发器也会在第二个表中插入数据。但是该插入导致第二个表的触发器在第一个表上执行插入,依此类推。

你能帮我解决这个问题吗?如何在不循环的情况下让表格相互更新?

更新
我有另一个问题  当我在表中插入时如何更改数据?例如,我在the_geom列中插入GEOMETRY。如果几何的SRID=70066我希望将此函数the_geom放入ST_TRANSFORM(the_geom,900913)列结果。

更新2

触发器

  CREATE TRIGGER update_geom
  AFTER INSERT
  ON filedata_temp
  FOR EACH ROW
  EXECUTE PROCEDURE update_geom();

功能

 CREATE OR REPLACE FUNCTION update_geom()
 RETURNS trigger AS
 $$
 BEGIN
  IF ST_SRID(NEW.the_geom)=70066 THEN

    UPDATE filedata_temp SET id='88',the_geom=ST_TRANSFORM(NEW.the_geom,900913);
  END IF;
RETURN NEW;

END;
$$
LANGUAGE plpgsql;

如果我使用此功能触发器无效,但如果:

 CREATE OR REPLACE FUNCTION update_geom()
 RETURNS trigger AS
 $$
 BEGIN

    UPDATE filedata_temp SET id='88',the_geom=ST_TRANSFORM(NEW.the_geom,900913);
RETURN NEW;

END;
$$
LANGUAGE plpgsql;

我得到id=88,但ST_TRANSFORM不起作用。

更新3

ST_TRANSFORM()很好的功能,但它在我的情况下做了一些奇怪的事情。

例如我有一个表filedata_temp(SRID = 4326)。我使用srid = 70066插入几何体我尝试此触发器

 CREATE OR REPLACE FUNCTION update_geom()
 RETURNS trigger AS
 $$
 BEGIN

    UPDATE filedata_temp the_geom=ST_TRANSFORM(NEW.the_geom,4326);
RETURN NEW;

END;
$$
LANGUAGE plpgsql;

获得这个几何体。 "0103000020E6100000010000001800000097832C7ABD823741DA312CBF59F6174145ED23E0088337413CB8228A65F7174145ED23E0088337413CB8228A65F7174145ED23E0088337413CB8228A65F7174115B8A7F8208337416DE8C689ADF7174115B8A7F8208337416DE8C689ADF71741D1D3BAF56383374114BFD1303AF917418B016D395F8537413C2856DFF7F717413AF95F044C853741A997BC22A3F71741F88E75BD2D85374178C92D9BE6F61741F92A3B192685374165C8D76E31F61741C84AA37B26853741F2674F6A96F5174144F25B9B16853741E849D10C1BF5174105142CD2E384374112E19E8688F31741B72C78F697843741A808260138F31741FF0C0C6A0884374151A8BBFF76F21741832CF2EEF48337418BE15C1290F21741FFFB3AC6A3833741D85A253DF4F2174113E8B8956C83374109067F2139F31741E383648E3383374100C25C64D8F3174179BAEBD7178337412DA0D6482BF41741CF38E4F7038337410AB04BD7E5F41741C936158CE182374145C1EC5D99F5174197832C7ABD823741DA312CBF59F61741"

ST_transform()从SRID = 4326生成此字符串,并在EPSG:70066中转换几何体。

70066中有这个字符串

"0103000020B2110100010000001800000097832C7ABD823741DA312CBF59F6174145ED23E0088337413CB8228A65F7174145ED23E0088337413CB8228A65F7174145ED23E0088337413CB8228A65F7174115B8A7F8208337416DE8C689ADF7174115B8A7F8208337416DE8C689ADF71741D1D3BAF56383374114BFD1303AF917418B016D395F8537413C2856DFF7F717413AF95F044C853741A997BC22A3F71741F88E75BD2D85374178C92D9BE6F61741F92A3B192685374165C8D76E31F61741C84AA37B26853741F2674F6A96F5174144F25B9B16853741E849D10C1BF5174105142CD2E384374112E19E8688F31741B72C78F697843741A808260138F31741FF0C0C6A0884374151A8BBFF76F21741832CF2EEF48337418BE15C1290F21741FFFB3AC6A3833741D85A253DF4F2174113E8B8956C83374109067F2139F31741E383648E3383374100C25C64D8F3174179BAEBD7178337412DA0D6482BF41741CF38E4F7038337410AB04BD7E5F41741C936158CE182374145C1EC5D99F5174197832C7ABD823741DA312CBF59F61741"

并在4326

"0103000020E61000000100000018000000AE4F5BA2FC5B4E407E80E7E6F46C4C40F7F1BF79255C4E4019C32D62086D4C40F7F1BF79255C4E4019C32D62086D4C40F7F1BF79255C4E4019C32D62086D4C40A7CE9382325C4E40D8EA369C0D6D4C40A7CE9382325C4E40D8EA369C0D6D4C401BD2B101575C4E4064A420982A6D4C4090DF29FE665D4E4064EE5369116D4C408195B3905C5D4E403664043C0B6D4C4025A00D0E4C5D4E40F7FD7274FD6C4C404201C7B5475D4E409ADF7B26F06C4C403801C7B5475D4E40E43D0EBFE46C4C406EC339053F5D4E404085D2B7DB6C4C40BDFDA836235D4E4001EBC841BE6C4C40685B445FFA5C4E4015C4038EB86C4C40ADB5C108AD5C4E40727935C6AA6C4C408A6B4B9BA25C4E40331ECEACAC6C4C40A7368928775C4E40F7C22E47B46C4C409F640F9D595C4E4077694F81B96C4C40660C21333B5C4E4012EA7C62C56C4C406623646D2C5C4E40CE83E38FCB6C4C4042D9EDFF215C4E40C6A89957D96C4C4095D75EC00F5C4E4013FFA0A5E66C4C40AE4F5BA2FC5B4E407E80E7E6F46C4C40"

2 个答案:

答案 0 :(得分:3)

您有相互递归的触发器,并且您希望阻止递归。相反,您需要触发器仅在用户的直接操作时触发,而不是通过触发器触发操作。

不幸的是,PostgreSQL没有直接支持你想要的东西,你需要调整你的设计以避免相互递归。

更新了问题:在触发器中,更改NEW的内容,例如

IF tg_op = 'INSERT' OR tg_op = 'UPDATE' THEN
    NEW.the_geom := ST_TRANSFORM(NEW.the_geom,900913)
END IF;

请参阅really rather good manual触发器。

答案 1 :(得分:2)

        -- The scenario is:
        -- for UPDATEs we use an "alternating bit protocol"
        -- (could also be done by bumping and synchronisng a serial number)
        -- For INSERTs: we only test for NOT EXISTS.
        -- DELETEs are not yet implemented.
        -- *******************************************************************
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

        --
        -- Tables for test: we convert int <<-->> text
        --
CREATE TABLE one
        ( id INTEGER NOT NULL PRIMARY KEY
        , flipflag boolean NOT NULL default false
        , ztext varchar
        );
CREATE TABLE two
        ( id INTEGER NOT NULL PRIMARY KEY
        , flipflag boolean NOT NULL default false
        , zval INTEGER
        );
        ------------------------
CREATE function func_one()
RETURNS TRIGGER AS $body$
BEGIN

IF tg_op = 'INSERT' THEN

        INSERT INTO two (id,zval)
        SELECT NEW.id, NEW.ztext::integer
        WHERE NOT EXISTS (
                SELECT * FROM two WHERE two.id = NEW.id)
                ;
ELSIF tg_op = 'UPDATE' THEN

        UPDATE two
        SET zval = NEW.ztext::integer
        , flipflag = NOT flipflag
        WHERE two.id = NEW.id
                ;
END IF;

        RETURN NEW;
END;

$body$
language plpgsql;
CREATE TRIGGER trig_one_i
        AFTER INSERT ON one
        FOR EACH ROW
        EXECUTE PROCEDURE func_one()
        ;

CREATE TRIGGER trig_one_u
        AFTER UPDATE ON one
        FOR EACH ROW
        WHEN (NEW.flipflag = OLD.flipflag)
        EXECUTE PROCEDURE func_one()
        ;

        ------------------------
CREATE function func_two()
RETURNS TRIGGER AS $body$
BEGIN

IF tg_op = 'INSERT' THEN
        INSERT INTO one (id,ztext)
        SELECT NEW.id, NEW.zval::varchar
        WHERE NOT EXISTS (
                SELECT * FROM one WHERE one.id = NEW.id)
                ;
ELSIF tg_op = 'UPDATE' THEN
        UPDATE one
        SET ztext = NEW.zval::varchar
        , flipflag = NOT flipflag
        WHERE one.id = NEW.id
                ;
END IF;

        RETURN NEW;
END;

$body$
language plpgsql;

CREATE TRIGGER trig_two_i
        AFTER INSERT ON two
        FOR EACH ROW
        EXECUTE PROCEDURE func_two()
        ;
CREATE TRIGGER trig_two_u
        AFTER UPDATE ON two
        FOR EACH ROW
        WHEN (NEW.flipflag = OLD.flipflag)
        EXECUTE PROCEDURE func_two()
        ;        --
        -- enter some data
        --
INSERT INTO one (id,ztext)
select gs, gs::text
FROM generate_series(1,10) gs
        ;

        -- Change some data
UPDATE one SET ztext=100 where id = 1;
UPDATE two SET zval=10*zval where id IN (2,4,6,8,10);
INSERT INTO two (id, zval) VALUES(11,14);

SELECT * FROM one ORDER BY id;
SELECT * FROM two ORDER BY id;

结果:

NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "one_pkey" for table "one"
CREATE TABLE
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "two_pkey" for table "two"
CREATE TABLE
CREATE FUNCTION
CREATE TRIGGER
CREATE TRIGGER
CREATE FUNCTION
CREATE TRIGGER
CREATE TRIGGER
INSERT 0 10
UPDATE 1
UPDATE 5
INSERT 0 1
 id | flipflag | ztext 
----+----------+-------
  1 | f        | 100
  2 | t        | 20
  3 | f        | 3
  4 | t        | 40
  5 | f        | 5
  6 | t        | 60
  7 | f        | 7
  8 | t        | 80
  9 | f        | 9
 10 | t        | 100
 11 | f        | 14
(11 rows)

 id | flipflag | zval 
----+----------+------
  1 | t        |  100
  2 | f        |   20
  3 | f        |    3
  4 | f        |   40
  5 | f        |    5
  6 | f        |   60
  7 | f        |    7
  8 | f        |   80
  9 | f        |    9
 10 | f        |  100
 11 | f        |   14
(11 rows)