杰瑞科技汇

Python如何连接SQL Plus?

我们通常不会用 Python 来直接调用 sqlplus.exe 这个命令行工具,虽然技术上可行(例如通过 subprocess 模块),但这是一种笨拙且不推荐的方法,因为它会启动一个新的、重量级的进程,难以处理复杂的交互,并且难以获取结构化的数据。

Python如何连接SQL Plus?-图1
(图片来源网络,侵删)

正确的、现代且推荐的方法是使用 Python 的数据库 API,特别是 cx_Oracle 库。 cx_Oracle 是一个官方支持的 Python 扩展模块,它允许 Python 程序无缝地访问 Oracle 数据库,其底层原理与 SQL*Plus 连接数据库的方式完全一致,都是通过 Oracle 的客户端库(如 Instant Client)。

这篇“Python SQLPlus 博客”的核心内容,实际上是 “使用 Python (cx_Oracle) 连接并操作 Oracle 数据库”


博客文章:Python 与 Oracle 数据库的优雅邂逅:告别 SQL*Plus,拥抱自动化

作为一名开发者或数据分析师,你是否曾有过这样的烦恼:

  • 每天都需要手动登录 SQL*Plus,执行固定的 SQL 查询,并将结果复制粘贴到 Excel 或报告中。
  • 需要根据某些业务逻辑,动态生成并执行一系列 SQL 语句,手动操作效率低下且容易出错。
  • 想将数据库操作集成到你的 Python 自动化流程(如 ETL、监控脚本)中,但 SQL*Plus 显得力不从心。

好消息是,Python 可以完美地解决这些问题,我们将告别传统的 SQL*Plus 命令行工具,学习如何使用 Python 强大的 cx_Oracle 库,与 Oracle 数据库进行优雅、高效的交互,开启数据库自动化的新篇章。

Python如何连接SQL Plus?-图2
(图片来源网络,侵删)

第一步:准备工作——安装与配置

在开始编码之前,我们需要确保环境已经准备就绪。

安装 Oracle 客户端

Python 的 cx_Oracle 库需要 Oracle 客户端库来与数据库通信,最简单的方式是使用 Oracle Instant Client。

  • 下载:访问 Oracle Instant Client 官方下载页面
  • 选择版本:根据你的操作系统(Windows, Linux, macOS)和 Oracle 数据库版本选择合适的 Instant Client 包。basicbasic-light 包就足够了。
  • 配置
    • Windows:解压下载的 zip 文件到一个固定目录(如 C:\oracle\instantclient_19_10),将该目录添加到系统的 PATH 环境变量中。
    • Linux/macOS:解压到某个目录(如 /opt/oracle/instantclient_19_10),并确保该目录在系统的 LD_LIBRARY_PATH (Linux) 或 DYLD_LIBRARY_PATH (macOS) 环境变量中。

安装 Python 的 cx_Oracle

Python如何连接SQL Plus?-图3
(图片来源网络,侵删)

打开你的终端或命令提示符,使用 pip 进行安装:

pip install cx_Oracle

环境已经配置好了,让我们开始编写 Python 代码!


第二步:建立数据库连接

所有操作的第一步都是连接到数据库。cx_Oracle 提供了非常简洁的 API。

import cx_Oracle
# --- 配置信息 ---
# 建议从环境变量或配置文件中读取,而不是硬编码
db_user = "your_username"
db_password = "your_password"
db_dsn = "hostname:port/service_name"  # "localhost:1521/XE"
try:
    # 1. 创建连接
    # 注意:如果你的 Instant Client 不在系统 PATH 中,需要指定其路径
    # cx_Oracle.init_oracle_client(lib_dir="C:/oracle/instantclient_19_10")
    connection = cx_Oracle.connect(user=db_user, password=db_password, dsn=db_dsn)
    # 2. 创建游标
    # 游标用于执行 SQL 语句并获取结果
    cursor = connection.cursor()
    print("成功连接到 Oracle 数据库!")
    # ... 在这里执行你的数据库操作 ...
except cx_Oracle.DatabaseError as e:
    error, = e.args
    print(f"数据库错误代码: {error.code}")
    print(f"数据库错误消息: {error.message}")
finally:
    # 3. 关闭游标和连接
    if 'cursor' in locals() and cursor:
        cursor.close()
    if 'connection' in locals() and connection:
        connection.close()
    print("数据库连接已关闭。")

代码解释

  • cx_Oracle.connect(): 使用用户名、密码和数据源名称 建立连接。
  • connection.cursor(): 创建一个游标对象,它是执行 SQL 的主力。
  • try...except...finally: 这是处理数据库连接的最佳实践。try 块执行操作,except 捕获数据库错误,finally 确保在任何情况下(无论成功或失败)都会关闭游标和连接,释放资源。

第三步:执行查询与获取数据

连接建立后,我们就可以执行 SQL 查询并处理结果了。

示例1:查询并打印结果

