我试图在
INSERT
中的每个新行 PostgreSQL
之后填充一些计算列,但我无法让它工作。
我已经阅读了这些帖子(我知道这些是针对
SQLite
的 - 这个问题最初是针对SQLite
的,但我已将其更改为PostgreSQL
- 一旦我得到,我会看看SQLite
PG
版本正在运行):
和
但我想知道我是否有使用
SELECT
语句和FOR EACH ROW
中的TRIGGER
语句,因为我仅想要计算刚刚插入的行的值,而不是所有行。
有关更多历史记录,这个问题是我上一个问题的延续:
这是桌子设置:
CREATE TABLE myTable (
datetime TEXT,
sys_id INT,
cputil REAL,
memfree REAL,
sessnum INT,
util_lag REAL, -- to be calculated AFTER INSERT via TRIGGER
mem_lag REAL, -- to be calculated AFTER INSERT via TRIGGER
util_diff REAL, -- to be calculated AFTER INSERT via TRIGGER
mem_diff REAL -- to be calculated AFTER INSERT via TRIGGER
util_change TEXT -- to be calculated AFTER INSERT via TRIGGER
);
现在进行
TRIGGER
设置。
我尝试了以下 SQL TRIGGER
语法,但无法让它工作:
CREATE TRIGGER tr_fill_calculated_columns
AFTER INSERT ON myTable
BEGIN
UPDATE myTable
SET util_lag = LAG(cputil) OVER (ORDER BY datetime),
SET mem_lag = LAG(memfree) OVER (ORDER BY datetime),
SET util_diff = cputil - util_lag,
SET mem_diff = memfree - mem_lag,
SET util_change = CASE
WHEN util_diff > 0 THEN 'Up'
WHEN util_diff < 0 THEN 'Down'
WHERE datetime = NEW.datetime AND sys_id = NEW.sys_id
END;
我还尝试了以下方法(我认为这更接近
PostgreSQL
中需要完成的方式):
CREATE OR REPLACE FUNCTION fn_calculate_columns_after_insert
RETURNS TRIGGER
LANGUAGE PLPGSQL
AS $$
BEGIN
NEW.util_lag := (SELECT LAG(cputil) OVER (ORDER BY datetime) FROM myTable);
NEW.mem_lag := (SELECT LAG(memfree) OVER (ORDER BY datetime) FROM myTable);
NEW.util_diff := cputil - util_lag;
NEW.mem_diff := memfree - mem_lag;
IF NEW.util_diff > 0 THEN
NEW.util_change := 'Up';
IF NEW.util_diff < 0 THEN
NEW.util_change := 'Down';
ELSE
NEW.util_change := '';
RETURN NEW;
END;
$$
CREATE TRIGGER tr_fill_calculated_columns
AFTER INSERT ON myTable
FOR EACH ROW
EXECUTE FUNCTION fn_calculate_columns_after_insert();
无论我尝试什么,我都会不断获得
SQL error [42601]: ERROR: syntax error at or near ";"
或接近其他角色。这真让我抓狂。官方文档或示例教程都没有给出我想要做什么的示例,我认为这并不难 - 根据新插入的行中的现有列值更新简单的计算列。在我看来非常基本。
完整的数据集包含数亿行,因此性能很重要 - 我只希望 TRIGGER 在 INSERT 之后立即计算最后一行,此后不再查询它,也就是说,我只希望 TRIGGER 作用于新的正在插入的行(每次插入新行时)。
为了帮助明确我在结果中寻找什么,这里有一些触发前数据示例:
datetime,sys_id,cputil,memfree,sessnum
2019/05/03 08:06:14,100,0.57,0.51,47
2019/05/03 08:11:14,100,0.47,0.62,43
2019/05/03 08:16:14,100,0.56,0.57,62
2019/05/03 08:21:14,100,0.57,0.56,50
2019/05/03 08:26:14,100,0.35,0.46,43
2019/05/03 08:31:14,100,0.41,0.58,48
2019/05/03 08:36:14,100,0.57,0.35,58
2019/05/03 08:41:14,100,0.41,0.4,58
2019/05/03 08:46:14,100,0.53,0.35,62
2019/05/03 08:51:14,100,0.51,0.6,45
2019/05/03 08:56:14,100,0.32,0.37,47
2019/05/03 09:01:14,100,0.62,0.59,60
2019/05/03 09:06:14,100,0.66,0.72,57
2019/05/03 09:11:14,100,0.54,0.54,44
2019/05/03 09:16:14,100,0.29,0.4,47
2019/05/03 09:21:14,100,0.43,0.68,66
2019/05/03 09:26:14,100,0.49,0.66,65
2019/05/03 09:31:14,100,0.64,0.55,66
2019/05/03 09:36:14,100,0.42,0.6,42
2019/05/03 09:41:14,100,0.55,0.59,63
这是所需的触发后结果的示例,其中计算列由触发器/功能填充:
datetime,sys_id,cputil,memfree,sessnum,util_lag,mem_lag,util_diff,mem_diff,util_change
2019/05/03 08:06:14,100,0.57,0.51,47,[NULL],[NULL],[NULL],[NULL],[NULL]
2019/05/03 08:11:14,100,0.47,0.62,43,0.57,0.51,-0.1,0.11,Down
2019/05/03 08:16:14,100,0.56,0.57,62,0.47,0.62,0.0900000000000001,-0.05,Up
2019/05/03 08:21:14,100,0.57,0.56,50,0.56,0.57,0.0099999999999999,-0.0099999999999999,Up
2019/05/03 08:26:14,100,0.35,0.46,43,0.57,0.56,-0.22,-0.1,Down
2019/05/03 08:31:14,100,0.41,0.58,48,0.35,0.46,0.06,0.12,Up
2019/05/03 08:36:14,100,0.57,0.35,58,0.41,0.58,0.16,-0.23,Up
2019/05/03 08:41:14,100,0.41,0.4,58,0.57,0.35,-0.16,0.05,Down
2019/05/03 08:46:14,100,0.53,0.35,62,0.41,0.4,0.12,-0.05,Up
2019/05/03 08:51:14,100,0.51,0.6,45,0.53,0.35,-0.02,0.25,Down
2019/05/03 08:56:14,100,0.32,0.37,47,0.51,0.6,-0.19,-0.23,Down
2019/05/03 09:01:14,100,0.62,0.59,60,0.32,0.37,0.3,0.22,Up
2019/05/03 09:06:14,100,0.66,0.72,57,0.62,0.59,0.04,0.13,Up
2019/05/03 09:11:14,100,0.54,0.54,44,0.66,0.72,-0.12,-0.18,Down
2019/05/03 09:16:14,100,0.29,0.4,47,0.54,0.54,-0.25,-0.14,Down
2019/05/03 09:21:14,100,0.43,0.68,66,0.29,0.4,0.14,0.28,Up
2019/05/03 09:26:14,100,0.49,0.66,65,0.43,0.68,0.06,-0.02,Up
2019/05/03 09:31:14,100,0.64,0.55,66,0.49,0.66,0.15,-0.11,Up
2019/05/03 09:36:14,100,0.42,0.6,42,0.64,0.55,-0.22,0.0499999999999999,Down
2019/05/03 09:41:14,100,0.55,0.59,63,0.42,0.6,0.13,-0.01,Up
最后,我也想知道如何在 SQLite 中执行此操作,即执行完全相同的操作的正确 SQLite 语法是什么?
从您的
SQL error [42601]: ERROR: syntax error at or near ";"
开始:演示
IF
条件语句需要后续的END IF
。该错误具有误导性,因为解析器正在寻找该错误,找到了最近的END
,即最后的那个。它想要一个 END IF
,却得到了一个 END;
- 因此投诉。CREATE OR REPLACE FUNCTION fn_calculate_columns_after_insert()--missing parentheses here
RETURNS TRIGGER LANGUAGE PLPGSQL AS $f$
BEGIN
NEW.util_lag := (SELECT LAG(cputil) OVER (ORDER BY datetime) FROM myTable);
NEW.mem_lag := (SELECT LAG(memfree) OVER (ORDER BY datetime) FROM myTable);
NEW.util_diff := cputil - util_lag;
NEW.mem_diff := memfree - mem_lag;
IF NEW.util_diff > 0 THEN
NEW.util_change := 'Up';
END IF;--this was missing
IF NEW.util_diff < 0 THEN
NEW.util_change := 'Down';
ELSE
NEW.util_change := '';
END IF;--this was missing
RETURN NEW;
END;--This semicolon is optional because it's immediately followed by closing dollar qoutes.
$f$;--This semicolon was missing. It is not optional, because it ends the whole `create function` statement
现在它已被接受,没有错误,但我必须看看它是否符合您的要求。