0

トリガーが設定された 2 つのテーブルがあります。

最初

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

2番目

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

そして、私には問題があります。最初のテーブルにデータを挿入すると、そのトリガーは 2 番目のテーブルにもデータを挿入します。しかし、その挿入により、2 番目のテーブルのトリガーが最初のテーブルで挿入を実行するというようになります。

これで私を助けてもらえますか?ループせずにテーブルを相互に更新するにはどうすればよいですか?

更新
私は別の問題を抱えていますテーブルに挿入するときにデータを変更する方法は? たとえば、列に GEOMETRY を挿入しthe_geomます。そして、ジオメトリの場合、この関数の作業結果を列SRID=70066に入れたいと思います。the_geomST_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"

4

2 に答える 2

3

相互に再帰的なトリガーがあり、再帰を防止したい。代わりに、トリガーを介したアクションではなく、ユーザーからの直接的なアクションでのみトリガーを起動する必要があります。

残念ながら、PostgreSQL はあなたが望むものを直接サポートしていません。相互再帰を避けるために設計を微調整する必要があります。

更新された質問: トリガーで、の内容を変更しますNEW

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

トリガーについては、かなり優れたマニュアルを参照してください。

于 2012-08-03T13:02:01.247 に答える
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)
于 2012-08-03T13:53:52.517 に答える