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

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 insertBase = 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 SQLCompilerBase = 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.lryc.cn/news/514349.html

相关文章:

  • [卫星遥感] 解密卫星目标跟踪:挑战与突破的深度剖析
  • I2C(一):存储器模式:stm32作为主机对AT24C02写读数据
  • scrapy 教程
  • 2025元旦源码免费送
  • 高级架构五 设计模式
  • RFID手持机与RFID工业平板在仓储物流管理系统中的选型
  • IoC设计模式详解:控制反转的核心思想
  • 《云原生安全攻防》-- K8s安全配置:CIS安全基准与kube-bench工具
  • LINUX下载编译gtk
  • 基于VSCode软件框架的RISC-V IDE MRS2正式上线发布
  • AWS re:Invent 2024 - Dr. Werner Vogels 主题演讲
  • 前端小案例——520表白信封
  • FPGA随记——过约束
  • 如何利用云计算进行灾难恢复?
  • 【华为OD-E卷 - 九宫格按键输入 100分(python、java、c++、js、c)】
  • 基于AI大模型的医院SOP优化:架构、实践与展望
  • Linux快速入门-一道简单shell编程题目
  • Hive如何创建自定义函数(UDF)?
  • 聊聊前端框架中的process.env,env的来源及优先级(next.js、vue-cli、vite)
  • linux shell脚本 【分支结构case...in 、循环结构、函数】内附练习
  • VSCode 终端显示“pnpm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本”
  • Android ActionBar 技术深度解析
  • matlab-数字滤波器设计与实战
  • JDK的运作原理
  • el-table 实现纵向多级表头
  • Android Studio 下载安装教程(2024 更新版),附详细图文
  • 安全框架:Apache Shiro
  • 泊松融合调研
  • uniapp——App下载文件,打开文档(一)
  • Python 列表的高级索引技巧