问题
使用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