如何在psql运行时动态传递变量,构建DBA快捷查询命令?
刚好我之前也遇到过类似的需求,psql的原生反斜杠命令确实方便,但自定义带参数的快捷方式得用点小技巧,下面给你几个可行的方案:
方案1:利用psql的:argv变量(兼容所有psql版本)
psql在执行带参数的宏时,会把后续输入的内容放到:argv数组里,:argv[1]就是第一个参数,:argv[2]是第二个,以此类推。你可以在~/.psqlrc里这么定义:
\set size 'SELECT pg_size_pretty(my_size_function(quote_ident(:'argv[1]')));'
使用方式
直接在psql会话里输入:
:size public :size "my-schema" -- 带特殊字符的schema名也能处理
优化:添加默认值
如果希望不输入参数时默认查public schema,可以用COALESCE给个默认值:
\set size 'SELECT pg_size_pretty(my_size_function(COALESCE(quote_ident(:'argv[1]'), quote_ident(''public''))));'
这样输入:size就会自动查public的大小,输入参数就查指定schema。
方案2:用\define定义带参数的宏(PostgreSQL 12+)
PostgreSQL 12及以后的psql支持\define命令,可以直接定义带命名参数的宏,写法更直观:
在~/.psqlrc里添加:
\define size(schema) SELECT pg_size_pretty(my_size_function(quote_ident('':schema'')));
使用方式
调用时用括号传递参数:
:size(public) :size(my_schema)
这个方法的优势是参数名更清晰,不容易搞混多个参数的顺序,适合需要传多个参数的场景。
关键细节:为什么之前的方法行不通?
你之前尝试的\set size 'select pg_size_pretty(my_size_function(:schema));',问题在于psql的\set变量是静态替换——当你定义这个变量时,psql会立刻尝试替换:schema这个变量(而此时它还没被定义),所以必须先手动设置:schema才能用。
而上面的两种方案,都是在执行宏的时候才处理参数::argv是执行时动态获取的输入内容,\define的参数也是在调用时才替换,完美解决了动态传参的需求。
安全提示:用quote_ident处理标识符
schema、表名这类属于SQL标识符,不是字符串,所以一定要用quote_ident()函数来处理参数,而不是直接加单引号。这样可以避免SQL注入,同时正确处理带特殊字符、大写字母的标识符(比如"My-Schema"会被正确转义)。
内容的提问来源于stack exchange,提问作者kozone

