Pav*_* V. 5 postgresql trigger view plpgsql
我创建了一个视图和一个 INSTEAD OF 触发器,用于从该视图中插入/更新/删除。现在我尝试向视图中插入一些数据,PostgreSQL 返回以下错误(捷克语翻译:“chyba”=“error”,“Stav SQL”=“SQL state”):
ERROR: cannot insert into view "ukaz_lok"
DETAIL: Views that return columns that are not columns of their base relation are not automatically updatable.
HINT: To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.
********** Chyba **********
ERROR: cannot insert into view "ukaz_lok"
Stav SQL: 55000
Run Code Online (Sandbox Code Playgroud)
这发生在其他一些 INSTEAD OF 触发器之前 - 这个错误只持续了一段时间(几个小时?我不记得了)然后 PostgreSQL 找到了触发器。我尝试了各种事情(更改触发器,删除所有触发器和视图并重新创建它们等),但我不确定什么有效,只是有些东西有效。那么究竟如何让 PostgreSQL 识别触发器呢?
我在 Windows XP 32 位上有 PostgreSQL 9.3.4 和 pgAdmin III 1.18.1。以防万一它是由代码中的某些内容引起的,这里是:
CREATE TABLE lokalita
(
kod_lok text NOT NULL,
nazev text NOT NULL,
katastr text NOT NULL,
presnost integer NOT NULL,
stred geometry(Point,4326) NOT NULL,
rozsah geometry(Polygon,4326),
CONSTRAINT pk_lok PRIMARY KEY (kod_lok),
CONSTRAINT fk_pro_pr FOREIGN KEY (presnost)
REFERENCES pro_presnost (id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
)
WITH (
OIDS=FALSE
);
CREATE OR REPLACE VIEW ukaz_lok AS
SELECT
l.kod_lok AS _kod,
l.nazev AS _nazev,
l.katastr AS _katastr,
l.presnost AS _presnost,
50.0 AS _sirka,
14.0 AS _delka
FROM lokalita l;
CREATE OR REPLACE FUNCTION osetri_lok() RETURNS trigger AS $$
BEGIN
IF TG_OP = 'INSERT' THEN
INSERT INTO lokalita (kod_lok, nazev, katastr, presnost, stred)
VALUES(
NEW._kod,
NEW._nazev,
NEW._katastr,
NEW._presnost,
ST_GeomFromText('POINT('|| NEW.delka ||' '|| NEW.sirka ||')', 4326)
);
ELSIF TG_OP = 'UPDATE' THEN
UPDATE lokalita
SET
nazev = NEW._nazev,
katastr = NEW._katastr,
presnost = NEW._presnost,
stred = ST_GeomFromText('POINT('|| NEW.delka ||' '|| NEW.sirka ||')', 4326)
WHERE lod_lok = OLD._kod;
ELSIF TG_OP = 'DELETE' THEN
DELETE FROM lokalita WHERE kod_lok = OLD._kod;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER osetri_lok
INSTEAD OF DELETE ON ukaz_lok
FOR EACH ROW
EXECUTE PROCEDURE osetri_lok();
INSERT INTO ukaz_lok (_kod, _nazev, _katastr, _presnost, _delka, _sirka)
VALUES(
'Kote2',
'Kot?h?lky 2',
'Kot?h?lky',
2,
14.060316,
50.432044
);
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 10
您INSTEAD OF DELETE
的代码中有一个触发器,但没有INSTEAD OF
INSERT
。也创造那个。
您可以将其设为 trigger INSTEAD OF INSERT OR DELETE
,但我建议为INSERT
andDELETE
和单独的触发器使用单独的触发器功能。简化功能代码(不再需要IF TG_OP =
等)。
还要考虑手册中的引用:
行级
INSTEAD OF
触发器应该返回NULL
以指示它没有修改视图底层基表中的任何数据,或者它应该返回传入的视图行(NEW
用于INSERT
和UPDATE
操作的OLD
行,或用于DELETE
操作的行 )。非空返回值用于表示触发器在视图中执行了必要的数据修改。这将导致受命令影响的行数增加。仅对于INSERT
和UPDATE
操作,触发器可能会NEW
在返回之前修改该行。这将更改INSERT RETURNING
或返回的数据UPDATE RETURNING
,并且在视图不会显示与提供的完全相同的数据时很有用。
归档时间: |
|
查看次数: |
10344 次 |
最近记录: |