patternsqlModerate
I have an INSTEAD OF trigger, but PostgreSQL still complains while I insert into view
Viewed 0 times
postgresqltriggercomplainswhileinsertintobutviewinsteadstill
Problem
I have created a view and an INSTEAD OF trigger for inserting/ updating/ deleting from that view. Now I have tried to insert some data to the view, and PostgreSQL returns following error (translation from Czech: "chyba" = "error", "Stav SQL" = "SQL state"):
This happened before with some other INSTEAD OF triggers - this bug lasted just for some time (few hours? I don't remember exactly) and then PostgreSQL found the trigger. I tried various things (change the trigger, delete all triggers and views and creating them anew etc.), but I'm not sure what worked, just that something worked. So how exactly to make the PostgreSQL recognize the trigger?
I have PostgreSQL 9.3.4 and pgAdmin III 1.18.1 on Windows XP 32 bit. Just in case it was caused by something in the code, here it is:
```
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._ka
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: 55000This happened before with some other INSTEAD OF triggers - this bug lasted just for some time (few hours? I don't remember exactly) and then PostgreSQL found the trigger. I tried various things (change the trigger, delete all triggers and views and creating them anew etc.), but I'm not sure what worked, just that something worked. So how exactly to make the PostgreSQL recognize the trigger?
I have PostgreSQL 9.3.4 and pgAdmin III 1.18.1 on Windows XP 32 bit. Just in case it was caused by something in the code, here it is:
```
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._ka
Solution
You have a trigger
You can make that a trigger
Also consider this quote from the manual:
A row-level
indicate that it did not modify any data from the view's underlying
base tables, or it should return the view row that was passed in (the
the trigger performed the necessary data modifications in the view.
This will cause the count of the number of rows affected by the
command to be incremented. For
the trigger may modify the
change the data returned by
and is useful when the view will not show exactly the same data that
was provided.
INSTEAD OF DELETE in your code, but none INSTEAD OF INSERT. Create that, too.You can make that a trigger
INSTEAD OF INSERT OR DELETE, but I'd suggest separate trigger functions for INSERT and DELETE and separate triggers. Simplifies the function code (no more need for IF TG_OP = etc.).Also consider this quote from the manual:
A row-level
INSTEAD OF trigger should either return NULL toindicate that it did not modify any data from the view's underlying
base tables, or it should return the view row that was passed in (the
NEW row for INSERT and UPDATE operations, or the OLD row forDELETE operations). A nonnull return value is used to signal thatthe trigger performed the necessary data modifications in the view.
This will cause the count of the number of rows affected by the
command to be incremented. For
INSERT and UPDATE operations only,the trigger may modify the
NEW row before returning it. This willchange the data returned by
INSERT RETURNING or UPDATE RETURNING,and is useful when the view will not show exactly the same data that
was provided.
Context
StackExchange Database Administrators Q#63941, answer score: 10
Revisions (0)
No revisions yet.