如何通过cx_oracle执行SQL脚本文件?
有没有办法用Python里的cx_oracle来执行一个sql脚本文件呢?
我需要执行我在sql文件里写的创建表的脚本。
3 个回答
在cx_Oracle库中,你可以找到一个测试用来加载脚本的方法:run_sql_script
我在我的项目中对这个方法做了如下修改:
def run_sql_script(self, connection, script_path):
cursor = connection.cursor()
statement_parts = []
for line in open(script_path):
if line.strip() == "/":
statement = "".join(statement_parts).strip()
if not statement.upper().startswith('CREATE PACKAGE'):
statement = statement[:-1]
if statement:
try:
cursor.execute(statement)
except Exception as e:
print("Failed to execute SQL:", statement)
print("Error:", str(e))
statement_parts = []
else:
statement_parts.append(line)
脚本文件中的命令必须用“/”来分隔。希望这对你有帮助。
另一种选择是使用 SQL*Plus(Oracle 的命令行工具)来运行脚本。你可以通过 Python 的 subprocess
模块来调用它——这里有一个不错的教程:http://moizmuhammad.wordpress.com/2012/01/31/run-oracle-commands-from-python-via-sql-plus/。
对于像 tables.sql
这样的脚本(注意这里故意有个错误):
CREATE TABLE foo ( x INT );
CREATE TABLER bar ( y INT );
你可以使用下面这样的函数:
from subprocess import Popen, PIPE
def run_sql_script(connstr, filename):
sqlplus = Popen(['sqlplus','-S', connstr], stdin=PIPE, stdout=PIPE, stderr=PIPE)
sqlplus.stdin.write('@'+filename)
return sqlplus.communicate()
connstr
是和 cx_Oracle
一样的连接字符串。filename
是脚本的完整路径(例如 'C:\temp\tables.sql'
)。这个函数会打开一个 SQLPlus 会话(用 '-S' 来关闭欢迎信息),然后排队发送 "@filename" 给它——这会告诉 SQLPlus 运行这个脚本。
sqlplus.communicate
会把命令发送到标准输入,等待 SQL*Plus 会话结束,然后返回(标准输出,错误输出)作为一个元组。调用这个函数并传入上面的 tables.sql
将会得到以下输出:
>>> output, error = run_sql_script(connstr, r'C:\temp\tables.sql')
>>> print output
Table created.
CREATE TABLER bar (
*
ERROR at line 1:
ORA-00901: invalid CREATE command
>>> print error
这需要稍微处理一下,具体取决于你想要返回给程序的内容——如果是交互式的,你可以把整个输出显示给用户,或者如果你只是想检查是否运行成功,可以扫描一下是否有 "ERROR" 这个词。
PEP-249 是 cx_oracle 试图遵循的一个标准,但这个标准里并没有类似的方法。
不过,整个过程应该很简单。你可以把文件的内容读进一个字符串里,然后用“;”这个字符来分割它,接着对分割出来的每一部分调用 .execute 方法。我假设“;”这个字符只是用来分隔文件中的 Oracle SQL 语句。
f = open('tabledefinition.sql')
full_sql = f.read()
sql_commands = full_sql.split(';')
for sql_command in sql_commands:
curs.execute(sql_command)