Gcc(Debian 4.9.2-10)4.9.2、64ビットでコンパイルされたx86_64-unknown-linux-gnu上のPostgreSQL 9.4.3の私のテーブルとトリガー:
_CREATE TABLE measurements (
measurement_id SERIAL PRIMARY KEY NOT NULL,
measurement_size_in_bytes INTEGER NOT NULL
);
CREATE TABLE file_headers (
header_id SERIAL PRIMARY KEY NOT NULL,
measurement_id INTEGER NOT NULL,
file_header_index_start INTEGER,
file_header_index_end INTEGER
);
CREATE TRIGGER measurement_ids AFTER INSERT
ON measurements FOR EACH ROW
EXECUTE PROCEDURE ins_function('SELECT measurement_id FROM measurements
ORDER BY measurement_id desc limit 1;', 1, 666 );
_
ここで、SERIAL以降、SELECTのデータ型はINTEGERであると想定しましたが、トリガーを開始する次のコマンドからエラーメッセージが表示されるため、明らかにfalseです。
_INSERT INTO measurements (measurement_size_in_bytes) VALUES (888);`
_
_ERROR: invalid input syntax for integer: "SELECT measurement_id FROM measurements ORDER BY measurement_id desc limit 1;" CONTEXT: PL/pgSQL function ins_function() line 10 at assignment
_
ins_function()
および@a_horse_with_no_nameと@Joishiのコメントに基づく編集:
_CREATE OR REPLACE FUNCTION ins_function() RETURNS TRIGGER AS $$
--
-- Perform AFTER INSERT operation on file_header by creating rows with new.measurement_id, new.file_header_index_start and new.file_header_index_end.
--
DECLARE
measurement_id INTEGER;
file_header_index_start INTEGER;
file_header_index_end INTEGER;
BEGIN
SELECT a.measurement_id INTO measurement_id from measurements a ORDER BY measurement_id desc limit 1;
file_header_index_start := TG_ARGV[0];
file_header_index_end := TG_ARGV[1];
IF TG_OP = 'INSERT' THEN
INSERT INTO file_headers (measurement_id, file_header_index_start, file_header_index_end)
VALUES (measurement_id, file_header_index_start, file_header_index_end);
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
$$ LANGUAGE plpgsql;
--
-- Function and trigger on INSERT.
--
CREATE TRIGGER measurement_ids AFTER INSERT
ON measurements FOR EACH ROW EXECUTE PROCEDURE ins_function(1, 666);
_
エラーは発生しませんが、出力は間違っています。テーブルで正常に表示されているのにINSERT
がテーブル_file_headers
_に表示されていませんmeasurements。
ですから、TEXTからINTへのキャストについて考え始めましたが、_TG_ARGV[]
_はテキストのデータ型なので、これは基本的な操作になるはずです。失敗した試みの1つはformat('SELECT $1.%I', TG_ARGV[0])
です。 regclass
はinsaft_function()
の- here の説明どおりに機能します
_SELECT NEW.measurement_id, TG_ARGV[0]::regclass, TG_ARGV[1]::regclass;
_
_file_headers
_テーブルへのINSERTが成功しないのはなぜですか?
未解決の名前の競合があります。
宣言せずに古いバージョンのPostgresを使用している必要があります。または、デフォルト以外の構成設定で操作しています。
ここでは、_measurement_id
_という名前の変数を宣言します。
_DECLARE
measurement_id INTEGER;
_
あいまいな変数名を最初から使用するのはfollyです。とにかくそれをするなら、あなたはあなたがしていることを知っている必要があります。 __measurement_id
_のように、列名とは異なり、変数名の先頭にアンダースコアを付けるのは慣れさせています。
後のSELECT
ステートメントはあいまいです:
_ORDER BY measurement_id
_
これにより、デフォルトの設定で最新のPostgreSQLにエラーメッセージが表示されます。 ドキュメントごと :
デフォルトでは、PL/pgSQLはSQLステートメントの名前が変数またはテーブルの列を参照できる場合、エラーを報告します。
そして:
システム全体でこの動作を変更するには、構成パラメーター_
plpgsql.variable_conflict
_をerror、use_variable、またはuse_column(errorは出荷時のデフォルト)のいずれかに設定します。このパラメータは、PL/pgSQL関数内のステートメントの後続のコンパイルに影響しますが、現在のセッションですでにコンパイルされているステートメントには影響しません。この設定を変更すると、PL/pgSQL関数の動作に予期しない変更が発生する可能性があるため、スーパーユーザーのみが変更できます。
9.0より古いPostgresでは、これは変数を意味するように解決されます。 ドキュメントごと
そのような場合、PL/pgSQLがあいまいな参照を変数として解決するように指定できます(これは、PL/pgSQLの動作PostgreSQL 9.0より前)
大胆な強調鉱山。
これにより、任意の結果になります。これは、ソート順が未定であるためです。
_CREATE OR REPLACE FUNCTION insaft_function()
RETURNS TRIGGER AS
$func$
DECLARE
_measurement_id integer;
_file_header_index_start integer := TG_ARGV[0]::int;
_file_header_index_end integer := TG_ARGV[1]::int;
BEGIN
SELECT a.measurement_id INTO _measurement_id
FROM measurements a
ORDER BY a.measurement_id DESC -- you had ambiguity here!
LIMIT 1;
IF TG_OP = 'INSERT' THEN -- noise if only used in AFTER INSERT trigger
INSERT INTO file_headers (measurement_id, file_header_index_start
, file_header_index_end)
VALUES (_measurement_id, _file_header_index_start, _file_header_index_end);
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END
$func$ LANGUAGE plpgsql;
_
これは_AFTER INSERT
_トリガーでのみ使用されるため、どのようにinsaft_function()
と名付けたかに注意してください。
引き金:
_CREATE TRIGGER insaft_measurement_ids
AFTER INSERT ON measurements
FOR EACH ROW EXECUTE PROCEDURE insaft_function(1, 666);
_
しかし、提供された設定では、関数を大幅に簡略化できます。
_CREATE OR REPLACE FUNCTION insaft_function()
RETURNS TRIGGER AS
$func$
BEGIN
INSERT INTO file_headers (measurement_id, file_header_index_start
, file_header_index_end)
VALUES (NEW.measurement_id, TG_ARGV[0]::int, TG_ARGV[1]::int);
RETURN NULL; -- result ignored since this is an AFTER trigger
END
$func$ LANGUAGE plpgsql;
_