Python调用SQLPlus来操作和解析Oracle数据库的方法


Posted in Python onApril 09, 2016

先来看一个简单的利用python调用sqlplus来输出结果的例子:

import os
import sys
from subprocess import Popen, PIPE
 
sql = """
set linesize 400
col owner for a10
col object_name for a30
 
select owner, object_name
 from dba_objects
 where rownum<=10;
"""
 
proc = Popen(["sqlplus", "-S", "/", "as", "sysdba"], stdout=PIPE, stdin=PIPE, stderr=PIPE)
proc.stdin.write(sql)
(out, err) = proc.communicate()
 
if proc.returncode != 0:
  print err
  sys.exit(proc.returncode)
else:
  print out

用Python查询Oracle,当然最好用cx_Oracle库,但有时候受到种种限制,不能安装Python第三方库,就得利用现有资源,硬着头皮上了。

用Python调用SqlPlus查询Oracle,首先要知道SqlPlus返回结果是什么样的:

(这是空行)
Number    Name    Address
------------ ----------- ------------------
1001     张三     南京路
1002     李四     上海路

第1行是空行,第2行是字段名称,第3行都是横杠,有空格隔开,第4行开始是查询到的结果。

在查询结果规整的情况下,根据第3行可以很清晰的看到结构,用Python解析起来也比较方便。但是,如果一张表字段特别多,记录数也相当多,那么默认情况下调用SqlPlus查询出的结果会比较乱,这就需要在调用查询之前做一些设定,比如:

set linesize 32767
set pagesize 9999
set term off verify off feedback off tab off
set numwidth 40

这样的调用查询结果就比较规整了。接下来就是用强大的Python来解析查询结果。

这里封装了一个函数,可以根据传入的SQL语句查询并解析结果,将每行结果存到列表中,列表中的每个元素是一个字段名称与值的映射。

#!/usr/bin/python
#coding=UTF-8

'''
@author: 双子座@开源中国
@summary: 通过SqlPlus查询Oracles数据库
'''

import os;

os.environ['NLS_LANG'] = 'AMERICAN_AMERICA.AL32UTF8'
gStrConnection = 'username/password@10.123.5.123:1521/ora11g'

#解析SqlPlus的查询结果,返回列表
def parseQueryResult(listQueryResult):
  listResult = []
  #如果少于4行,说明查询结果为空
  if len(listQueryResult) < 4:
    return listResult
  #第0行是空行,第1行可以获取字段名称,第2行可获取SQLPlus原始结果中每列宽度,第3行开始是真正输出
  # 1 解析第2行,取得每列宽度,放在列表中
  listStrTmp = listQueryResult[2].split(' ')
  listIntWidth = []
  for oneStr in listStrTmp:
    listIntWidth.append(len(oneStr))
  # 2 解析第1行,取得字段名称放在列表中
  listStrFieldName = []
  iLastIndex = 0
  lineFieldNames = listQueryResult[1]
  for iWidth in listIntWidth:
    #截取[iLastIndex, iLastIndex+iWidth)之间的字符串
    strFieldName = lineFieldNames[iLastIndex:iLastIndex + iWidth]
    strFieldName = strFieldName.strip() #去除两端空白符
    listStrFieldName.append(strFieldName)
    iLastIndex = iLastIndex + iWidth + 1
  # 3 第3行开始,解析结果,并建立映射,存储到列表中
  for i in range(3, len(listQueryResult)):
    oneLiseResult = unicode(listQueryResult[i], 'UTF-8')
    fieldMap = {}
    iLastIndex = 0
    for j in range(len(listIntWidth)):
      strFieldValue = oneLiseResult[iLastIndex:iLastIndex + listIntWidth[j]]
      strFieldValue = strFieldValue.strip()
      fieldMap[listStrFieldName[j]] = strFieldValue
      iLastIndex = iLastIndex + listIntWidth[j] + 1
    listResult.append(fieldMap)
  return listResult

def QueryBySqlPlus(sqlCommand):
  global gStrConnection
  #构造查询命令
  strCommand = 'sqlplus -S %s <<!\n' % gStrConnection
  strCommand = strCommand + 'set linesize 32767\n'
  strCommand = strCommand + 'set pagesize 9999\n'
  strCommand = strCommand + 'set term off verify off feedback off tab off \n'
  strCommand = strCommand + 'set numwidth 40\n'
  strCommand = strCommand + sqlCommand + '\n'
  #调用系统命令收集结果
  result = os.popen(strCommand)
  list = []
  for line in result:
    list.append(line)
  return parseQueryResult(list)

