讲师中心 微信公众号
AI工具推荐 视频效率加速

python-oracledb 游标与绑定变量:连接管理与数据持久化解析

小婷小哥_6903

小婷小哥_6903

发布时间:2025-11-21 12:20:29

|

409人浏览过

|

来源于php中文网

原创

python-oracledb 游标与绑定变量:连接管理与数据持久化解析

本文深入探讨了 `python-oracledb` 中游标对象 (`cursor`) 和绑定变量 (`cursor.var()`) 的工作机制及其生命周期。我们将澄清绑定变量在客户端Python环境与服务端Oracle数据库会话之间的行为差异,特别是数据在连接断开与重连后是否保持的问题。文章还将提供示例代码,并指导如何正确实现数据的持久化策略,以避免常见误解。

1. python-oracledb 游标与绑定变量基础

在使用 python-oracledb 库与 Oracle 数据库交互时,cursor 对象是执行 SQL 语句和管理查询结果的核心。通过 connection.cursor() 方法可以创建一个游标对象。

cursor.var() 方法用于创建绑定变量。这些绑定变量是 Python 客户端应用程序中的数据结构,其主要目的是将 Python 值作为绑定参数传递给 Oracle 数据库的 SQL 语句或 PL/SQL 块。例如,host_variable = cursor.var(str) 创建了一个可用于存储字符串的绑定变量。通过 host_variable.setvalue(0, 'VALUE') 可以为其赋值,并通过 host_variable.getvalue() 获取其当前值。

需要强调的是,cursor.var() 创建的变量首先是一个客户端 Python 对象。它在 Python 应用程序的内存中存在,独立于数据库会话。只有当这个绑定变量被用于执行 SQL 语句(例如 cursor.execute("INSERT INTO my_table VALUES (:my_var)", my_var=host_variable))时,其值才会被发送到数据库服务器。

立即学习“Python免费学习笔记(深入)”;

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

理解 python-oracledb 中连接和游标的行为,关键在于区分客户端 Python 对象与服务端 Oracle 数据库资源的生命周期。

  • Oracle 数据库会话(Session):当通过 oracledb.connect() 成功建立一个数据库连接时,Oracle 数据库会为该连接创建一个唯一的会话。这个会话是用户与数据库交互的上下文,所有在该连接上执行的操作(包括创建游标、执行SQL、管理事务等)都属于这个会话。
  • Oracle 数据库游标(Cursor):在数据库层面,游标是与特定会话关联的、用于处理 SQL 语句结果集的内存区域。它的生命周期与所属的数据库会话紧密相关。
  • 连接的关闭与重开:当调用 connection.close() 时,不仅会关闭客户端的连接对象,还会通知 Oracle 数据库终止对应的会话。这意味着该会话下所有相关的数据库资源,包括所有数据库游标和任何会话级的数据(如临时表、PL/SQL 包变量等),都会被释放。
  • 新连接,新会话:随后再次调用 oracledb.connect() 会建立一个全新的数据库连接,并导致 Oracle 数据库创建一个全新的、独立的会话。这个新会话与之前的会话没有任何关联,它拥有自己独立的资源集。

因此,从数据库的角度看,当一个连接关闭并重新打开时,所有与前一个会话相关的数据库端数据和游标都已失效。

3. 解析测试代码中的“假象”

初学者可能会遇到一个常见的误解,即认为通过 cursor.var() 创建的变量在连接关闭并重新打开后仍然保持其值。以下面的示例代码为例:

import oracledb
import connection_config # 假设包含用户、密码、DSN配置

# 第一次连接
con = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
cursor = con.cursor()   # 第一个连接的游标

host_variable = cursor.var(str) # 创建一个Python绑定变量对象
host_variable.setvalue(0, 'VALUE') # 设置其值

print(f"第一次连接后,host_variable的值: {host_variable.getvalue()}") # 输出 'VALUE'

con.close() # 关闭第一个连接,终止会话

# 第二次连接
con = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
cursor = con.cursor()   # 第二个连接的游标 (新会话)

print(f"第二次连接后,host_variable的值: {host_variable.getvalue()}") # 仍然输出 'VALUE'

