Python连接Oracle数据库,以字典形式返回结果

本文介绍如何使用Python的cx_Oracle包连接Oracle数据库,并通过简单的代码示例展示如何将查询结果转换为包含字段名的字典格式,便于进一步的数据处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

众所周知,Python连接Oracle数据库,一般都使用cx_Oracle这个包。

但关键是cx_Oracle这个包,返回的结果,都是元组或者列表。

如以下代码:

 1 import cx_Oracle
 2 import os
 3 
 4 os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'
 5 
 6 connection = cx_Oracle.connect("Booker", "123456", "172.18.240.31:1521/Book")
 7 
 8 cursor = connection.cursor()
 9 cursor.execute(" select * from book",)
10 
11 a = cursor.fetchall()
12 for c in a:
13     print(c)
14 
15 cursor.close()
16 connection.close()

其返回的结果如下:

('PHP',  '黄大力', '外星出版社', '34')

这是一个元组。无法返回包含字段名的字典格式。

查阅cx_Oracle的官方文档:https://oracle.github.io/python-cx_Oracle/

也没有找到相应的方法。

对于我这种强迫症的人来说,这是不可接受的。

能不能有其它的办法呢?找了一下,发现cursor有一个属性description,是显示字段的描述的,打印看看是什么结果:

print(cursor.description)

显示如下:

[ ('book_name', <class 'cx_Oracle.STRING'>, 300, 900, None, None, 1),, ('author', <class 'cx_Oracle.STRING'>, 300, 900, None, None, 1), ('public', <class 'cx_Oracle.STRING'>, 300, 900, None, None, 1), ('price', <class 'cx_Oracle.STRING'>, 300, 900, None, None, 1)]

是一个列表,而每一个字段则是一个元组,元组的第一个元素则是字段名。

查阅cx_Oracle的官方文档,其对cursor.description是这么描述的:

该只读属性是7项序列的序列。这些序列中的每一个都包含描述一个结果列的信息:(name,type,display_size,internal_size,precision,scale,null_ok)。对于不返回行的操作,或者如果游标execute()尚未通过该方法调用操作,此属性将为None 。

该类型将是模块级别定义的类型对象之一。

这就好办了。

for d in cursor.description:
    print(d)

输出:

('book_name', <class 'cx_Oracle.STRING'>, 20, 60, None, None, 0)
('author', <class 'cx_Oracle.DATETIME'>, 23, None, None, None, 1)
('public', <class 'cx_Oracle.STRING'>, 20, 60, None, None, 1)
('price', <class 'cx_Oracle.STRING'>, 300, 900, None, None, 1)

嗯,对的,每一个元素都是一个元组,我们就可以通过d[0]把字段名取出来了。

for d in cursor.description:
    print(d[0])

输出:

book_name
author
public
price

那这样,我们就可以使用一个for循环,把字段名取出来。以下这段语句,是循环cursor.description,取出第1个元素,然后组成一个列表。

cols = [d[0] for d in cursor.description]
print(cols)

输出:

['book_name', 'author', 'public', 'price']

那么,怎么和查询结果组合成字典呢?嗯,使用zip函数。

zip() 函数用于将可迭代对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象。

zip() 函数语法:

zip(iterable1,iterable2, ...)

参数说明:

  • iterable -- 一个或多个可迭代对象(字符串、列表、元祖、字典)

没错,字符串、列表、元组、字典都是可迭代对象。

zip函数就像一个拉链一下,把两个可迭代对象的元素一一对应起来。如果各个可迭代对象的元素个数不一致,则返回的对象长度与最短的可迭代对象相同。

使用以下代码,即可形成字段名和结果的字典了。

 1 import cx_Oracle
 2 import os
 3 
 4 os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'
 5 
 6 connection = cx_Oracle.connect("Booker", "123456", "172.18.240.31:1521/Book") 
 7 cursor = connection.cursor() cursor.execute("select * from book")  
 8 a = cursor.fetchall() 
 9 cols = [d[0] for d in cursor.description] 
10 print(cols) 
11 for row in a:
12   b = dict(zip(cols, row)) 
13   print(b['book_name']) 
14 cursor.close() 
15 connection.close()

输出:

PHP

这样我们就可以使用b['字段名']的方式进入各种操作了,又清晰又方便。

 

转载于:https://www.cnblogs.com/dhanchor/p/11111247.html

