当前位置: 首页 > article >正文

SQLALchemy如何将SQL语句编译为特定数据库方言

最近在一个使用fastapi+tortoise-orm的项目中,需要将orm的语句编译成特定数据库方言,但是查询了官方文档及一些资料却找不到合适的方法论😔,于是乎我就把目光放到了sqlalchemy身上,东找西找给我找着了。话不多说,请看代码。

方法1:

import sqlalchemy.dialects.mysql
from sqlalchemy import Integer, String, Column
from sqlalchemy.orm import declarative_base
from sqlalchemy.sql import insert

Base = declarative_base()


class Student(Base):
    __tablename__ = 'student'

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True, comment="名称")
    age = Column(Integer, index=True, comment="年龄")


def generate_sql(instance):
    stmt = insert(instance.__class__).values(
        {c.name: getattr(instance, c.name) for c in instance.__table__.columns}
    )
    return stmt.compile(dialect=sqlalchemy.dialects.mysql.dialect(), compile_kwargs={"literal_binds": True})
ikun = Student(id=1, name="ikun", age=30)
jay = Student(id=1, name="jay", age=26)
print(generate_sql(ikun)) # INSERT INTO student (id, name, age) VALUES (1, 'ikun', 30)
print(generate_sql(jay))  # INSERT INTO student (id, name, age) VALUES (1, 'jay', 26)

上面代码通过insert() 创建一个 INSERT 语句对象,然后获取模型实例的对应列的值,使用stmt.compile编译成mysql的方言。但是这个方法对于json类型的字段会编译失败,出现

sqlalchemy.exc.CompileError: No literal value renderer is available for literal value "['唱跳', 'rap', '篮球']" with datatype JSON

的错误提示。

因此,介绍下一个方法。

方法2:

import sqlalchemy.dialects.mysql
from sqlalchemy import Integer, String, Column, JSON, text
from sqlalchemy.orm import declarative_base
from sqlalchemy.sql.compiler import SQLCompiler

Base = declarative_base()


class Student(Base):
    __tablename__ = 'student'

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True, comment="名称")
    age = Column(Integer, index=True, comment="年龄")
    hobby = Column(JSON, comment="爱好")


def generate_sql(instance: Student) -> SQLCompiler:
    columnsmap = {c.name: getattr(instance, c.name) for c in instance.__table__.columns}
    columns = columnsmap.keys()
    stmt = text(
        f"INSERT INTO {instance.__tablename__} ({', '.join(columns)}) VALUES ({', '.join([f":{c}" for c in columns])});"
    ).bindparams(**columnsmap)
    return stmt.compile(dialect=sqlalchemy.dialects.mysql.dialect(), compile_kwargs={"literal_binds": True})

输出:

ikun = Student(id=1, name="ikun", age=30, hobby=json.dumps(["唱跳", "rap", "篮球"]))
jay = Student(id=1, name="jay", age=26, hobby=json.dumps(["唱歌", "足球"]))
print(generate_sql(ikun)) # INSERT INTO student (id, name, age, hobby) VALUES (1, 'ikun', 30, '["\\u5531\\u8df3", "rap", "\\u7bee\\u7403"]');
print(generate_sql(jay)) # INSERT INTO student (id, name, age, hobby) VALUES (1, 'jay', 26, '["\\u5531\\u6b4c", "\\u8db3\\u7403"]');

如果text() 创建原始SQL文本语句,使用参数占位符 :name, :age, :hobby,bindparams() 将实际值绑定到SQL语句中的占位符,dialect=sqlalchemy.dialects.mysql.dialect() 指定使用MySQL方言。使用这种生成也不需要考虑特殊字符转义的问题。


http://www.kler.cn/a/464327.html

相关文章:

  • 联发科MTK6771/MT6771安卓核心板规格参数介绍
  • 渗透测试-非寻常漏洞案例
  • Appium 2.0:移动自动化测试的革新之旅
  • 游戏如何检测iOS越狱
  • overleaf写学术论文常用语法+注意事项+审阅修订
  • 【工具进阶】使用 Nmap 进行有效的服务和漏洞扫描
  • Windows11 安卓子系统存储位置更改
  • 论文分享—供应链不安全:软件物料清单(SBOM)解决方案中缺乏完整性保护
  • Linux中sed命令的使用技巧
  • 计算机毕业设计hadoop+spark+hive民宿推荐系统 酒店推荐系统 民宿价格预测 酒店价格 预测 机器学习 深度学习 Python爬虫 HDFS集群
  • httpx.AsyncClient报错ProxyError: 504 Gateway Time-out
  • [CTF/网络安全] 攻防世界 Web_php_unserialize 解题详析
  • [算法] [leetcode-349] 两个数组的交集
  • [网络安全] DVWA之CSRF攻击姿势及解题详析合集
  • SAP SD学习笔记23 - 无偿出荷(免费交货)与继续无偿出荷(继续免费交货)
  • OpenCV-Python实战(15)——像素直方图均衡画
  • stm32 智能语音电梯系统
  • [AHK]用大模型写ahk脚本
  • Android Camera压力测试工具
  • 《代码随想录》Day23打卡!
  • Wonder Dynamics技术浅析(四):表情捕捉与面部动画
  • 服务器systemctl命令使用与go项目zero框架中实战
  • android.enableJetifier=true的作用:V4包的类自动编程成了androidx包的类,实现androidx的向下兼容
  • SpringMVC(1)——SpringMVC配置和基本原理
  • VMware安装配置
  • 远程医疗系统如何有效防护CC攻击