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基础教程之面向对象的一些概念
Aug 29 Python
Python单元测试框架unittest使用方法讲解
Apr 13 Python
Python实现获取磁盘剩余空间的2种方法
Jun 07 Python
Python实现读取邮箱中的邮件功能示例【含文本及附件】
Aug 05 Python
python清理子进程机制剖析
Nov 23 Python
python使用mysql的两种使用方式
Mar 07 Python
python 用lambda函数替换for循环的方法
Jun 09 Python
Django添加sitemap的方法示例
Aug 06 Python
Pandas 重塑(stack)和轴向旋转(pivot)的实现
Jul 22 Python
django项目登录中使用图片验证码的实现方法
Aug 15 Python
Django REST framework 单元测试实例解析
Nov 07 Python
Python3内置函数chr和ord实现进制转换
Jun 05 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
php 图像函数大举例(非原创)
2009/06/20 PHP
php递归创建和删除文件夹的代码小结
2012/04/13 PHP
PHPExcel内存泄漏问题解决方法
2015/01/23 PHP
PHP 自动加载的简单实现(推荐)
2016/08/12 PHP
浅析PHP7 的垃圾回收机制
2019/09/06 PHP
laravel-admin解决表单select联动时,编辑默认没选上的问题
2019/09/30 PHP
javascript onmouseout 解决办法
2010/07/17 Javascript
根据一段代码浅谈Javascript闭包
2010/12/14 Javascript
javascript淡入淡出效果的实现思路
2012/03/31 Javascript
jquery插件开发之实现jquery手风琴功能分享
2014/03/10 Javascript
Javascript实现鼠标右键特色菜单
2015/08/04 Javascript
javascript的 {} 语句块详解
2016/02/27 Javascript
微信小程序 MD5加密登录密码详解及实例代码
2017/01/12 Javascript
JS简单实现获取元素的封装操作示例
2017/04/07 Javascript
Javascript中的async awai的用法
2017/05/17 Javascript
Vue axios 中提交表单数据(含上传文件)
2017/07/06 Javascript
js实现敏感词过滤算法及实现逻辑
2018/07/24 Javascript
js实现简单的贪吃蛇游戏
2020/04/23 Javascript
javascript实现移动端触屏拖拽功能
2020/07/29 Javascript
浅谈vue项目,访问路径#号的问题
2020/08/14 Javascript
Python中的一些陷阱与技巧小结
2015/07/10 Python
Python读取和处理文件后缀为.sqlite的数据文件(实例讲解)
2017/06/27 Python
详谈python3中用for循环删除列表中元素的坑
2018/04/19 Python
python 读取数据库并绘图的实例
2019/12/03 Python
pytorch实现查看当前学习率
2020/06/24 Python
python中pyplot基础图标函数整理
2020/11/10 Python
HTML5 Blob 实现文件下载功能的示例代码
2019/11/29 HTML / CSS
凌阳科技股份有限公司C++程序员面试题笔试题
2014/11/20 面试题
客服专员岗位职责范本
2013/11/29 职场文书
小学教师管理制度
2014/01/18 职场文书
会计专业应届生自荐信
2014/02/07 职场文书
个人担保书格式范文
2014/05/12 职场文书
建筑安全生产目标责任书
2014/07/23 职场文书
解决MySQL存储时间出现不一致的问题
2021/04/28 MySQL
python调试工具Birdseye的使用教程
2021/05/25 Python
mysql使用 not int 子查询隐含陷阱
2022/04/12 MySQL