<think>我们被要求使用Python连接Oracle数据库,执行SQL语句,并将结果返回给Dify平台。根据引用,我们可以使用cx_Oracle库(现在更名为oracledb)来连接Oracle数据库。然后,我们需要将查询结果转换为Dify平台可以接受的格式,例如JSON。 步骤: 1. 安装必要的库:oracledb(即cx_Oracle的新版本)和flask(用于创建Web服务,以便Dify平台可以通过API调用)。 2. 编写连接Oracle数据库的代码,并执行SQL语句。 3. 创建一个简单的Web服务(使用Flask),该服务接收一个包含SQL查询的请求(或从请求中获取查询参数),然后执行该查询返回结果。 4. 在Dify平台中,我们可以通过HTTP请求(如HTTP Request节点)来调用这个Web服务,从而将结果返回给Dify平台。 注意:根据引用[3],在Dify中我们可以通过知识库和自然语言生成SQL,然后通过Python执行。这里我们假设已经生成了SQL语句,现在需要执行并返回结果。 详细步骤: 第一步:安装库 使用pip安装oracledb和flask: ```bash pip install oracledb flask ``` 第二步:编写Python脚本 我们将创建一个名为`oracle_service.py`的脚本,其中包含以下功能: - 连接Oracle数据库(使用连接字符串、用户名和密码) - 执行SQL查询 - 将结果转换为字典列表(方便JSON序列化) - 通过Flask提供API接口 第三步:在Flask应用中设置路由 我们将创建一个POST(或GET,但建议POST)接口,接收JSON格式的请求,其中包含要执行的SQL语句(或者包含SQL语句的参数)。然后执行该SQL并返回结果。 示例代码: 注意:为了安全,我们不应该允许任意SQL执行(防止SQL注入)。在实际应用中,应该限制可执行的SQL类型或使用参数化查询。但根据问题,我们假设SQL是安全且由Dify平台生成的。 这里我们提供一个简单的示例,仅供参考。请根据实际情况调整数据库连接参数和安全措施。 ```python import oracledb from flask import Flask, request, jsonify app = Flask(__name__) # 配置数据库连接信息 # 请替换为你的实际连接信息 USERNAME = 'your_username' PASSWORD = 'your_password' DSN = 'your_host:your_port/your_service_name' # 例如:'localhost:1521/orcl' def get_connection(): # 创建连接 connection = oracledb.connect(user=USERNAME, password=PASSWORD, dsn=DSN) return connection @app.route('/execute_query', methods=['POST']) def execute_query(): # 从请求中获取SQL语句 data = request.get_json() sql = data.get('sql') if not sql: return jsonify({'error': 'No SQL provided'}), 400 try: conn = get_connection() cursor = conn.cursor() cursor.execute(sql) # 获取列名 columns = [col[0] for col in cursor.description] # 获取所有行并转换为字典列表 rows = [] for row in cursor: rows.append(dict(zip(columns, row))) cursor.close() conn.close() return jsonify(rows) except Exception as e: return jsonify({'error': str(e)}), 500 if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) ``` 第四步:运行服务 在命令行中运行: ```bash python oracle_service.py ``` 第五步:在Dify平台中使用HTTP Request节点调用该服务 在Dify的工作流中,添加一个“HTTP Request”节点,配置如下: - URL: http://localhost:5000/execute_query (如果服务部署在远程服务器,请使用相应地址) - 方法: POST - Headers: Content-Type: application/json - Body: 一个JSON对象,包含键`sql`,值为要执行的SQL语句(例如:`{"sql": "SELECT * FROM my_table"}`) 然后,HTTP Request节点的输出就是数据库查询结果,可以在后续节点中使用。 注意事项: 1. 安全性:这个示例允许执行任意SQL语句,存在安全风险。在生产环境中,应该对SQL语句进行严格的校验,或者只允许执行特定的查询(例如通过存储过程)。 2. 错误处理:上述代码中捕获了异常并返回错误信息,但实际应用中可能需要更详细的错误处理。 3. 连接池:对于高并发场景,应该使用连接池来管理数据库连接,而不是每次请求都新建连接。 4. 环境配置:确保运行该服务的服务器可以访问Oracle数据库,并且安装了Oracle客户端(或者使用oracledb的瘦模式,不需要安装客户端)。 引用说明: - 引用[1]和[4]介绍了Python连接Oracle数据库的基本方法,我们使用了oracledb库(即cx_Oracle)[^1][^4]。 - 引用[2]提到了通过Python连接Dify并结合知识库解析自然语言生成SQL,然后执行。我们的服务正是用于执行SQL并返回结果[^2]。 - 引用[3]强调了生成SQL的规则,我们在Dify平台中生成SQL后,通过这个服务执行[^3]。 通过以上步骤,我们实现了Python连接Oracle数据库执行SQL并将结果返回给Dify平台的功能。 生成的相关问题: 1. 如何确保从Dify平台生成的SQL语句的安全性? 2. 在Dify平台中如何处理数据库查询结果以生成图表? 3. 如何优化PythonOracle数据库连接性能?</think>### Python 连接 Oracle 数据库并将结果返回 Dify 平台的完整指南 以下是分步实现方案,结合引用内容并优化了安全性和性能: #### 1. **环境准备与依赖安装** ```bash # 安装必需库 (引用[1][4]) pip install oracledb flask flask-cors ``` - `oracledb`:Oracle 官方 Python 驱动(替代 cx_Oracle) - `flask`:创建 API 接口供 Dify 调用 - `flask-cors`:解决跨域问题 #### 2. **Python 连接 Oracle 的核心代码** ```python import oracledb from flask import Flask, request, jsonify from flask_cors import CORS app = Flask(__name__) CORS(app) # 允许跨域请求 # Oracle 连接配置 (引用[4]) ORACLE_USER = "your_username" ORACLE_PWD = "your_password" ORACLE_DSN = "hostname:port/service_name" # 示例: localhost:1521/ORCLCDB def get_oracle_connection(): """创建 Oracle 数据库连接""" try: # 使用瘦客户端模式 (无需安装 Oracle 客户端) connection = oracledb.connect( user=ORACLE_USER, password=ORACLE_PWD, dsn=ORACLE_DSN ) return connection except Exception as e: print(f"数据库连接失败: {str(e)}") return None @app.route('/execute-sql', methods=['POST']) def execute_sql(): """执行 SQL 并返回结果""" # 从 Dify 请求中获取 SQL sql_query = request.json.get('sql') if not sql_query: return jsonify({"error": "未提供 SQL 语句"}), 400 conn = get_oracle_connection() if not conn: return jsonify({"error": "数据库连接失败"}), 500 try: with conn.cursor() as cursor: cursor.execute(sql_query) # 获取结果集 (引用[4]) if cursor.description: columns = [col[0] for col in cursor.description] rows = cursor.fetchall() result = [dict(zip(columns, row)) for row in rows] else: result = {"affected_rows": cursor.rowcount} return jsonify({"data": result}) except oracledb.Error as e: return jsonify({"error": f"SQL 执行错误: {str(e)}"}), 400 finally: conn.close() if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=False) ``` #### 3. **Dify 平台调用流程** 1. **在 Dify 中创建 API 工具** (引用[2][3]) - 路径:`工作流 > 添加工具 > HTTP 请求` - 配置: ``` URL: http://your-server-ip:5000/execute-sql 方法: POST Headers: Content-Type: application/json Body: {"sql": "{{ 生成的SQL语句 }}"} ``` 2. **在知识库中配置 SQL 生成规则** (引用[3]) ```sql -- 知识库提示词示例 (引用[3]) 你是一个数据分析师,根据用户需求生成 Oracle SQL 语句。 要求: 1. 仅返回可执行的 SQL 语句 2. 使用 LIKE 进行字符串匹配 3. 使用 SUM() 处理求和请求 4. 无效请求返回“无法形成查询” ``` #### 4. **安全增强措施** 1. **SQL 白名单验证** (防注入) ```python # 在 execute_sql() 函数中添加 VALID_KEYWORDS = ["SELECT", "FROM", "WHERE", "JOIN", "GROUP BY"] def is_safe_sql(sql): sql_upper = sql.upper() return all(kw in sql_upper for kw in VALID_KEYWORDS) and \ not any(kw in sql_upper for kw in ["DROP", "DELETE", "UPDATE", "INSERT"]) ``` 2. **连接池管理** (高性能) ```python # 使用连接池 (引用[4]) pool = oracledb.create_pool( user=ORACLE_USER, password=ORACLE_PWD, dsn=ORACLE_DSN, min=2, max=5, increment=1 ) # 在接口中获取连接 conn = pool.acquire() ``` #### 5. **执行示例** 1. **Dify 用户输入** `"显示2023年销售额前10的客户"` 2. **知识库生成 SQL** (引用[3]) ```sql SELECT customer_name, SUM(sales_amount) AS total_sales FROM sales WHERE EXTRACT(YEAR FROM sale_date) = 2023 GROUP BY customer_name ORDER BY total_sales DESC FETCH FIRST 10 ROWS ONLY ``` 3. **返回 Dify 的结果格式** ```json { "data": [ {"CUSTOMER_NAME": "Company A", "TOTAL_SALES": 1500000}, {"CUSTOMER_NAME": "Company B", "TOTAL_SALES": 1200000}, ... ] } ``` #### 关键注意事项 1. **连接故障处理** - 添加重试机制(如引用[5]) - 使用 `ping()` 验证连接状态 ```python if conn.ping() is None: print("连接有效") ``` 2. **数据类型转换** Oracle 的 `CLOB`/`BLOB` 需特殊处理: ```python # 在结果转换处添加 if isinstance(value, oracledb.LOB): value = value.read() ``` 3. **性能优化** - 分页查询:添加 `LIMIT` 和 `OFFSET` 参数 - 异步处理:对长查询使用 Celery 任务队列 > 通过此方案,Dify 平台可实现:自然语言 → SQL生成 → Oracle执行 → 结果可视化的完整流程[^2][^3]。实际部署时建议使用 HTTPS 和 API 密钥认证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值