问题
使用python操作oracle数据库,获取表的某几个字段作为变量值使用。
使用Popen+sqlplus的方法需要对格式进行控制,通过流获取这几个字段值不简洁(个人观点……)。(优点是能够使用sqlplus的方法直接访问sql文件,不需要考虑打开/关闭连接,并且通过流向文件中写入还挺好用的。不过优点不是这次所关注的)
使用cx-Oracle将查询结果返回为tuple格式,对返回结果的操作简洁,满足需求。(要注意数据库连接创建与关闭、sql的编写、预处理与提交等等,看起来也不简洁(同样个人观点……))
基础方法
数据库连接
1、使用tns串连接
1
2
|
connectObj = cx_Oracle.connect( 'oracleUserName' , 'password' , oracle_tns) |
2、其他简洁方式
1
2
|
db = cx_Oracle.connect( 'hr' , 'hrpwd' , 'localhost:1521/XE' ) db1 = cx_Oracle.connect( 'hr/hrpwd@localhost:1521/XE' ) |
数据库断开连接
1
|
connectObj.close() |
建立游标
1
|
cursorObj = connectObj.cursor() |
关闭游标
1
|
cursorObj.close() |
增
1、单条插入:
1
2
3
4
|
sql = "INSERT INTO T_AUTOMONITOR_TMP(point_id) VALUES(:pointId)" cursorObj.prepare(sql) rown = cursorObj.execute( None , { 'pointId' : pointId}) connectObj.commit() |
2、多条插入:
1
2
3
4
|
sql = "INSERT INTO T_AUTOMONITOR_TMP(point_id) VALUES(:pointId)" cursorObj.prepare(sql) rown = cursorObj.executemany( None , recordList) connectObj.commit() |
删
1
2
3
4
|
sql = "DELETE FROM T_AUTOMONITOR_TMP t WHERE t.point_id = :pointId " cursorObj.prepare(sql) rown = cursorObj.execute( None , { 'pointId' : pointId}) connectObj.commit() |
改
1
2
3
4
5
6
7
8
|
sql = "UPDATE t_automonitor_other t\ SET t.active = '2' \ WHERE t.active = '1' \ AND t.point_id = :pointId\ " cursorObj.prepare(sql) cursorObj.execute( None , { 'pointId' : pointId}) connectObj.commit() |
查
1
2
3
|
sql = "SELECT t.describ FROM t_automonitor_tmp t WHERE t.point_id = :pointId" cursorObj.prepare(sql) cursorObj.execute( None , { 'pointId' : pointId}) |
Tips
- 增、删、改操作都需要当前连接进行commit()
- 若使用一个游标cursor进行N次查询,注意若再使用前N-1次查询结果可能会存在异常。要进行多个查询,个人建议使用完cursor后将结果保留再关闭cursor,多次查询重复该操作。
- 如果不使用prepare,可以直接使用execute,以下查询等价:
1
2
3
|
r1 = cursor.execute( 'SELECT * FROM locations WHERE country_id=:1 AND city=:2' , ( 'US' , 'Seattle' )) r2 = cursor.execute( 'SELECT * FROM locations WHERE country_id=:9 AND city=:4' , ( 'US' , 'Seattle' )) r3 = cursor.execute( 'SELECT * FROM locations WHERE country_id=:m AND city=:0' , ( 'US' , 'Seattle' )) |
- sql语句的语法与数据库有关,不想使用绑定变量,可以拼接sql字符串 (´•༝•`)
简单工具
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
class baseUtilsX(): """baseUtils""" def __init__( self ): self .connectObj = "" self .connCnt = 0 self .cursorCnt = 0 def initOracleConnect( self ): oracle_tns = cx_Oracle.makedsn( 'XXX.XXX.XXX.XXX' , 1521 , 'XX' ) if self .connCnt = = 0 : self .connectObj = cx_Oracle.connect( 'oracleUserName' , 'password' , oracle_tns) self .connCnt + = 1 def getOracleConnect( self ): self .initOracleConnect() return self .connectObj def closeOracleConnect( self , connectObj): connectObj.close() self .connCnt - = 1 def getOracleCursor( self ): self .initOracleConnect() self .cursorCnt + = 1 return self .connectObj.cursor() def closeOracleCursor( self , cursorObj): cursorObj.close() self .cursorCnt - = 1 if self .cursorCnt = = 0 : print "will close conn" self .closeOracleConnect( self .connectObj) def selectFromDbTable( self , sql, argsDict): # 将查询结果由tuple转为list queryAnsList = [] selectCursor = self .getOracleCursor() selectCursor.prepare(sql) queryAns = selectCursor.execute( None , argsDict) for ansItem in queryAns: queryAnsList.append( list (ansItem)) self .closeOracleCursor(selectCursor) return queryAnsList |
python 连接 Oracle 乱码问题(cx_Oracle)
用python连接Oracle是总是乱码,最后发现时oracle客户端的字符编码设置不对。
编写的python脚本中需要加入如下几句:
1
2
|
import os os.environ[ 'NLS_LANG' ] = 'SIMPLIFIED CHINESE_CHINA.UTF8' |
这样可以保证select出来的中文显示没有问题。
要能够正常的insert和update中文,还需要指定python源文件的字符集密码和oracle一致。
1
|
# -*- coding: utf-8 -*- |
例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# -*- coding: utf-8 -*- import os os.environ[ 'NLS_LANG' ] = 'SIMPLIFIED CHINESE_CHINA.UTF8' #或者os.environ['NLS_LANG'] = 'AMERICAN_AMERICA.AL32UTF8' import cx_Oracle db = cx_Oracle.connect(username / passwd@host:port / sevicename) cursor = db.cursor() #其他操作 db.commit() db.close() |
参考:
客户端的NLS_LANG设置及编码转换
①在Oracle客户端向服务器端提交SQL语句时,Oracle客户端根据NLS_LANG和数据库字符集,对从应用程序接传送过来的字符串编码进行转换处理。如果NLS_LANG与数据库字符集相同,不作转换,否则要转换成数据库字符集并传送到服务器。服务器在接收到字符串编码之后,对于普通的CHAR或VARCHAR2类型,直接存储;对于NCHAR或NVARCHAR2类型,服务器端将其转换为国家字符集再存储。
①在Oracle客户端向服务器端提交SQL语句时,Oracle客户端根据NLS_LANG和数据库字符集,对从应用程序接传送过来的字符串编码进行转换处理。如果NLS_LANG与数据库字符集相同,不作转换,否则要转换成数据库字符集并传送到服务器。服务器在接收到字符串编码之后,对于普通的CHAR或VARCHAR2类型,直接存储;对于NCHAR或NVARCHAR2类型,服务器端将其转换为国家字符集再存储。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
参考文章
精通 Oracle+Python,第 1 部分:查询最佳应践
原文链接:https://segmentfault.com/a/1190000012022631