我有两个带触发器的表。
第一
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"
答案 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)