如何通过SSH远程查询PostgreSQL文本字段?解决单引号转义报错
你猜的完全正确!问题根源就是单引号的嵌套冲突。当你在ssh -t的双引号命令里嵌套psql -c的单引号参数时,SQL语句里的'username'会提前闭合psql -c后面的单引号——bash会把第一个'当成psql -c参数的开始,遇到username前面的'就直接闭合了,剩下的内容被当成额外的命令,而PostgreSQL拿到的SQL变成了SELECT rolname FROM pg_roles WHERE rolname = username;,自然会把username当成列名,抛出"column does not exist"的错误。
下面给你几个实用的解决办法,按场景选择就行:
方案1:用双单引号转义SQL内的单引号(最简单)
在bash的单引号字符串中,两个连续的单引号会被解析成一个单引号。所以只要把SQL里的'username'改成''username'',就能避免提前闭合的问题:
ssh -t remote_server "cd /; sudo -u postgres psql -c 'SELECT rolname FROM pg_roles WHERE rolname = ''username'';'"
这个方案最适合简单的SQL语句,改动最小。
方案2:用双引号包裹psql的-c参数(需转义外层双引号)
如果你的SQL里没有需要bash替换的变量,可以把psql -c的参数用双引号包裹,同时用反斜杠转义外层的双引号,避免和ssh命令的双引号冲突:
ssh -t remote_server "cd /; sudo -u postgres psql -c \"SELECT rolname FROM pg_roles WHERE rolname = 'username';\""
这种方式也很直观,适合SQL里有单引号但不需要变量替换的场景。
方案3:使用Here Document(适合复杂SQL)
如果你的SQL语句比较长或者逻辑复杂,用Here Document( heredoc)会更清晰,完全避免引号嵌套的头疼问题:
ssh -t remote_server << 'EOF' cd / sudo -u postgres psql -c 'SELECT rolname FROM pg_roles WHERE rolname = '\''username'\'';' EOF
这里的'EOF'表示heredoc的内容不会被bash做变量替换,内部的单引号用'\''来转义(简单理解就是:先闭合外层单引号,插入一个单引号,再重新打开单引号)。你也可以直接在heredoc里用双引号包裹SQL语句,更省事:
ssh -t remote_server << 'EOF' cd / sudo -u postgres psql -c "SELECT rolname FROM pg_roles WHERE rolname = 'username';" EOF
方案4:写成脚本文件(最稳妥,适合频繁执行)
如果这个命令你经常用,不如在远程服务器上创建一个脚本文件,彻底告别引号问题:
- 在远程服务器上创建
check_postgres_user.sh:
#!/bin/bash sudo -u postgres psql -c 'SELECT rolname FROM pg_roles WHERE rolname = '\''username'\'';'
- 给脚本加执行权限:
chmod +x check_postgres_user.sh
- 之后直接通过ssh执行:
ssh -t remote_server "cd /; ./check_postgres_user.sh"
这种方式不仅避免了引号嵌套,还方便后续修改SQL逻辑。
内容的提问来源于stack exchange,提问作者Andre

