在python中使用cx_Oracle使用PL/SQL和DML/DDL解析SQL文件
我有一个SQL文件,我想使用在python中使用cx_Oracle使用PL/SQL和DML/DDL解析SQL文件,python,oracle,cx-oracle,Python,Oracle,Cx Oracle,我有一个SQL文件,我想使用cx\u oraclepython库在oracle中解析和执行它。SQL文件包含经典的DML/DDL和PL/SQL,例如,它可以如下所示: create.sql: -- This is some ; malicious comment CREATE TABLE FOO(id numeric); BEGIN INSERT INTO FOO VALUES(1); INSERT INTO FOO VALUES(2); INSERT INTO FOO VALUE
cx\u oracle
python库在oracle中解析和执行它。SQL文件包含经典的DML/DDL和PL/SQL,例如,它可以如下所示:
create.sql
:
-- This is some ; malicious comment
CREATE TABLE FOO(id numeric);
BEGIN
INSERT INTO FOO VALUES(1);
INSERT INTO FOO VALUES(2);
INSERT INTO FOO VALUES(3);
END;
/
CREATE TABLE BAR(id numeric);
如果我在SQLDeveloper或SQL*Plus中使用此文件,它将被拆分为3个查询并执行
但是,cx_Oracle.connect(…).cursor().execute(…)一次只能执行一个查询,而不能执行整个文件。我不能简单地使用string.split(“;”)
(如本文所建议的)拆分字符串,因为注释将被拆分(并将导致错误),而PL/SQL块将不会作为单个命令执行,从而导致错误
在Oracle论坛()上,我发现cx_Oracle本身不支持解析整个文件。我的问题是,有没有一个工具可以帮我做到这一点?我可以调用python库将我的文件拆分为查询
编辑:最好的解决方案似乎直接使用SQL*Plus。我使用了以下代码:
#打开文件
f=打开(文件路径“r”)
data=f.read()
f、 关闭()
#在末尾添加EXIT,以便SQL*Plus结束(没有--no interactive:(
data=“%s\n\nEXIT”%data
#将结果写入临时文件(必需,SQL*Plus采用文件名参数)
f=打开('tmp.file','w')
f、 写入(数据)
f、 关闭()
#执行SQL*Plus
output=子进程。检查\u输出(['sqlplus','%s/%s@%s'(db\u用户,db\u密码,db\u地址),'@','tmp.file'])
#如果在结果中发现错误,则引发异常
如果输出.find('ERROR at line')!=-1:
引发异常(“%s\n\n堆栈:%s%”(在SQLPlus结果中发现错误,输出))
可以同时执行多条语句,但这是一种半黑客操作。您需要包装语句,然后一次执行一条语句
导入cx\u Oracle
>>>
>>>a=cx\U Oracle.connect('架构/pw@db')
>>>curs=a.cursor()
>>>SQL=(“创建表tmp_测试(a日期)”),
…(“插入tmp_测试值(系统日期)”)
... )
>>>对于SQL中的i:
…打印i
...
创建tmp_测试表(日期)
插入tmp_测试值(sysdate)
>>>对于SQL中的i:
…游标执行(i)
...
>>>a.提交()
>>>
正如您所指出的,这并不能解决分号问题,因为分号问题没有简单的答案。在我看来,您有3个选项:
subprocess
并以这种方式调用脚本。这是最简单、最快速的选项,但根本不使用cx\u Oracle
>>> import subprocess
>>> cmdline = ['sqlplus','schema/pw@db','@','tmp_test.sql']
>>> subprocess.call(cmdline)
SQL*Plus: Release 9.2.0.1.0 - Production on Fri Apr 13 09:40:41 2012
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to:
Oracle Database 11g Release 11.2.0.1.0 - 64bit Production
SQL>
SQL> CREATE TABLE FOO(id number);
Table created.
SQL>
SQL> BEGIN
2 INSERT INTO FOO VALUES(1);
3 INSERT INTO FOO VALUES(2);
4 INSERT INTO FOO VALUES(3);
5 END;
6 /
PL/SQL procedure successfully completed.
SQL> CREATE TABLE BAR(id number);
Table created.
SQL>
SQL> quit
Disconnected from Oracle Database 11g Release 11.2.0.1.0 - 64bit Production
0
>>>
您好,subprocess.call似乎是一个合理的解决方案(我不能使用第二个选项,因为我无法控制SQL文件)。但是,当我作为subprocess运行sqlplus时,它将等待“QUIT”命令。我的Python脚本需要非交互式(将以这种方式执行多个SQL文件)。您将如何更改它,使其不会等待stdin?@Savannah,您不能将quit添加到SQL脚本中吗?生成它们的人应该确保它们退出。我添加了类似data=“%s\n\nEXIT”的内容%data添加到我运行的脚本中,它现在可以工作了。使用subprocess.Popen而不是call将允许您从Python结束会话,而无需将exit命令添加到SQL脚本中-请参见这里的相同问题。基本上,Oracle是死板的,实际上没有任何内置的解析多语句SQL脚本的能力,因此SQLPlus和SQL Developer和TOAD都实现了自己的解析器:-(