目录
一、环境信息
|------|--------------------------------------------------------------------------------------------------------------------|
| 名称 | 值 |
| CPU | 12th Gen Intel(R) Core(TM) i7-12700H |
| 操作系统 | CentOS Linux release 7.9.2009 (Core) |
| 内存 | 7G |
| 逻辑核数 | 8 |
| DM版本 | DM Database Server 64 V8 DB Version: 0x7000d 03134284368-20250917-293539-20149 Msg Version: 44 Gsu level(5) cnt: 0 |
二、说点什么
最近经常有客户使用sqlalchemy来操作达梦数据库出现问题,问题排查与解决的同时,也不由的感叹一下,sqlalchemy真的很便捷,python很适合快捷开发,入门比较友好,未入门者来说点什么。
三、下载链接
有的小伙伴想使用非源码编译安装,可以参考如下链接:
|----|--------------------------------------------------------------------------------------------------------------------------------------|
| 编号 | 链接 |
| 1 | 达梦数据库-学习-36-API驱动下载汇总 |
四、安装
1、Python3安装
|----|--------------------------------------------------------------------------------------------------------------------|
| 编号 | 链接 |
| 1 | Linux-学习-06-Python3安装与卸载 |
2、环境变量配置
(1)配置
/etc/profile添加如下内容:
bash
export DM_HOME="/opt/Dm8"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$DM_HOME/bin"
(2)生效
bash
. /etc/profile
3、升级
bash
pip3 install --upgrade pip setuptools wheel
4、SQLAlchemy安装
bash
pip3 install SQLAlchemy==1.4.48
5、dmPython源码编译安装
(1)切换目录
bash
cd /opt/Dm8/drivers/python/dmPython
安装实际路径来。
(2)编译安装
bash
python3 setup.py install
6、sqlalchemy_dm源码编译安装
(1)切换目录
bash
cd /opt/Dm8/drivers/python/sqlalchemy1.4.6
安装实际路径来。
(2)编译安装
bash
python3 setup.py install
五、Demo
1、源码
python
#encoding:utf-8
from sqlalchemy import create_engine, Column, Integer, String, Float
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from datetime import datetime
import time
import faulthandler
import os
import signal
faulthandler.enable(file=open('Core.log', 'w'))
def my_handler(signum, frame):
with open('my_handler.log', 'a') as f:
f.write('My handler caught signal : %d\n' % (signum))
# 创建基类
Base = declarative_base()
# 定义数据模型 - 学生表
class Student(Base):
__tablename__ = 'students'
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
student_id = Column(String(20), unique=True, nullable=False) # 学号
math_score = Column(Float, default=0.0)
english_score = Column(Float, default=0.0)
total_score = Column(Float, default=0.0)
grade = Column(String(10), default='') # 等级
def __repr__(self):
return "<Student(id={self.id}, name='{self.name}', total={self.total_score})>"
def main():
LoadRows = 1024
new_students = []
#signal.signal(signal.SIGSEGV, my_handler)
# 创建SQLite内存数据库(生产环境请用文件数据库)
engine = create_engine('dm://SYSDBA:qwer1234S@localhost:5236/',connect_args={'local_code':1,'connection_timeout':15}) # echo=True显示SQL语句
#os.kill(os.getpid(), signal.SIGFPE)
# 创建表
Base.metadata.create_all(engine)
# 创建会话工厂
Session = sessionmaker(bind=engine)
session = Session()
try:
print("=" * 50)
print("示例1: 批量插入新学生记录")
print("=" * 50)
# 创建要批量插入的学生列表
for i in range(LoadRows):
new_students.append(Student(id=i, name='Sun', student_id=str(i), math_score=i, english_score=i+1))
# 计算总分(演示在保存前可以预处理数据)
for student in new_students:
student.total_score = student.math_score + student.english_score
# 批量保存 - 性能最高的方式
start_time = time.time()
session.bulk_save_objects(new_students)
session.commit()
elapsed_time = time.time() - start_time
print("批量插入%d条记录完成,耗时: %4f 秒" % (len(new_students),elapsed_time))
# 查询验证(注意:bulk_save_objects不会填充ID到对象)
students_in_db = session.query(Student).all()
# for s in students_in_db:
# print(" ID:%d, 姓名:%s, 学号:%s, 总分:%f" % (s.id,s.name,s.student_id,s.total_score))
#
# print("\n" + "=" * 50)
# print("示例2: 批量更新学生成绩和等级")
# print("=" * 50)
#
# # 先查询出现有学生
# existing_students = session.query(Student).all()
#
# # 模拟批量更新:调整分数并计算等级
# for student in existing_students:
# # 给每个学生加点分(模拟批处理)
# student.math_score += 1.5
# student.english_score += 1.0
# student.total_score = student.math_score + student.english_score
#
# # 根据新总分计算等级
# if student.total_score >= 180:
# student.grade = 'A'
# elif student.total_score >= 160:
# student.grade = 'B'
# elif student.total_score >= 140:
# student.grade = 'C'
# else:
# student.grade = 'D'
#
# # 批量更新 - 使用相同的bulk_save_objects方法
# session.bulk_save_objects(existing_students)
# session.commit()
#
# print("批量更新完成!更新后的数据:")
# updated_students = session.query(Student).order_by(Student.total_score.desc()).all()
# for s in updated_students:
# print(" 姓名:{s.name:3} | 数学:{s.math_score:5.1f} | 英语:{s.english_score:5.1f} | 总分:{s.total_score:5.1f} | 等级:{s.grade}")
#
# final_students = session.query(Student).order_by(Student.id).all()
# for s in final_students:
# print(" ID:{s.id:2} | 姓名:{s.name:3} | 学号:{s.student_id} | 总分:{s.total_score:5.1f} | 等级:{s.grade}")
#
# # 注意:新插入的学生对象不会自动获取ID
# # 如果需要ID,需要在commit后重新查询
# print("\n注意:使用bulk_save_objects新插入的对象不会自动获取ID")
# print("例如,孙八的ID在对象中仍然是: {mixed_operations[1].id if len(mixed_operations) > 1 else 'N/A'}")
#
# # 如果需要获取新插入的ID,可以使用return_defaults参数(但有性能代价)
# print("\n" + "=" * 50)
# print("示例4: 使用return_defaults获取新插入的ID")
# print("=" * 50)
#
# # 创建新会话,演示return_defaults
# session2 = Session()
#
# new_student_with_id = Student(
# name='吴十',
# student_id='20230008',
# math_score=88.0,
# english_score=92.0,
# total_score=180.0
# )
#
# # 使用return_defaults=True,这样有默认值(如自增ID)的列会被填充
# # 注意:这会影响性能,只应用于确实需要立即获取ID的场景
# session2.bulk_save_objects([new_student_with_id], return_defaults=True)
# session2.commit()
#
# print("使用return_defaults后,新学生的ID: {new_student_with_id.id}")
#
# # 清理
# session2.close()
except Exception as e:
session.rollback()
print("发生错误: {e}")
import traceback
traceback.print_exc()
finally:
session.close()
print("\n程序执行完毕!")
if __name__ == "__main__":
main()
2、运行
bash
[dmdba@lzl PythonScript]$ python3 DmSqlAlchemy.py
==================================================
示例1: 批量插入新学生记录
==================================================
批量插入1024条记录完成,耗时: 0.195764 秒
程序执行完毕!
3、验证
bash
SQL> SELECT * FROM STUDENTS LIMIT 10;
行号 ID NAME STUDENT_ID MATH_SCORE ENGLISH_SCORE TOTAL_SCORE GRADE
---------- ----------- ---- ---------- ------------------------- ------------------------- ------------------------- -----
1 0 Sun 0 0.000000000000000E+00 1.000000000000000E+00 1.000000000000000E+00
2 1 Sun 1 1.000000000000000E+00 2.000000000000000E+00 3.000000000000000E+00
3 2 Sun 2 2.000000000000000E+00 3.000000000000000E+00 5.000000000000000E+00
4 3 Sun 3 3.000000000000000E+00 4.000000000000000E+00 7.000000000000000E+00
5 4 Sun 4 4.000000000000000E+00 5.000000000000000E+00 9.000000000000000E+00
6 5 Sun 5 5.000000000000000E+00 6.000000000000000E+00 1.100000000000000E+01
7 6 Sun 6 6.000000000000000E+00 7.000000000000000E+00 1.300000000000000E+01
8 7 Sun 7 7.000000000000000E+00 8.000000000000000E+00 1.500000000000000E+01
9 8 Sun 8 8.000000000000000E+00 9.000000000000000E+00 1.700000000000000E+01
10 9 Sun 9 9.000000000000000E+00 1.000000000000000E+01 1.900000000000000E+01
10 rows got
已用时间: 3.286(毫秒). 执行号:15002.