展开菜单
首页 精品内容 本月促销 装机必备 Windows macOS软件 IOS软件 Android AI PDF教程 专题
全部分类

当前位置:

首页 > 编程开发 > Python-oracledb 游标与连接管理详解

Python-oracledb 游标与连接管理详解

本文深入探讨python-oracledb中游标对象(cursor)和变量(cursor.var())的工作原理。我们将区分客户端Python对象与服务器端数据库会话资源,解释cursor.var()创建的变量的生命周期,以及它们在数据库连接关闭和重连时的行为。文章还将纠正常见误解,并提供在不同数据库会话间维护数据值的正确方法。

深入理解 python-oracledb 游标变量与数据库连接管理

本文深入探讨 `python-oracledb` 中游标对象(`cursor`)和变量(`cursor.var()`)的工作原理。我们将区分客户端 Python 对象与服务器端数据库会话资源,解释 `cursor.var()` 创建的变量的生命周期,以及它们在数据库连接关闭和重连时的行为。文章还将纠正常见误解,并提供在不同数据库会话间维护数据值的正确方法。

1. python-oracledb 游标与绑定变量概述

在 python-oracledb 模块中,cursor 对象是与数据库进行交互的核心。它允许执行 SQL 语句、调用存储过程和函数。cursor.var() 方法则用于创建绑定变量,这些变量是 Python 程序与 Oracle 数据库之间传递数据的桥梁。

cursor.var() 返回一个 Var 对象,它代表一个客户端 Python 数据结构,用于存储将要发送到数据库或从数据库接收的数据。这些 Var 对象是为 SQL 语句中的绑定参数设计的,能够显著提高性能和安全性,例如防止 SQL 注入。

2. 数据库会话与游标的生命周期

理解 python-oracledb 中变量行为的关键在于区分客户端(Python 应用程序)和服务器端(Oracle 数据库)的概念。

  • 数据库会话(Session):当 oracledb.connect() 建立一个连接时,Oracle 数据库会为该连接创建一个唯一的会话。这个会话是用户与数据库交互的上下文,所有 SQL 语句的执行、游标的打开、事务的管理都发生在这个会话中。
  • 服务器端游标:在数据库服务器上,当执行一个 SQL 语句时,Oracle 可能会为它分配一个服务器端游标。这个服务器端游标的生命周期与创建它的数据库会话紧密相关。
  • 连接关闭的影响:当调用 connection.close() 时,与该连接关联的数据库会话会被终止。这意味着该会话中所有打开的服务器端游标、未提交的事务以及任何会话级别的状态都会被清除。
  • 重新连接:再次调用 oracledb.connect() 会建立一个全新的数据库连接,并创建一个全新的、独立的数据库会话。这个新会话与之前的会话之间没有任何状态共享。

3. cursor.var() 变量的客户端特性

cursor.var() 方法创建的 Var 对象是一个纯粹的 Python 对象,其值存储在 Python 程序的内存空间中。它的生命周期独立于数据库连接的打开或关闭。

  • 客户端存储:当您使用 host_variable = cursor.var(str) 创建一个 Var 对象并调用 host_variable.setvalue(0, 'VALUE') 时,这个值仅仅是存储在 Python 程序的 host_variable 对象中。
  • 数据传输:只有当这个 Var 对象作为绑定变量被传递给 cursor.execute() 方法时,其值才会被实际发送到数据库服务器。同样,如果它被用作输出绑定变量,数据库返回的值也会被存储回这个 Python Var 对象中。
  • 独立于会话:即使数据库连接关闭,host_variable 这个 Python 对象仍然存在于程序的内存中,并保留其最后设置的值。它与任何特定的数据库会话或服务器端游标无关。

4. 实战演示:连接重置对变量的真实影响

为了更清晰地说明这一点,我们来看一个常见的误解和正确的行为演示。

4.1 常见误解:变量值似乎被保留

考虑以下代码片段,它可能导致初学者误认为 cursor.var() 创建的变量值在连接关闭和重开后依然保持:

import oracledb
import connection_config # 假设包含 user, pw, dsn

# 第一次连接和操作
con = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
cursor = con.cursor()

host_variable = cursor.var(str)
host_variable.setvalue(0, 'VALUE_FROM_SESSION_1')
print(f"第一次连接 - host_variable 值: {host_variable.getvalue()}") # 输出: VALUE_FROM_SESSION_1
con.close() # 关闭连接,终止第一个数据库会话

# 第二次连接和操作
con = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
cursor = con.cursor() # 创建新的游标,关联到新的数据库会话

# 此时,host_variable 仍然是第一次连接时创建的那个 Python 对象
print(f"第二次连接后 - host_variable 值: {host_variable.getvalue()}") # 输出: VALUE_FROM_SESSION_1
con.close()

