cx_Oracle.DatabaseError:DPI-1039:语句已关闭

时间:2019-06-04 11:47:43

标签: python python-2.7 cx-oracle

已升级到最新的Cx_Oracle版本(5.1.3至7.1.3),现在我的所有代码都已损坏。尝试传递游标时似乎出现了问题。

def select_query_remy(self,sql,params=None):
    with cx_Oracle.connect(self.connection) as con:
        cur = con.cursor()
        if params:
            cur.execute(sql,params)
        else:
            cur.execute(sql)
        #print cur.fetchall()
        return cur

我在fetchall中获取了正确的数据,所以我知道它正在正确连接并返回有效结果。所以我将其注释掉。

在其他脚本中,我称它为行,现在应该正确存储游标了吗?

rows = con.select_query_remy(sql)

当我从其他脚本中fetchall()进入下面并得到错误消息。

print rows.fetchall()
     

cx_Oracle.DatabaseError:DPI-1039:语句已关闭

有什么想法吗?

完整的db.py

import cx_Oracle

class db:

list ={}    

def __init__(self):
    '''
        AMFM Python DB connectors
   '''
    db.list["disprod"] = [999,"disprod.prod.com"]
    db.list["prodqry"] = [999,"prodqry.prod.com"]
    db.list["amfmprod"] = [999,"amfmprod.prod.com"]
    db.list["esriprod"] = [999,"esriprod.prod.com"]
    db.list["amfmtest"] = [999,"amfmtest.prod.com"]
    db.list["amfmdev"] = [999,"CCTdAMFM.prod.com"]
    db.list["amfmtran"] = [999,"amfmtran.prod.com"]


def setup(self,env, username, password):
    self.username = username
    self.password = password
    self.env = env

    self.port = db.list[env][0]
    self.ip = db.list[env][1]
    if env == "prodqry":
        self.env = "prodqry.world"
    elif env == "amfmprod":
        self.env = "amfmprod.world"
    elif env == "esriprod":
        self.env = "esriprod.world"
    else:
        self.env = env
    self.connection = self.username+"/"+self.password+"@"+self.ip+":"+str(self.port)+"/"+self.env

def select_query_remy(self,sql,params=None):
    with cx_Oracle.connect(self.connection) as con:
        cur = None
        cur = con.cursor()
        if params:
            cur.execute(sql,params)
        else:
            cur.execute(sql)
        return cur

在另一个python中,我创建了一个新的数据库,并尝试使光标返回。

con = db()
con.setup("xxx","user","password")
rows = con.select_query_remy(sql)
print rows.fetchall()

结果:

Traceback (most recent call last):
  File "C:\Python27\ArcGIS10.5\test\test.py", line 30, in <module>
    print rows.fetchall()
cx_Oracle.DatabaseError: DPI-1039: statement was already closed

如果我返回fetchall(),则会看到数据。当我通过游标本身时,就会发生错误。

def select_query_remy(self,sql,params=None):
        with cx_Oracle.connect(self.connection) as con:
            cur = None
            cur = con.cursor()
            if params:
                cur.execute(sql,params)
            else:
                cur.execute(sql)
            #return cur
            return cur.fetchall()

有什么主意为什么不能像过去那样传递光标?

2 个答案:

答案 0 :(得分:1)

我在查询 Oracle 数据库时遇到了此错误消息。我相信如果数据库中有 LOB(大对象)就会发生这种情况,但在我查询的所有 Oracle 数据库中并非如此。

由于我使用 Jupyter 进行原型设计,所以我更喜欢使用上下文管理器 (with) 语句,如果我必须在单独的单元格中添加 .close() 语句,这会使操作查询结果变得更加困难。

我对此的解决方法实际上是使用内置的 deepcopy 函数(我尝试使用 .copy() 但这也不起作用。对数据的任何进一步操作/显示都会产生相同的错误。

>

所以我给你的解决方案如下:

from copy import deepcopy
import cx_Oracle

def select_query_remy(self,sql,params=None):
    with cx_Oracle.connect(self.connection) as con:
        cur = con.cursor()
        if params:
            cur.execute(sql,params)
        else:
            cur.execute(sql)
        #print cur.fetchall()
        return deepcopy(cur.fetchall())

我相信这应该可以解决您的问题,如果它与我遇到的问题相同。

答案 1 :(得分:0)

您的错误与with-block(也称为上下文管理器)有关。让我在select_query_remy函数中添加一些注释:

def select_query_remy(self,sql,params=None):
    with cx_Oracle.connect(self.connection) as con:  # connects to database
        cur = None
        cur = con.cursor()
        if params:
            cur.execute(sql,params)
        else:
            cur.execute(sql)
        return cur                                # closes connection (invalidates cursor too!)    

由于with块管理数据库连接的上下文,因此在退出该块后将关闭连接。

为解决该错误,我建议直接在函数内部执行fetchall ,然后在函数外部使用该数据。 (您已经知道了这一点。)

进一步阅读:The Python Language Reference: The with statement