问题
I have two tables with triggers on them.
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
SECOND
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
And I have a problem. If I insert data in the first table its trigger inserts data in the second table too. But that insert causes the second table's trigger to do an insert on the first table, and so on.
Can you help me with this? How to can I get the tables to update each other without looping?
UPDATE
i have another problem
How to change data when i INSERT it in table? For example i insert GEOMETRY in the_geom
column. And if geometry's SRID=70066
i want to put in the_geom
column result of working of this function ST_TRANSFORM(the_geom,900913)
.
UPDATE 2
trigger
CREATE TRIGGER update_geom
AFTER INSERT
ON filedata_temp
FOR EACH ROW
EXECUTE PROCEDURE update_geom();
function
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;
If i use this function trigger no work but if this:
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;
i get id=88
but ST_TRANSFORM not work.
UPDATE 3
ST_TRANSFORM() nice function but its do something strange in my case.
For example i have a table filedata_temp(SRID=4326). I Insert geometry with srid=70066 i try this trigger
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;
And get this geometry.
"0103000020E6100000010000001800000097832C7ABD823741DA312CBF59F6174145ED23E0088337413CB8228A65F7174145ED23E0088337413CB8228A65F7174145ED23E0088337413CB8228A65F7174115B8A7F8208337416DE8C689ADF7174115B8A7F8208337416DE8C689ADF71741D1D3BAF56383374114BFD1303AF917418B016D395F8537413C2856DFF7F717413AF95F044C853741A997BC22A3F71741F88E75BD2D85374178C92D9BE6F61741F92A3B192685374165C8D76E31F61741C84AA37B26853741F2674F6A96F5174144F25B9B16853741E849D10C1BF5174105142CD2E384374112E19E8688F31741B72C78F697843741A808260138F31741FF0C0C6A0884374151A8BBFF76F21741832CF2EEF48337418BE15C1290F21741FFFB3AC6A3833741D85A253DF4F2174113E8B8956C83374109067F2139F31741E383648E3383374100C25C64D8F3174179BAEBD7178337412DA0D6482BF41741CF38E4F7038337410AB04BD7E5F41741C936158CE182374145C1EC5D99F5174197832C7ABD823741DA312CBF59F61741"
ST_transform() make this string from SRID=4326 and geometry which transform in EPSG:70066.
There is this string in 70066
"0103000020B2110100010000001800000097832C7ABD823741DA312CBF59F6174145ED23E0088337413CB8228A65F7174145ED23E0088337413CB8228A65F7174145ED23E0088337413CB8228A65F7174115B8A7F8208337416DE8C689ADF7174115B8A7F8208337416DE8C689ADF71741D1D3BAF56383374114BFD1303AF917418B016D395F8537413C2856DFF7F717413AF95F044C853741A997BC22A3F71741F88E75BD2D85374178C92D9BE6F61741F92A3B192685374165C8D76E31F61741C84AA37B26853741F2674F6A96F5174144F25B9B16853741E849D10C1BF5174105142CD2E384374112E19E8688F31741B72C78F697843741A808260138F31741FF0C0C6A0884374151A8BBFF76F21741832CF2EEF48337418BE15C1290F21741FFFB3AC6A3833741D85A253DF4F2174113E8B8956C83374109067F2139F31741E383648E3383374100C25C64D8F3174179BAEBD7178337412DA0D6482BF41741CF38E4F7038337410AB04BD7E5F41741C936158CE182374145C1EC5D99F5174197832C7ABD823741DA312CBF59F61741"
And in 4326
"0103000020E61000000100000018000000AE4F5BA2FC5B4E407E80E7E6F46C4C40F7F1BF79255C4E4019C32D62086D4C40F7F1BF79255C4E4019C32D62086D4C40F7F1BF79255C4E4019C32D62086D4C40A7CE9382325C4E40D8EA369C0D6D4C40A7CE9382325C4E40D8EA369C0D6D4C401BD2B101575C4E4064A420982A6D4C4090DF29FE665D4E4064EE5369116D4C408195B3905C5D4E403664043C0B6D4C4025A00D0E4C5D4E40F7FD7274FD6C4C404201C7B5475D4E409ADF7B26F06C4C403801C7B5475D4E40E43D0EBFE46C4C406EC339053F5D4E404085D2B7DB6C4C40BDFDA836235D4E4001EBC841BE6C4C40685B445FFA5C4E4015C4038EB86C4C40ADB5C108AD5C4E40727935C6AA6C4C408A6B4B9BA25C4E40331ECEACAC6C4C40A7368928775C4E40F7C22E47B46C4C409F640F9D595C4E4077694F81B96C4C40660C21333B5C4E4012EA7C62C56C4C406623646D2C5C4E40CE83E38FCB6C4C4042D9EDFF215C4E40C6A89957D96C4C4095D75EC00F5C4E4013FFA0A5E66C4C40AE4F5BA2FC5B4E407E80E7E6F46C4C40"
回答1:
You have mutually recursive triggers and you want to prevent the recursion. Your instead want a trigger to fire only on a direct action from a user, not an action via a trigger.
Unfortunately, PostgreSQL doesn't directly support what you want, you'll need to tweak your design to avoid the mutual recursion.
Updated question: In a trigger, alter the contents of NEW
, eg
IF tg_op = 'INSERT' OR tg_op = 'UPDATE' THEN
NEW.the_geom := ST_TRANSFORM(NEW.the_geom,900913)
END IF;
See the really rather good manual for triggers.
回答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;
RESULT:
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)
来源:https://stackoverflow.com/questions/11790990/update-tables-logic