解释: 上述代码中,两次 print(host_variable.getvalue()) 都输出了 VALUE_FROM_SESSION_1。这并非因为值在数据库会话之间得到了保持,而是因为 host_variable 仅仅是一个 Python 对象,它的值在 Python 程序的内存中。当 con.close() 被调用时,数据库连接被关闭,但 host_variable 这个 Python 对象本身并没有被销毁,它仍然存在于 Python 内存中并保留着上次设置的值。第二个 print 语句只是再次读取了这个 Python 对象的当前值,而它与新建立的数据库会话或新游标没有任何关联。

4.2 正确演示:新会话需要新变量

为了证明变量值不会在数据库会话之间自动传递,我们需要为新的连接和游标创建新的 Var 对象:

import oracledb
import connection_config # 假设包含 user, pw, dsn

# 第一个连接和游标
con1 = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
cursor1 = con1.cursor()

host_variable1 = cursor1.var(str)
host_variable1.setvalue(0, 'VALUE_FROM_SESSION_1')
print(f"Session 1 - host_variable1 value: {host_variable1.getvalue()}")
con1.close() # 关闭第一个连接

# 第二个连接和游标
con2 = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
cursor2 = con2.cursor()
host_variable2 = cursor2.var(str) # 为新游标创建新的Var对象

# 打印 host_variable1 的值(仍在Python内存中)
print(f"After con1 closed, host_variable1 value (in Python memory): {host_variable1.getvalue()}")

# 打印 host_variable2 的值(新创建,未设置)
try:
    # 尝试获取新创建但未设置值的Var对象的值,通常会是None或引发错误
    print(f"Session 2 - host_variable2 value (newly created): {host_variable2.getvalue()}")
except oracledb.ProgrammingError as e:
    print(f"Session 2 - host_variable2 value (newly created): Not set, error: {e}")
except Exception as e:
    print(f"Session 2 - host_variable2 value (newly created): Not set, or unexpected error: {e}")

con2.close() # 关闭第二个连接

输出示例:

Session 1 - host_variable1 value: VALUE_FROM_SESSION_1
After con1 closed, host_variable1 value (in Python memory): VALUE_FROM_SESSION_1
Session 2 - host_variable2 value (newly created): Not set, or error: DPY-2005: a value must be set for the variable

这个例子清楚地表明,host_variable2 作为一个新的 Var 对象,在创建时并没有继承 host_variable1 的值。它是一个独立的、未初始化的对象,进一步证实了 cursor.var() 创建的变量是客户端 Python 对象,其值不自动跨数据库会话传递。

5. 跨数据库会话维护数据值的策略

既然 cursor.var() 创建的变量值不会自动跨数据库会话保持,那么如果需要在不同会话之间共享或维护数据,有哪些可行的策略呢?

  1. 客户端 Python 变量: 最直接的方式是将数据存储在 Python 脚本的普通变量中。这些变量在 Python 程序的生命周期内都有效,可以被不同连接和游标使用。

    import oracledb
    import connection_config
    
    # 在Python客户端维护一个值
    client_data = 'DATA_TO_PERSIST'
    
    # 第一次连接
    con1 = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
    cursor1 = con1.cursor()
    # 使用 client_data
    # 例如,将其作为绑定变量传递给SQL
    # cursor1.execute("INSERT INTO my_table (col) VALUES (:1)", [client_data])
    print(f"第一次连接使用客户端数据: {client_data}")
    con1.close()
    
    # 第二次连接
    con2 = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
    cursor2 = con2.cursor()
    # 再次使用 client_data
    print(f"第二次连接使用客户端数据: {client_data}")
    con2.close()

    这种方法适用于需要在客户端应用程序中短暂存储数据,并在不同数据库操作中重用的场景。

  2. Oracle 数据库包变量: 在 Oracle 数据库服务器端,可以利用 PL/SQL 包的全局变量来维护会话级别的状态。包变量可以在同一个会话内的不同存储过程或函数调用中共享。如果需要跨会话,则需要更复杂的机制(如使用 DBMS_SESSION.SET_CONTEXT 或将包变量持久化到表中)。

    -- 示例:创建PL/SQL包
    CREATE PACKAGE my_package AS
        g_session_data VARCHAR2(100);
        PROCEDURE set_data(p_data IN VARCHAR2);
        FUNCTION get_data RETURN VARCHAR2;
    END my_package;
    /
    
    CREATE PACKAGE BODY my_package AS
        PROCEDURE set_data(p_data IN VARCHAR2) IS
        BEGIN
            g_session_data := p_data;
        END set_data;
    
        FUNCTION get_data RETURN VARCHAR2 IS
        BEGIN
            RETURN g_session_data;
        END get_data;
    END my_package;
    /

    在 Python 中使用:

    # ... (连接建立) ...
    cursor = con.cursor()
    # 设置包变量
    cursor.execute("BEGIN my_package.set_data(:1); END;", ['Persistent Value'])
    # 获取包变量
    result = cursor.execute("SELECT my_package.get_data FROM DUAL").fetchone()
    print(f"从包中获取的值: {result[0]}")
    con.close()
    # 注意:这个值只在该会话中有效,新会话需要重新设置

    这种方法将数据存储在服务器端,但其生命周期通常也局限于当前数据库会话。

  3. 数据库表持久化: 最可靠和常用的方法是将数据存储在数据库表中。通过 INSERT、UPDATE 或 DELETE 等 SQL 语句,可以将数据永久地写入数据库,使其在任何时间、任何会话中都可访问。

    import oracledb
    import connection_config
    
    # ... (连接建立) ...
    cursor = con.cursor()
    
    # 将数据插入表中
    data_to_save = 'Important Persistent Data'
    cursor.execute("CREATE TABLE IF NOT EXISTS persistent_data (id NUMBER GENERATED BY DEFAULT AS IDENTITY, value VARCHAR2(255))")
    cursor.execute("INSERT INTO persistent_data (value) VALUES (:1)", [data_to_save])
    con.commit() # 提交事务以确保数据持久化
    
    # 关闭连接
    con.close()
    
    # 重新连接,数据仍然存在
    con_new = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
    cursor_new = con_new.cursor()
    # 从表中读取数据
    result = cursor_new.execute("SELECT value FROM persistent_data WHERE value = :1", [data_to_save]).fetchone()
    print(f"从数据库表中读取的值: {result[0]}")
    con_new.close()

    这种方法提供了最高级别的数据持久性,数据可以跨越应用程序重启、数据库重启甚至长时间间隔。

