ビューと、そのビューから挿入/更新/削除するためのINSTEAD OFトリガーを作成しました。今、私はビューにいくつかのデータを挿入しようとしました、そしてPostgreSQLは次のエラーを返します(チェコ語からの翻訳: "chyba" = "エラー"、 "Stav SQL" = "SQL状態"):
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
これは以前に他のINSTEAD OFトリガーで発生しました-このバグはしばらく(数時間?私は正確には覚えていません)続き、その後PostgreSQLがトリガーを見つけました。私はさまざまなことを試しました(トリガーを変更する、すべてのトリガーとビューを削除し、それらを新しく作成するなど)。しかし、何が機能しているかはわかりません。 PostgreSQLにトリガーを正確に認識させるにはどうすればよいですか?
私はPostgreSQL 9.3.4とpgAdmin III 1.18.1をWindowsにインストールしていますXP 32ビット。コード内の何かが原因で発生した場合に備えて、ここに示します。
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
);
コードにトリガーINSTEAD OF DELETE
がありますが、INSTEAD OF
INSERT
はありません。それも作成します。
あなたはそれをトリガー_INSTEAD OF INSERT OR DELETE
にすることができますが、私はINSERT
とDELETE
のための別々のトリガー関数と別々のトリガーを提案するでしょう。関数コードを簡略化します(IF TG_OP =
などは必要ありません)。
このマニュアルからの引用 も考慮してください:
行レベルの
INSTEAD OF
トリガーは、NULL
を返して、ビューの基礎となるベーステーブルのデータを変更しなかったことを示すか、渡されたビュー行(NEW行)を返す必要がありますINSERTおよびUPDATE操作の場合、またはOLD
操作の場合はDELETE
行)。 null以外の戻り値は、トリガーがビューで必要なデータ変更を実行したことを示すために使用されます。これにより、コマンドの影響を受ける行数のカウントが増加します。INSERT
およびUPDATE
操作の場合、トリガーはNEW行を変更してからそれを返す場合があります。これにより、INSERT RETURNING
またはUPDATE RETURNING
によって返されるデータが変更され、提供されたものとまったく同じデータがビューに表示されない場合に役立ちます。