其中os.environ['NLS_LANG']的值来自

select userenv['language'] from dual;
在调用的时候,只要类似:
listResult = QueryBySqlPlus('select * from studentinfo')

然后就可以用循环打印出结果了。

Python 相关文章推荐
在Python中使用base64模块处理字符编码的教程
Apr 28 Python
python实现查找excel里某一列重复数据并且剔除后打印的方法
May 26 Python
使用Python脚本将文字转换为图片的实例分享
Aug 29 Python
Python探索之创建二叉树
Oct 25 Python
Python编程之gui程序实现简单文件浏览器代码
Dec 08 Python
使用python爬取B站千万级数据
Jun 08 Python
Python将list中的string批量转化成int/float的方法
Jun 26 Python
从运行效率与开发效率比较Python和C++
Dec 14 Python
Python的log日志功能及设置方法
Jul 11 Python
PyCharm+Miniconda3安装配置教程详解
Feb 16 Python
requests在python中发送请求的实例讲解
Feb 17 Python
python 算法题——快乐数的多种解法
May 27 Python
python调用fortran模块
Apr 08 #Python
python3使用urllib模块制作网络爬虫
Apr 08 #Python
Python抓取电影天堂电影信息的代码
Apr 07 #Python
Python Requests安装与简单运用
Apr 07 #Python
Python Requests 基础入门
Apr 07 #Python
Python检测网站链接是否已存在
Apr 07 #Python
python多进程共享变量
Apr 06 #Python
You might like
thinkphp实现图片上传功能分享
2014/03/04 PHP
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 2611816 bytes)
2014/11/08 PHP
php实现的二叉树遍历算法示例
2017/06/15 PHP
PHP convert_cyr_string()函数讲解
2019/02/13 PHP
基于jQuery的的一个隔行变色,鼠标移动变色的小插件
2010/07/06 Javascript
js中escape对应的C#解码函数 UrlDecode
2012/12/16 Javascript
Javascript 拖拽的一些高级的应用(逐行分析代码,让你轻松了拖拽的原理)
2015/01/23 Javascript
JS实现的页面自定义滚动条效果
2015/10/26 Javascript
jquery对象与DOM对象转化
2017/02/08 Javascript
vue组件的写法汇总
2018/04/12 Javascript
JavaScript实现异步图像上传功能
2018/07/12 Javascript
jquery ajax加载数据前台渲染方式 不用for遍历的方法
2018/08/09 jQuery
js的对象与函数详解
2019/01/21 Javascript
JS隐藏号码中间4位代码实例
2019/04/09 Javascript
图解NodeJS实现登录注册功能
2019/09/16 NodeJs
JQuery常用选择器功能与用法实例分析
2019/12/23 jQuery
python根据距离和时长计算配速示例
2014/02/16 Python
python提取内容关键词的方法
2015/03/16 Python
Python 装饰器使用详解
2017/07/29 Python
hmac模块生成加入了密钥的消息摘要详解
2018/01/11 Python
Python编程argparse入门浅析
2018/02/07 Python
Python wxPython库消息对话框MessageDialog用法示例
2018/09/03 Python
python消费kafka数据批量插入到es的方法
2018/12/27 Python
Python实现图片转字符画的代码实例
2019/02/22 Python
PyQt5 closeEvent关闭事件退出提示框原理解析
2020/01/08 Python
在python tkinter界面中添加按钮的实例
2020/03/04 Python
使用python执行shell脚本 并动态传参 及subprocess的使用详解
2020/03/06 Python
乌克兰数字设备、配件和智能技术的连锁商店:KTC
2020/08/18 全球购物
局域网定义和特性
2016/01/23 面试题
《要下雨了》教学反思
2014/02/17 职场文书
理工大学毕业生自荐信范文
2014/02/22 职场文书
导游词之茶卡盐湖
2019/11/26 职场文书
Python还能这么玩之用Python修改了班花的开机密码
2021/06/04 Python
zabbix自定义监控nginx状态实现过程
2021/11/01 Servers
Python接口自动化之文件上传/下载接口详解
2022/04/05 Python