这段代码看似表明 host_variable 的值在连接关闭和重新打开后依然存在。然而,这是一种误解。实际情况是:

  1. host_variable = cursor.var(str) 创建的是一个Python 对象,它存在于 Python 应用程序的内存中。
  2. host_variable.setvalue(0, 'VALUE') 只是修改了这个 Python 对象内部存储的值。
  3. 这个值从未被发送到数据库。在上述代码中,没有执行任何 SQL 语句来利用 host_variable 将数据传递给数据库。
  4. 当 con.close() 被调用时,第一个数据库连接和会话被终止,但 host_variable 这个 Python 对象本身仍然存在于 Python 程序的内存中,其内部存储的值并未改变。
  5. 在第二次连接后,当再次调用 host_variable.getvalue() 时,它只是返回了 Python 对象自身在内存中保留的值,而与新建立的数据库连接或游标没有任何关系。

4. 正确理解变量行为的示例

为了更清楚地说明这一点,我们可以修改代码,创建两个独立的 host_variable 对象,分别与两个不同的连接/游标关联:

import oracledb
import connection_config # 假设包含用户、密码、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_ONE')

print(f"host_variable1 的值: {host_variable1.getvalue()}") # 输出 'VALUE_ONE'

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) # 创建一个新的绑定变量对象,与 cursor2 关联

# 尝试获取 host_variable2 的值
# 如果未设置,它将返回默认值(例如 None 或空字符串,取决于类型和驱动行为)
print(f"host_variable2 的值 (未设置): {host_variable2.getvalue()}") # 输出 None 或空字符串

运行这段代码,你会发现 host_variable2.getvalue() 不会输出 VALUE_ONE。这证明了 host_variable1 和 host_variable2 是独立的 Python 对象,并且数据库会话之间的状态不会自动传递。

核心结论: cursor.var() 创建的 Python 绑定变量对象,其生命周期独立于数据库连接的关闭和重新打开。但它所代表的数据库端绑定参数的生命周期是严格绑定到其所属的数据库会话的。当会话终止时,数据库端的一切都随之消失。

Seasonal Keyword Planner
Seasonal Keyword Planner

将电商关键词映射到12个月需求曲线,生成逐月的listing、广告和内容发布时间表。

下载

5. 数据持久化的策略

如果你的目标是让某个值在数据库连接重置后仍然可用,并且能在新的连接中用于查询,那么仅仅依赖 cursor.var() 是不够的,因为 cursor.var() 只是一个客户端的数据容器。你需要采取明确的持久化策略:

5.1 客户端 Python 变量

最简单的方法是将需要持久化的数据存储在普通的 Python 变量中。当数据库连接关闭并重新打开时,你可以将这些 Python 变量的值重新赋给新的 cursor.var() 对象,然后再将其用于数据库操作。

import oracledb
import connection_config

# 存储需要持久化的值
persistent_data = 'MY_PERSISTENT_VALUE'

# 第一次连接
con1 = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
cursor1 = con1.cursor()
bind_var1 = cursor1.var(str)
bind_var1.setvalue(0, persistent_data)
# 可以在此执行使用 bind_var1 的 SQL 语句
print(f"第一次连接中,使用持久化数据: {bind_var1.getvalue()}")
con1.close()

# 第二次连接
con2 = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
cursor2 = con2.cursor()
bind_var2 = cursor2.var(str)
bind_var2.setvalue(0, persistent_data) # 将持久化数据重新赋给新的绑定变量
print(f"第二次连接中,重新使用持久化数据: {bind_var2.getvalue()}")
con2.close()

这种方法适用于数据量不大,且仅需在当前 Python 应用程序实例中保持的场景。

5.2 Oracle 数据库包变量

如果需要在数据库会话之间(但不是永久地)共享数据,或者希望数据在 PL/SQL 逻辑中可用,可以考虑使用 Oracle 数据库中的包变量。包变量在会话级别持久化,这意味着只要会话不结束,包变量的值就会保持。

示例(PL/SQL 包定义):

