概述

  1. dmPython是DM提供的依据Python DB API version 2.0中API使用规定而开发的数据库访问接口。使用API能对DM数据库进行访问。
  2. dmPythonn 接口当前版本号为 2.3,需要对应的DM Server版本为7.0.0.9以上,Python版本为2.6以上。

前置条件

  1. 已安装python2.6及以上版本(本文使用版本为anaconda虚拟环境3.8)
  2. 已安装DM8数据库

dmPython安装

dmPython可以运行在任何安装了 python 的平台上。可以使用安装包安装,也可以直接用源码安装。另外,需要保证 dpi 和 dmPython 版本一致,都是 32 位或都是 64 位。
由于dmPython的运行需要使用到dpi动态库,使用者必须将dpi所在的目录加入到系统的环境变量。(目录一般为DM安装路径下的bin目录)
dmPython路径一般为DM安装路径下的drivers/python/dmPython/目录中。
进入anaconda虚拟环境下执行:

cd /dm/drivers/python/dmPython/
python setup.py install

dmp 文件 python mysql python读取dmp文件_python

dmp 文件 python mysql python读取dmp文件_Python_02

当出现图中成功安装即为安装成功。

使用API操作数据库

dmp 文件 python mysql python读取dmp文件_1024程序员节_03

import dmPython
cursor = dmPython.connect(user='SYSDBA', password='SYSDBA', server='127.0.0.1', port='5236', autoCommit=True).cursor()#user默认值为SYSDBA,password默认值为SYSDBA,server默认值为localhost(等价于127.0.0.1),port默认值为5236,autoCommit默认值为Ture,均为非必要性参数。可以直接cursor = dmPython.connect()进行连接也可以cursor = dmPython.Connect()进行连接,三者完全等价。
CITY = cursor.execute('select * from DMHR.CITY')#语句为执行select * from DMHR.CITY的sql语句

CITY此时为DmdbCursor类型,DmdbCursor是达梦所特有的数据类型

使用fetchall()就可以将查询结果以list列表形式返回。

dmp 文件 python mysql python读取dmp文件_python_04

List类型可以直接取某列的值

dmp 文件 python mysql python读取dmp文件_dmp 文件 python mysql_05

使用fetchall()获取到表达式的列后,不能重复继续执行。

dmp 文件 python mysql python读取dmp文件_python_06

由上图所示,使用游标获取所有列后,会自动关闭释放资源,所以必须要有一个值用来收集输出。

CITY = cursor.execute('select * from DMHR.CITY')
get=CITY.fetchall()

此时变量get就可以和使用list一样操作,实现随机取值。

例:type(get[188])时,发现取出某个特定是一个元组形式。如果想获取到对应列的值,则需要get[188][0]就能获取到188行中对应的ID值。

dmp 文件 python mysql python读取dmp文件_Python_07

创建一个随机的拥有10000行数据的表DAMENG_TEST。

dmp 文件 python mysql python读取dmp文件_Python_08

使用时间函数time计算时间。当获取表中某个值所需要耗费的时间,使用list速度更优或者是使用where筛选返回速度更优。

#获取第1892行的数据

Import time
t=time.perf_counter()
cursor.execute("select * from dameng_test where rowid='1892'").fetchall()
end = time.perf_counter()
end-t
cursor.close

获取得到平均时间0.019441103000644944秒

#获取第9000行的数据

t=time.perf_counter()
a=cursor.execute("select * from dameng_test").fetchall()
a[9000]
enda=time.perf_counter()
enda-t
cursor.close

获取得到平均时间为0.5143464370012225秒

若改写成
#获取第9000行的数据

a=cursor.execute("select * from dameng_test").fetchall()
t=time.perf_counter()
a[9000]
enda=time.perf_counter()
enda-t
cursor.close

获取第9000个值的所需平均时间为0.00018298900067748036
其中使用游标花费时间0.514163448000545秒

筛选条件当ID=81470.976807862时

t=time.perf_counter()
cursor.execute("select * from dameng_test where ID=81470.976807862").fetchall()
end = time.perf_counter()
print(end-t)
cursor.close

执行平均时间为0.053887011999904644秒

筛选条件当ID=81470.976807862时

t=time.perf_counter()
for i in range(len(a)):
    if a[i][0] == 81470.976807862:
        result=i
        break
    enda=time.perf_counter()
print(enda-t)
cursor.close

执行平均时间为0.009578908000548836秒

