三月 5, 2024
摘要:pg_variables
模块提供了处理各种类型变量的函数。创建的变量仅在当前用户会话中可用。
目录
介绍
pg_variables 模块提供了处理各种类型变量的函数。创建的变量仅存在于当前用户会话中。默认情况下,创建的变量不是事务性的(即它们不受BEGIN
、COMMIT
或ROLLBACK
语句的影响)。然而,这是可以通过pgv_set()
的参数is_transactional
,进行定制的行为:
SELECT pgv_set('vars', 'int1', 101);
BEGIN;
SELECT pgv_set('vars', 'int2', 102);
ROLLBACK;
SELECT * FROM pgv_list() order by package, name;
package | name | is_transactional
---------+------+------------------
vars | int1 | f
vars | int2 | f
但如果是指定标记 is_transactional 创建的变量:
BEGIN;
SELECT pgv_set('vars', 'trans_int', 101, true);
SAVEPOINT sp1;
SELECT pgv_set('vars', 'trans_int', 102, true);
ROLLBACK TO sp1;
COMMIT;
SELECT pgv_get('vars', 'trans_int', NULL::int);
pgv_get
---------
101
您可以将变量聚集到包中。这样做是为了能够让变量具有不同的名称,或者快速删除整批变量。如果包变空了,则会自动删除。
安装
典型的安装过程可能如下所示:
$ cd pg_variables
$ make USE_PGXS=1
$ sudo make USE_PGXS=1 install
$ make USE_PGXS=1 installcheck
$ psql DB -c "CREATE EXTENSION pg_variables;"
模块函数
pg_variables 模块提供的函数如下表所示。
要使用 pgv_get() 函数,需要包和变量已经存在。要使用 pgv_get() 函数,必须使用 pgv_set() 函数设置变量。
如果一个包不存在,你会得到如下错误:
SELECT pgv_get('vars', 'int1', NULL::int);
ERROR: unrecognized package "vars"
如果一个变量不存在,你会得到如下错误:
SELECT pgv_get('vars', 'int1', NULL::int);
ERROR: unrecognized variable "int1"
pgv_get() 函数会检查变量类型。如果变量类型与函数类型不匹配,则会引发错误:
SELECT pgv_get('vars', 'int1', NULL::text);
ERROR: variable "int1" requires "integer" value
标量变量函数
函数 | 返回类型 |
---|---|
pgv_set(package text, name text, value anynonarray, is_transactional bool default false) |
void |
pgv_get(package text, name text, var_type anynonarray, strict bool default true) |
anynonarray |
数组变量函数
函数 | 返回类型 |
---|---|
pgv_set(package text, name text, value anyarray, is_transactional bool default false) |
void |
pgv_get(package text, name text, var_type anyarray, strict bool default true) |
anyarray |
pgv_set
参数:
package
- 包的名称,如果不存在,会创建。name
- 变量的名称,如果不存在,会创建该变量。如果变量已经存在,并且它的事务属性和is_transactional
参数不匹配 ,则pgv_set
会失败。value
- 变量的新值。如果变量已经存在,并且其类型与新值的类型不匹配,则pgv_set
会失败。is_transactional
- 新创建的变量的事务属性,默认为 false。
pgv_get
参数:
package
- 现有包的名称。如果包不存在,则结果取决于strict
参数:如果它为 false,则pgv_get
返回 NULL,否则会失败。name
- 现有变量的名称。如果变量不存在,则结果取决于strict
参数:如果它为 false,则pgv_get
返回 NULL,否则会失败。var_type
- 现有变量的类型。需要传递它以获得正确的返回类型。strict
- 如果之前没有创建变量或包的情况下,需要pgv_get
不引发错误,则传递 false,默认情况下为 true。
记录变量函数
模块提供了以下函数,来处理一系列记录类型。
要使用 pgv_update()、pgv_delete() 和 pgv_select() 函数,必须存在包和变量。否则会引发错误。需要使用 pgv_insert() 函数设置变量,才能使用这些函数。
pgv_update()、pgv_delete() 和 pgv_select() 函数会检查变量类型。如果变量类型不匹配记录类型,则会引发错误。
函数 | 返回类型 | 描述 |
---|---|---|
pgv_insert(package text, name text, r record, is_transactional bool default false) |
void |
将一条记录添加到变量集合中。如果包和变量不存在,它们将被创建。r 的第一列将是一个主键。如果存在具有相同主键的记录,则会引发错误。如果此变量集合具有其他结构,则会引发错误。 |
pgv_update(package text, name text, r record) |
boolean |
使用相应的主键更新记录(r 的第一列是主键)。如果找到记录,则返回 true。如果此变量集合具有其他结构,则会引发错误。 |
pgv_delete(package text, name text, value anynonarray) |
boolean |
使用相应的主键来删除一条记录(r 的第一列是主键)。如果找到记录,则返回 true。 |
pgv_select(package text, name text) |
set of record |
返回变量集合中的记录。 |
pgv_select(package text, name text, value anynonarray) |
record |
返回带有相应主键的记录(r 的第一列是主键)。 |
pgv_select(package text, name text, value anyarray) |
set of record |
返回带有相应主键的变量集合中的记录(r 的第一列是主键)。 |
辅助函数
函数 | 返回类型 | 描述 |
---|---|---|
pgv_exists(package text, name text) |
bool |
如果包和变量存在,则返回 true。 |
pgv_exists(package text) |
bool |
如果包存在,则返回 true。 |
pgv_remove(package text, name text) |
void |
使用相应的名称删除变量。所需的包和变量必须存在,否则将引发错误。 |
pgv_remove(package text) |
void |
使用相应的名称删除包和所有包变量。所需的包必须存在,否则将引发错误。 |
pgv_free() |
void |
删除所有包和变量。 |
pgv_list() |
table(package text, name text, is_transactional bool) |
返回已定义的包和变量的记录集。 |
pgv_stats() |
table(package text, allocated_memory bigint) |
返回已定义的包的列表,和占用的内存(以字节为单位)。 |
请注意,pgv_stats() 仅适用于 PostgreSQL 9.6 及更高版本。
示例
使用函数来处理标量和数组变量是很容易的:
SELECT pgv_set('vars', 'int1', 101);
SELECT pgv_set('vars', 'text1', 'text variable'::text);
SELECT pgv_get('vars', 'int1', NULL::int);
pgv_get_int
-------------
101
SELECT SELECT pgv_get('vars', 'text1', NULL::text);
pgv_get
---------------
text variable
SELECT pgv_set('vars', 'arr1', '{101,102}'::int[]);
SELECT pgv_get('vars', 'arr1', NULL::int[]);
pgv_get
-----------
{101,102}
假设我们有一个 tab 表:
CREATE TABLE tab (id int, t varchar);
INSERT INTO tab VALUES (0, 'str00'), (1, 'str11');
然后你可以使用函数来处理记录变量:
SELECT pgv_insert('vars', 'r1', tab) FROM tab;
SELECT pgv_select('vars', 'r1');
pgv_select
------------
(1,str11)
(0,str00)
SELECT pgv_select('vars', 'r1', 1);
pgv_select
------------
(1,str11)
SELECT pgv_select('vars', 'r1', 0);
pgv_select
------------
(0,str00)
SELECT pgv_select('vars', 'r1', ARRAY[1, 0]);
pgv_select
------------
(1,str11)
(0,str00)
SELECT pgv_delete('vars', 'r1', 1);
SELECT pgv_select('vars', 'r1');
pgv_select
------------
(0,str00)
您可以列出包和变量:
SELECT * FROM pgv_list() order by package, name;
package | name | is_transactional
---------+-------+------------------
vars | arr1 | f
vars | int1 | f
vars | r1 | f
vars | text1 | f
并获取已占用的内存(以字节为单位):
SELECT * FROM pgv_stats() order by package;
package | allocated_memory
---------+------------------
vars | 49152
您可以删除变量或整个包:
SELECT pgv_remove('vars', 'int1');
SELECT pgv_remove('vars');
您可以删除所有包和变量:
SELECT pgv_free();
如果你想要支持事务和保存点的变量,你应该在函数pgv_set()
或pgv_insert()
的最后一个参数,带上标记is_transactional = true
。以下用例描述了事务型变量的行为:
SELECT pgv_set('pack', 'var_text', 'before transaction block'::text, true);
BEGIN;
SELECT pgv_set('pack', 'var_text', 'before savepoint'::text, true);
SAVEPOINT sp1;
SELECT pgv_set('pack', 'var_text', 'savepoint sp1'::text, true);
SAVEPOINT sp2;
SELECT pgv_set('pack', 'var_text', 'savepoint sp2'::text, true);
RELEASE sp2;
SELECT pgv_get('pack', 'var_text', NULL::text);
pgv_get
---------------
savepoint sp2
ROLLBACK TO sp1;
SELECT pgv_get('pack', 'var_text', NULL::text);
pgv_get
------------------
before savepoint
ROLLBACK;
SELECT pgv_get('pack', 'var_text', NULL::text);
pgv_get
--------------------------
before transaction block
如果您在BEGIN
或SAVEPOINT
语句之后创建了一个事务型变量,然后回滚到前面的状态 - 变量将不再存在:
BEGIN;
SAVEPOINT sp1;
SAVEPOINT sp2;
SELECT pgv_set('pack', 'var_int', 122, true);
RELEASE SAVEPOINT sp2;
SELECT pgv_get('pack', 'var_int', NULL::int);
pgv_get
---------
122
ROLLBACK TO sp1;
SELECT pgv_get('pack','var_int', NULL::int);
ERROR: unrecognized variable "var_int"
COMMIT;
您可以通过ROLLBACK
撤消删除事务型变量,但如果您删除整个包,则所有常规变量会被永久删除:
SELECT pgv_set('pack', 'var_reg', 123);
SELECT pgv_set('pack', 'var_trans', 456, true);
BEGIN;
SELECT pgv_free();
SELECT * FROM pgv_list();
package | name | is_transactional
---------+------+------------------
(0 rows)
-- Memory is allocated yet
SELECT * FROM pgv_stats();
package | allocated_memory
---------+------------------
pack | 24576
ROLLBACK;
SELECT * FROM pgv_list();
package | name | is_transactional
---------+-----------+------------------
pack | var_trans | t
一旦您创建了一个事务型变量,则每次要通过函数pgv_set()
、pgv_insert()
更改变量值时,都应使用标记is_transactional
。如果您尝试变更此事务型标记,您会得到一个错误:
SELECT pgv_insert('pack', 'var_record', row(123::int, 'text'::text), true);
SELECT pgv_insert('pack', 'var_record', row(456::int, 'another text'::text));
ERROR: variable "var_record" already created as TRANSACTIONAL
函数pgv_update()
和pgv_delete()
不需要此标记。