6. 总结与最佳实践

  • 客户端 vs. 服务器:理解 python-oracledb 的 cursor.var() 创建的是客户端 Python 对象,其值存储在 Python 内存中,与数据库会话无关。只有通过 cursor.execute() 调用,这些值才会在客户端和服务器端之间传输。
  • 会话生命周期:Oracle 数据库会话是短暂的。关闭连接会终止当前会话及其所有服务器端资源。重新连接会创建一个全新的会话。
  • 数据持久化:如果需要在不同的数据库会话之间维护数据,应避免依赖 cursor.var() 对象来“记住”值。相反,应采用以下策略:
    • 将数据存储在客户端 Python 变量中,适用于在应用程序运行时短暂共享数据。
    • 利用 Oracle 数据库包变量,在单个数据库会话内共享数据,但通常不跨会话。
    • 将数据持久化到数据库表中,这是实现数据永久性、跨任何会话共享的最可靠方式。

通过清晰地认识客户端 Python 对象与服务器端数据库会话之间的界限,开发者可以更有效地管理 python-oracledb 中的数据流和连接,从而构建健壮、高效的数据库应用程序。

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
编程开发
相关文章 更多
精品专题 更多
本月促销

正软商城本月促销专区,汇集办公、设计、安全、影音、系统工具及AI软件等正版软件优惠活动,提供限时折扣、特价授权和优惠购买信息,活动库存及价格以页面实时展示为准。

装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

IOS软件

正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

AI

正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
灵活计算器
灵活计算器

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

图几
图几

图几是一款适用于 macOS 的截图、标注与美化工具,支持离线操作保障隐私。界面整理和高频系统操作被放到一起考虑,桌面或窗口内容一多时,管理起来会更省心。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Menuist
Menuist

Menuist 是一款面向 macOS 的 Finder 右键菜单增强工具,主要用来补充新建文件、快捷导航等常用操作,让日常文件管理和访问路径时更高效、更顺手。

Mole
Mole

Mole 是一款专为 Mac 设计的深度清理优化工具,涵盖缓存清理、应用管理及实时状态监控等功能。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

WINDOWS 更多
Windows 10
Windows 10

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

傲梅轻松备份
傲梅轻松备份

傲梅轻松备份是一款专业易用的数据备份软件,为重要数据提供安全保障。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

Wise Folder Hider Pro
Wise Folder Hider Pro

Wise Folder Hider Pro 是一款专业级文件和文件夹隐藏加密软件,为私密数据添加多重保护。高频操作更强调就近处理,浏览、整理和跨目录移动文件时,来回切换和重复点击都会少很多。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

PinStack
PinStack

PinStack是一款轻量级的Windows平台剪贴板管理工具,优化您的剪贴板使用体验。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Seer
Seer

Seer是一款在Win平台下的空格键功能增强效率工具,只需轻敲空格键,就能预览几乎任何格式的文件。它更适合把零散的小功能集中起来使用,处理高频琐碎任务时会更省事。