Python通过SSH执行Oracle SQLplus语句时如何免转义处理
无需手动转义SQL,通过Python SSH调用Oracle SQLPlus的替代方案
以下是两种无需手动转义SQL字符串,也不需要创建独立SQL脚本的解决办法:
方法1:使用Bash Here Document传递SQL
利用Bash的Here Document( heredoc)语法,将SQL原样传递给远程的sqlplus,避免shell解析特殊字符(如$、')。关键是给heredoc的边界符加上单引号,让shell完全不解析内部内容。
修改后的代码:
import subprocess sql = """ SET TIME OFF SET TIMING OFF SET HEADING OFF SET LINESIZE 1000 SET PAGESIZE 0 SET TRIMSPOOL ON SET FEEDBACK OFF select name || '__a' from v$database; """ export_cmd = "export ORACLE_HOME=/u01/oracle/19/srv; export ORACLE_SID=db01; export LD_LIBRARY_PATH=${ORACLE_HOME}/lib" # 使用带单引号的EOF作为heredoc边界,避免shell解析SQL中的特殊字符 ssh_command = f"""{export_cmd}; $ORACLE_HOME/bin/sqlplus -S / as sysdba <<'EOF' {sql} EOF""" host = "host1" process = subprocess.Popen(["ssh", f"oracle@{host}", ssh_command], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() print("Output:\n", stdout.decode()) print("Error:\n", stderr.decode())
方法2:通过Subprocess stdin直接传递SQL
将SQL通过Python subprocess的stdin管道直接发送给远程的sqlplus进程,完全绕开shell的字符串拼接与解析,这是最安全的方式,彻底避免转义需求。
修改后的代码:
import subprocess sql = """ SET TIME OFF SET TIMING OFF SET HEADING OFF SET LINESIZE 1000 SET PAGESIZE 0 SET TRIMSPOOL ON SET FEEDBACK OFF select name || '__a' from v$database; """ export_cmd = "export ORACLE_HOME=/u01/oracle/19/srv; export ORACLE_SID=db01; export LD_LIBRARY_PATH=${ORACLE_HOME}/lib" ssh_command = f"""{export_cmd}; $ORACLE_HOME/bin/sqlplus -S / as sysdba""" host = "host1" # 开启stdin管道,用于传递SQL process = subprocess.Popen( ["ssh", f"oracle@{host}", ssh_command], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE ) # 将SQL编码后通过stdin发送给远程进程 stdout, stderr = process.communicate(input=sql.encode()) print("Output:\n", stdout.decode()) print("Error:\n", stderr.decode())
说明
- 方法1通过Bash语法避免转义,适合需要在远程shell命令中直接嵌入SQL的场景;
- 方法2通过管道传递输入,完全隔离SQL与shell解析,是更推荐的方案,尤其适合包含大量特殊字符或动态生成的SQL。
内容的提问来源于stack exchange,提问作者Prokhozhii
相关产品推荐
相关产品推荐

