2012-08-03 76 views
0

我有兩個表上有觸發器。更新表邏輯

FIRST

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 

而且我有一個問題。如果我在第一個表中插入數據,它的觸發器也會在第二個表中插入數據。但是,該插入會導致第二個表的觸發器在第一個表上執行插入操作,依此類推。

你能幫我嗎?如何才能讓表格互相更新而不循環?

UPDATE
我還有一個問題 如何更改數據,當我在表中插入呢?例如,我在the_geom列中插入GEOMETRY。如果幾何的SRID=70066我想把這個函數ST_TRANSFORM(the_geom,900913)的工作列結果the_geom

更新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"

+1

你必須相互遞歸觸發器和要防止遞歸。你反而需要一個觸發器來觸發* only *在用戶的* direct *動作上,而不是通過觸發器的動作?如果是這樣,PostgreSQL不直接支持你想要的,你需要調整你的設計。如果你解釋了爲什麼你需要這兩個觸發器,表格是什麼等等,這將有所幫助。有可能建議避免這個問題的設計。 – 2012-08-03 08:29:41

+0

調整問題的措辭。正確? – 2012-08-03 08:32:12

+0

Okey im瞭解你。我改變表格,現在循環不能heppen。但我得到另一個問題。 – 2012-08-03 09:26:51

回答

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的觸發器。

+0

Tnx爲答案。我嘗試像你的觸發器,但我這種情況下,我得到錯誤'錯誤:控制到達觸發器程序結束沒有返回 上下文:PL/pgSQL函數「update_geom」'但我有一條線返回新; – 2012-08-06 04:31:26

+0

@KliverMax將完整的觸發文本放在pastebin或其他東西上併發布。沒有完整的觸發定義,我無能爲力。 – 2012-08-06 04:52:21

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)