gsql设置变量
【摘要】 gsql提供类似于Linux的shell命令的变量特性,可以使用gsql的元命令\set设置一个变量,格式如下:\set varname value要删除一个变量请使用如下方式:\unset varname*gsql作为客户端使用,在执行的sql语句发生错误时默认不会退出,而是继续执行后续的命令,需要客户业务自行检查sql执行情况,来决定是否退出。通常,我们期望gsql在执行sql脚本的过程...
gsql提供类似于Linux的shell命令的变量特性,可以使用gsql的元命令\set设置一个变量,格式如下:
\set varname value
要删除一个变量请使用如下方式:\unset varname
*gsql作为客户端使用,在执行的sql语句发生错误时默认不会退出,而是继续执行后续的命令,需要客户业务自行检查sql执行情况,来决定是否退出。通常,我们期望gsql在执行sql脚本的过程中遇到报错能够及时退出,暴露问题,推荐设置如下参数:
1,*对于单条语句,执行错误时要求退出,可以设置如下参数:\set ON_ERROR_STOP on
sql命令执行错误时gsql在跑批模式(gsql xxxxx -f xxxx)下会自动退出,交互模式下不会退出。
在第二条sql语句报错退出。
2,对于gsql元命令来说,我们期望元命令执行错误时也能及时退出,继续执行的话可能出现非预期的情况。*建议设置COMMAND_ERROR_STOP为on.
特殊变量COMMAND_ERROR_STOP使用示例:
当COMMAND_ERROR_STOP为on时,元命令执行错误时,报错退出。开启时能有效的识别到元命令的执行错误。
当COMMAND_ERROR_STOP为off时,元命令执行错误时,打印相关信息不退出,脚本继续执行。
\set COMMAND_ERROR_STOP on
\i /home/omm/copy_data.sql
select id, name from student;
如上脚本中COMMAND_ERROR_STOP设置为on,元命令报错之后输出错误信息,脚本不再执行
gsql:test.sql:2: /home/omm/copy_data.sql: Not a directory
如果COMMAND_ERROR_STOP设置为off,元命令报错之后输出错误信息,继续执行SELECT语句
gsql:test.sql:2: /home/omm/copy_data.sql: Not a directory
id | name
----+------
1 | Jack
(1 row)
3,对于事务,通常,我们期望事务中不会发生错误,出现错误时需要能够及时退出报错。
和事务相关的参数设置中有如下参数影响事务中的错误处理逻辑:
ON_ERROR_ROLLBACK: 如果是on,当一个事务块里的语句产生错误的时候,这个错误将被忽略而事务继续;如果是interactive,这样的错误只是在交互的会话里忽略;如果是off(缺省),事务块里一个语句生成的错误将会回滚整个事务。on_error_rollback-on模式是通过在一个事务块的每个命令前隐含地发出一个SAVEPOINT的方式工作的,在发生错误的时候回滚到该事务块。
事务中出现问题通常建议回滚整个事务,gsql默认情况下会回滚该事务,也是符合我们正常期望的,建议保持参数默认值
以上参数设置可以保证sql语句出现错误时,能够及时报错退出;
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
如果客户不想设置如上参数,可以自行在语句执行之后进行错误判断。需要注意如下事项:
gsql 允许sql语句中间穿插元命令,由此我们需要注意判断ERROR变量的值,该变量代表上一条sql执行的结果。有的时候我们可能会写错sql,或者写的不完整,gsql从上往下扫描脚本里的每一行,如果是sql语句,会记录在query_buffer中,并解析当前query_buffer中是否是一条完整的sql语句, 如果是,则发送给数据库执行,如果不是,则继续扫描, 如果扫描到元命令,则直接执行。在这样的逻辑下,sql脚本可以这样写:
SELECT
usename,
\if false
query,
\endif
application_name
FROM
pg_stat_activity
WHERE
application_name = 'cn_';
这种在gsql中是允许的。 但是通常我们并不会用这种写法,这种写法大多数时候不太直观。使用这种写法时需要注意下面这种问题:
SELECT * from pg_stat_activity limit 1; -- 语句1
\if ${ERROR} -- 判断1
\q -1
\endif
SELECT * from pg_stat_activity limit 2 -- 语句2
\if ${ERROR} -- 判断2
\q -1
\endif
insert into xxxxx;
语句2并没有写完,这时候gsql会把语句2保留在query_buffer中,继续扫描下面的语句。此时判断2中ERROR变量实际上存储的是语句1的执行结果,这时候存在误判,没有正常退出,继续执行下面的语句是非预期的。-- 建议设置\set INCOMPLETE_QUERY_ERROR true
这样,gsql在执行元命令前,会检查query_buffer里是否带有语句,如果带有,说明出现了sql中穿插元命令的情况,设置该变量为true后,在流程控制元命令前会检查query_buffer中是否还有未执行完的语句,如果有,则会报错退出,避免继续执行下去,出现异常。
(ERROR变量的说明补充中)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
以上是一些跑批时的参数设置推荐。
还有需要注意的场景是,在sql语句的结果集过大时,建议设置FETCH_COUNT保持在合理的范围内,参考产品文档设置在100 - 1000:
问题场景:
1,gsql查询的结果集太大,导致gsql使用内存过高,被系统杀死。
gsql默认是获取到所有的结果,然后解析并打印,libpq中会保存一份结果,gsql在处理结果时也会保存一份结果,导致gsql进程的内存使用量大。
1)使用方法:\set FETCH_COUNT 10,然后执行语句
2)后台使用游标执行,for循环中fetch获得结果集并打印,前端没有差异,后台执行的SQL语句如下
START TRANSACTION
CURSOR _psql_cursor NO SCROLL FOR select relname from pg_class limit 30;
FETCH FORWARD 10 FROM _psql_cursor
FETCH FORWARD 10 FROM _psql_cursor
FETCH FORWARD 10 FROM _psql_cursor
FETCH FORWARD 10 FROM _psql_cursor
CLOSE _psql_cursor
COMMIT
也就是使用fetch获取数据,并且获取一部分就打印一部分
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)