import cx_Oracle
# (使用上面的连接代码...)
try:
    # --- 执行查询 ---
    sql_query = "SELECT employee_id, first_name, last_name, salary FROM employees WHERE department_id = 10"
    cursor.execute(sql_query)
    # --- 获取结果 ---
    # cursor.fetchone(): 获取下一行结果,返回一个元组,当没有更多数据时返回 None。
    # cursor.fetchall(): 获取所有剩余的行,返回一个列表,其中每个元素是一个元组。
    # cursor.fetchmany(size): 获取指定数量的行。
    print("\n--- 部门ID为10的员工信息 ---")
    # 使用 fetchone 循环处理,适合处理大量数据,节省内存
    while True:
        row = cursor.fetchone()
        if not row:
            break
        print(f"员工ID: {row[0]}, 姓名: {row[1]} {row[2]}, 薪资: {row[3]}")
    # 或者使用 fetchall
    # rows = cursor.fetchall()
    # for row in rows:
    #     print(f"员工ID: {row[0]}, 姓名: {row[1]} {row[2]}, 薪资: {row[3]}")
except cx_Oracle.DatabaseError as e:
    # 错误处理...
    pass
finally:
    # 关闭连接...
    pass

示例2:将查询结果转换为列表的字典(更 Pythonic 的方式)

直接使用元组访问列 (row[0]) 可读性不强,我们可以通过 cursor.description 获取列名,并将结果处理成字典列表,这在处理复杂数据时非常有用。

import cx_Oracle
# (使用上面的连接代码...)
try:
    sql_query = "SELECT employee_id, first_name, last_name, salary FROM employees WHERE ROWNUM <= 5"
    cursor.execute(sql_query)
    # 获取列名
    columns = [desc[0] for desc in cursor.description]
    # 将每一行数据转换为字典
    employees = []
    for row in cursor:
        employees.append(dict(zip(columns, row)))
    print("\n--- 员工信息(字典格式)---")
    for emp in employees:
        print(emp)
except cx_Oracle.DatabaseError as e:
    # 错误处理...
    pass
finally:
    # 关闭连接...
    pass

第四步:执行 DML 语句(增删改)

对于 INSERT, UPDATE, DELETE 等数据操作语句,我们需要使用参数化查询来防止 SQL 注入,并确保数据安全。

示例:插入数据

import cx_Oracle
# (使用上面的连接代码...)
try:
    # 注意:必须在连接上设置自动提交为 False,以便在出错时回滚
    connection.autocommit = False 
    sql_insert = "INSERT INTO employees (employee_id, first_name, last_name, email, hire_date, job_id) VALUES (:1, :2, :3, :4, SYSDATE, 'IT_PROG')"
    new_employee = (999, 'Python', 'Tester', 'python.tester@example.com')
    cursor.execute(sql_insert, new_employee)
    # 提交事务
    connection.commit()
    print(f"成功插入 {cursor.rowcount} 行数据。")
except cx_Oracle.DatabaseError as e:
    # 发生错误时回滚事务
    connection.rollback()
    print("发生错误,事务已回滚。")
    # 错误处理...
    pass
finally:
    # 关闭连接...
    pass

代码解释

  • connection.autocommit = False: Oracle 默认不自动提交,这给了我们手动控制事务的机会。
  • cursor.execute(sql, params): 使用 1, 2 等作为占位符,然后将参数作为元组或列表传递给 execute 方法。cx_Oracle 会安全地处理这些参数,防止 SQL 注入。
  • connection.commit(): 提交事务,使更改永久生效。
  • connection.rollback(): 回滚事务,撤销所有未提交的更改。

第五步:调用存储过程

Python 调用 Oracle 存储过程同样非常方便。

示例:调用一个带输入输出参数的存储过程

假设我们有一个存储过程 GET_EMP_SALARY,接收员工 ID,返回其薪资。

import cx_Oracle
# (使用上面的连接代码...)
try:
    sql_proc = "{call GET_EMP_SALARY(:emp_id, :sal_out)}"
    emp_id_to_find = 101
    salary_var = cursor.var(cx_Oracle.NUMBER) # 定义一个变量来接收输出参数
    cursor.callproc('GET_EMP_SALARY', [emp_id_to_find, salary_var])
    # 获取输出参数的值
    # 注意:输出参数的值在调用后存储在变量中
    actual_salary = salary_var.getvalue()
    print(f"\n员工ID {emp_id_to_find} 的薪资是: {actual_salary}")
except cx_Oracle.DatabaseError as e:
    # 错误处理...
    pass
finally:
    # 关闭连接...
    pass

总结与最佳实践

通过以上步骤,你已经掌握了使用 Python 操作 Oracle 数据库的核心技能,让我们总结一下关键点和最佳实践:

  1. 首选 cx_Oracle:不要尝试用 subprocess 调用 sqlpluscx_Oracle 是更专业、更高效的选择。
  2. 环境配置是关键:确保 Oracle Instant Client 已正确安装并配置到系统路径中。
  3. 资源管理:始终使用 try...finally 块来确保 cursorconnection 被正确关闭。
  4. 事务控制:对于 DML 操作,明确设置 autocommit = False,并在适当的时候调用 commit()rollback()
  5. 防止 SQL 注入:永远不要用字符串拼接的方式构建 SQL 语句,始终使用参数化查询 (cursor.execute(sql, params))。
  6. 错误处理:使用 try...except cx_Oracle.DatabaseError 来捕获和处理数据库相关的错误。
  7. 代码结构化:将数据库连接信息(用户名、密码、DSN)存储在配置文件或环境变量中,而不是硬编码在脚本里。

你可以利用 Python 的强大功能,构建复杂的数据库自动化脚本,将重复性的工作交给机器,让自己专注于更有创造性的任务,Python 与 Oracle 的结合,将为你的工作效率带来质的飞跃!

分享:
扫描分享到社交APP
上一篇
下一篇