如何通过cx_oracle执行SQL脚本文件?

14 投票
3 回答
28994 浏览
提问于 2025-04-17 02:57

有没有办法用Python里的cx_oracle来执行一个sql脚本文件呢?

我需要执行我在sql文件里写的创建表的脚本。

3 个回答

1

在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)

脚本文件中的命令必须用“/”来分隔。希望这对你有帮助。

13

另一种选择是使用 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" 这个词。

13

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)

撰写回答