CREATE PACKAGE my_data_pkg AS
  g_session_value VARCHAR2(100);
  PROCEDURE set_value(p_value IN VARCHAR2);
  FUNCTION get_value RETURN VARCHAR2;
END my_data_pkg;
/

CREATE PACKAGE BODY my_data_pkg AS
  PROCEDURE set_value(p_value IN VARCHAR2) IS
  BEGIN
    g_session_value := p_value;
  END set_value;

  FUNCTION get_value RETURN VARCHAR2 IS
  BEGIN
    RETURN g_session_value;
  END get_value;
END my_data_pkg;
/

Python 代码:

import oracledb
import connection_config

con = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
cursor = con.cursor()

# 设置包变量的值
cursor.execute("BEGIN my_data_pkg.set_value(:val); END;", val='SESSION_DATA')
con.commit()

# 获取包变量的值
cursor.execute("SELECT my_data_pkg.get_value FROM DUAL")
result = cursor.fetchone()
print(f"第一次获取包变量值: {result[0]}") # 输出 'SESSION_DATA'

# 此时如果关闭并重新打开连接,会创建一个新会话,新会话的包变量值将是初始值 (NULL)
# 但如果只是在同一个连接中执行其他操作,包变量值会保持。
# 演示:在同一个连接中再次获取
cursor.execute("SELECT my_data_pkg.get_value FROM DUAL")
result = cursor.fetchone()
print(f"同连接中再次获取包变量值: {result[0]}") # 仍输出 'SESSION_DATA'

con.close()

请注意,如果关闭连接并重新打开,由于会话的改变,新的会话将无法访问到旧会话设置的包变量值。

5.3 数据库表

最可靠和最通用的数据持久化方法是将数据存储在 Oracle 数据库的表中。数据一旦插入表中,除非被显式删除或修改,否则它将永久存在,并且可以被任何连接、任何会话访问。

import oracledb
import connection_config

# 确保表存在
# cursor.execute("CREATE TABLE my_persistent_data (id NUMBER, value VARCHAR2(100))")
# cursor.execute("INSERT INTO my_persistent_data (id, value) VALUES (1, 'INITIAL_DATA')")
# con.commit()

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

# 插入或更新数据
cursor1.execute("MERGE INTO my_persistent_data a USING (SELECT 1 id, :new_value value FROM DUAL) b ON (a.id = b.id) WHEN MATCHED THEN UPDATE SET a.value = b.value WHEN NOT MATCHED THEN INSERT (a.id, a.value) VALUES (b.id, b.value)", new_value='UPDATED_DATA_FROM_CON1')
con1.commit()
con1.close()

# 第二次连接
con2 = oracledb.connect(user=connection_config.user, password=connection_config.pw, dsn=connection_config.dsn)
cursor2 = con2.cursor()

# 从表中读取数据
cursor2.execute("SELECT value FROM my_persistent_data WHERE id = 1")
result = cursor2.fetchone()
print(f"从数据库表中获取持久化数据: {result[0]}") # 输出 'UPDATED_DATA_FROM_CON1'

con2.close()

将数据存储在表中是跨连接、跨会话甚至跨应用程序实例持久化数据的标准方法。

总结

python-oracledb 中的 cursor.var() 创建的是客户端 Python 对象,用于将数据传递给数据库的绑定参数。数据库游标和会话的生命周期与数据库连接紧密相关:关闭连接会终止会话并释放所有会话级资源。因此,绑定变量的值不会在数据库连接关闭并重新打开后自动在数据库端“持久化”。

若需在连接重置后维护数据状态,应采用以下策略:

  1. 客户端 Python 变量:在 Python 应用程序内存中存储数据,并在新连接上重新绑定。
  2. Oracle 数据库包变量:利用 Oracle 包变量在单个数据库会话内持久化数据,但不会跨会话。
  3. 数据库表:将数据存储在数据库表中,实现最可靠和永久的持久化。

理解客户端与服务端生命周期的区别是高效、正确使用 python-oracledb 进行数据库编程的关键。

相关文章

python速学教程(入门到精通)
python速学教程(入门到精通)

python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

4643

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

951

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

1229

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

6641

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

3383

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

6620

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

9101

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

1230

2024.04.29

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

60

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn