毎月作成されるこのテーブルがあります。例: model201707
( 'model' = fixed; '201707' =現在の日付に基づく年と月):
| COLUMN_NAME | TYPE |
|---------------|-------------|
| serial | varchar |
| lot | varchar |
| model | varchar |
| line | varchar |
| machine | varchar |
| datetimestamp | timestamptz |
値の例:
| serial | lot | model | line | machine | datetimestamp |
|--------|------------|--------|------|---------|---------------------|
| 1 | 16_F22_F23 | sample | A | 1 | 2017-02-28 07:22:39 |
| 2 | 16_F22_F23 | sample | A | 1 | 2017-02-28 07:22:42 |
| 3 | 16_F22_F23 | sample | A | 1 | 2017-02-28 07:22:45 |
テーブルからデータを取得する関数を作成しましたmodel201707
をテーブルに挿入しますtb_moldsummary
:
| COLUMN_NAME | TYPE | | | |
|---------------|-----------|----|----|-----|
| machine_name | varchar | NN | PK | |
| model | varchar | NN | PK | UNQ |
| mold | varchar | NN | PK | UNQ |
| cavity | varchar | NN | PK | UNQ |
| totalshots | int4 | | | |
| datetimestamp | timestamp | | | |
値の例:
| machine | model | m_id | cav_id | totalshots | datetimestamp |
|---------|--------|------|---------|------------|---------------------|
| 1 | sample | 16 | F22_F23 | 3 | 2017-02-28 07:22:45 |
関数:
CREATE OR REPLACE FUNCTION insert_data_func()
RETURNS TRIGGER AS
$BODY$
EXECUTE 'INSERT INTO tb_moldsummary '
|| 'SELECT NEW.machine, NEW.model, split_part(NEW.lot, ''_'', 1), '
|| 'SUBSTRING(NEW.lot FROM (POSITION(''_'' in NEW.lot)+1) FOR LENGTH(NEW.lot)), COUNT(lot), NEW.datetimestamp '
|| 'FROM model' || to_char(CURRENT_TIMESTAMP, 'YYYYMM')
|| ' WHERE lot = NEW.lot AND machine = NEW.machine GROUP BY machine, model, lot '
|| 'ON CONFLICT ON CONSTRAINT tb_summary_unique '
|| 'DO UPDATE SET '
|| 'machine = NEW.machine, '
|| 'totalshots = tb_moldsummary.totalshots + 1, '
|| 'datetimestamp = NEW.datetimestamp ';
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
CREATE TRIGGER insert_data_trigger
AFTER INSERT ON model201707
FOR EACH ROW
EXECUTE PROCEDURE insert_data_func();
エラー:
[Err] ERROR: missing FROM-clause entry for table "new" LINE 1: INSERT INTO tb_moldsummary SELECT NEW.machine, NEW.model, sp...
私は以下のリンクをすでにチェックしましたが、混乱しています:
PLPGSQL STATEMENTS EXECUTING DYNAMIC SQL
insert-record-into-a-table-in-a-trigger-function
この動的UPSERTの正しい構文は何ですか?
複数の問題。これはうまくいくはずです:
CREATE OR REPLACE FUNCTION insert_data_func()
RETURNS TRIGGER AS
$func$
BEGIN -- !
EXECUTE
$x$INSERT INTO tb_moldsummary AS t
SELECT $1.machine -- !
, $1.model
, split_part(lot, '_', 1)
, right(lot, position('_' IN lot) * -1) -- ! simpler
, COUNT(lot)
, $1.datetimestamp
FROM model$x$ || to_char(now(), 'YYYYMM') || '
WHERE lot = $1.lot
AND machine = $1.machine
GROUP BY machine, model, lot
ON CONFLICT ON CONSTRAINT tb_summary_unique
DO UPDATE
SET machine = $1.machine -- !
, totalshots = t.totalshots + 1
, datetimestamp = $1.datetimestamp'
USING NEW; -- !
RETURN NEW; -- can be RETURN NULL for AFTER trigger
END
$func$ LANGUAGE plpgsql;
重要な修正を行に付けました。
NEW
をEXECUTE
句を使用してUSING
に渡します(参照した質問への回答で指示されているとおり)。
ドル引用は、単一引用符を含む文字列リテラルの構文を簡略化するのに役立ちます。
交換する
SUBSTRING(NEW.lot FROM (POSITION('_' in NEW.lot)+1) FOR LENGTH(NEW.lot))
このよりシンプルで高速な同等の式を使用して:
right(NEW.lot, position('_' IN NEW.lot) * -1)