当然,此时的表结构中并未加入index索引,在ID列上加入了索引后使用where条件通过哈希语句平均时间降低至0.01601278700036346秒,时间逼近于使用变量存储的时间。

若需要取某一行的操作较多,并且空间损耗可以接受的情况下。在python中先将对应的数据导入到某值中,再进行执行速度会快很多倍。空间换取时间,通过降低访问数据库的方式以提高程序的执行速率。

cursor.execute为操作数据库。同理增,删,改三个操作仅需要调整好其中的SQL语句即可。

实现增删改查基本操作。

将其打包成一个class类
直接执行

import dmPython
class DM8_DB():
    cursor = dmPython.connect(user='SYSDBA', password='SYSDBA', server='127.0.0.1', port='5236', autoCommit=True).cursor()
    def __init__(self, table, owner='SYSDBA',  id_data = None, student_name=None, score=None, update=None,where=None, select1='*'):
        self.owner=owner
        self.table=table
        self.id_data=str(id_data)
        self.student_name=student_name
        self.score=str(score)
        self.update=update
        self.where=where
        self.select1=select1
    def insert(self):
        sql="INSERT INTO "+self.owner+"."+self.table+" VALUES(?,?,?)"
        try:
            cursor.execute(sql,self.id, self.student_name,self.score)
            print('insert success')
        except:
            print('insert error')
    def update(self):
        sql="update "+self.owner+"."+self.table+" set ? where "+self.where
        try:
            cursor.execute(sql)
            print('update success')
        except:
            print('update error')
    def delete(self):
        sql='delete from "+self.owner+"."+self.table+"  where '+ self.where
        try:
            cursor.execute(sql)
            print('delete success')
        except:
            print('delete error')
    def select(self):
        cursor = dmPython.connect(user='SYSDBA', password='SYSDBA', server='127.0.0.1', port='5236', autoCommit=True).cursor()
        sql='select '+self.select1+' from '+self.owner+"."+self.table
        s=cursor.execute(sql).fetchall()
        try:
            if not self.where  is None:
                sql='select '+self.select1+' from '+self.owner+"."+self.table+'  where ? '+self.where
                s=cursor.execute(sql, self.select1, self.owner, self.table, self.where).fetchall()
                print('not null')
            else:
                sql='select '+self.select1+' from '+self.owner+"."+self.table
                s=cursor.execute(sql).fetchall()
                print('select success')
                return s
        except:
                print('select error')

可以直接执行查询

a=DM8_DB('dameng_test').select()#查询dameng_test所有记录
a=DM8_DB(table= 'dameng_test',where ='rowid = 1000').select()#查询dameng_test第1000行的值

实现INSERT功能

原图:

dmp 文件 python mysql python读取dmp文件_dmp 文件 python mysql_09

执行:

DM8_DB(owner='DMHR', table= 'REGION', id_data='8',student_name='ddong').insert()

执行后:

dmp 文件 python mysql python读取dmp文件_dmp 文件 python mysql_10

代码中所包含的?为参数传入值。仅对insert的参数值起作用

实现update更新

原图:

dmp 文件 python mysql python读取dmp文件_Python_11

执行:

DM8_DB(owner='DMHR', table= 'REGION', where= "REGION_NAME='ddong'", set1='REGION_ID=13').updateDATA()

执行后:

dmp 文件 python mysql python读取dmp文件_数据库_12

实现delete更新

原图:

dmp 文件 python mysql python读取dmp文件_Python_13

执行:

`DM8_DB(owner='DMHR', table= 'REGION', where= "REGION_NAME='ddong'").delete()`

执行后:

dmp 文件 python mysql python读取dmp文件_Python_14

大字段的查询
达梦数据库的大字段增改查与绑定参数的方式都是利用的cursor.execute接口,DM大字段最大支持长度是2G,超过则会报错。达梦的大字段类型与python版本有关。
对应为:
Python3及以上
BLOB类型数据查询结果为byte类型
CLOB类型数据查询结果为str类型
Python3及以下
BLOB类型数据查询结果为str类型
CLOB类型数据查询结果为unicode类型
插入一个CLOB类型longstring += 'ABCDEF0123456789' * 700与BLOB类型blobtype=longstring.encode("ascii")进入到数据库中。
执行

cursor.execute('insert into testLOB values(?, ?)', blobtype, longstring

查询只需要执行

cursor.execute('select * from testLOB).fetchall()

也可以执行

cursor.execute('select * from testLOB).fetchone()#执行取出一条记录
cursor.execute('select * from testLOB).next()#执行取出下一条记录