达梦数据库-学习-46-sqlalchemy_dm+dmPython安装与示例

目录

一、环境信息

二、说点什么

三、下载链接

四、安装

1、Python3安装

2、环境变量配置

(1)配置

(2)生效

3、升级

4、SQLAlchemy安装

5、dmPython源码编译安装

(1)切换目录

(2)编译安装

6、sqlalchemy_dm源码编译安装

(1)切换目录

(2)编译安装

五、Demo

1、源码

2、运行

3、验证


一、环境信息

|------|--------------------------------------------------------------------------------------------------------------------|
| 名称 | 值 |
| 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.
相关推荐
heartbeat..5 小时前
Redis 中的锁:核心实现、类型与最佳实践
java·数据库·redis·缓存·并发
Prince-Peng5 小时前
技术架构系列 - 详解Redis
数据结构·数据库·redis·分布式·缓存·中间件·架构
cooldream20095 小时前
Vim 报错 E325:swap 文件冲突的原理、处理流程与彻底避免方案
linux·编辑器·vim
i建模5 小时前
在 Rocky Linux 上安装轻量级的 XFCE 桌面
linux·运维·服务器
虾说羊5 小时前
redis中的哨兵机制
数据库·redis·缓存
_F_y5 小时前
MySQL视图
数据库·mysql
lxl13075 小时前
学习C++(5)运算符重载+赋值运算符重载
学习
2301_790300965 小时前
Python单元测试(unittest)实战指南
jvm·数据库·python
Data_Journal5 小时前
Scrapy vs. Crawlee —— 哪个更好?!
运维·人工智能·爬虫·媒体·社媒营销
若风的雨6 小时前
WC (Write-Combining) 内存类型优化原理
linux