我想使用
我一直在尝试三种方法来设置变量:
-
这些方法都不能在触发器中使用,当通过
我得出的结论是该函数在不同的事务和不同的(?)会话中触发。这是否可以配置,使所有操作在相同的上下文中完成?
SET
在会话/事务中记录用户的id,以便稍后可以使用current_setting
在触发器函数中访问它。基本上,我正在尝试第二种选项,与之前发布的非常相似的票证不同的是,我正在使用PG 10.1。我一直在尝试三种方法来设置变量:
-
SET local myvars.user_id = 4
,从而在事务中本地设置它;
- SET myvars.user_id = 4
,从而在会话中设置它;
- SELECT set_config('myvars.user_id', '4', false)
,根据最后一个参数,将是前两个选项的快捷方式。这些方法都不能在触发器中使用,当通过
current_setting
获取变量时,会收到null
的返回值。下面是我设计的脚本,用于解决问题(可以轻松使用postgres docker镜像):database=$POSTGRES_DB
user=$POSTGRES_USER
[ -z "$user" ] && user="postgres"
psql -v ON_ERROR_STOP=1 --username "$user" $database <<-EOSQL
DROP TRIGGER IF EXISTS add_transition1 ON houses;
CREATE TABLE IF NOT EXISTS houses (
id SERIAL NOT NULL,
name VARCHAR(80),
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT now(),
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS transitions1 (
id SERIAL NOT NULL,
house_id INTEGER,
user_id INTEGER,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT now(),
PRIMARY KEY(id),
FOREIGN KEY(house_id) REFERENCES houses (id) ON DELETE CASCADE
);
CREATE OR REPLACE FUNCTION add_transition1() RETURNS TRIGGER AS \$\$
DECLARE
user_id integer;
BEGIN
user_id := current_setting('myvars.user_id')::integer || NULL;
INSERT INTO transitions1 (user_id, house_id) VALUES (user_id, NEW.id);
RETURN NULL;
END;
\$\$ LANGUAGE plpgsql;
CREATE TRIGGER add_transition1 AFTER INSERT OR UPDATE ON houses FOR EACH ROW EXECUTE PROCEDURE add_transition1();
BEGIN;
%1% SELECT current_setting('myvars.user_id');
%2% SELECT set_config('myvars.user_id', '55', false);
%3% SELECT current_setting('myvars.user_id');
INSERT INTO houses (name) VALUES ('HOUSE PARTY') RETURNING houses.id;
SELECT * from houses;
SELECT * from transitions1;
COMMIT;
DROP TRIGGER IF EXISTS add_transition1 ON houses;
DROP FUNCTION IF EXISTS add_transition1;
DROP TABLE transitions1;
DROP TABLE houses;
EOSQL
我得出的结论是该函数在不同的事务和不同的(?)会话中触发。这是否可以配置,使所有操作在相同的上下文中完成?
myvars.user_id
是NULL,在使用SET LOCAL
后,它会在事务结束时重置为''
,我必须考虑所有情况。 - ChuckE