from django.db import connection
from django.db import transaction
from django.db.utils import (IntegrityError,OperationalError,ProgrammingError,DataError
)
from django.utils import timezoneclass Db(object):"""数据库操作工具类,封装了CRUD、批量操作、事务和软删除功能数据表必须要有:updated_at-更新时间created_at-创建时间is_deleted-软删除标志 0为删除,1已删除deleted_at-删除时间"""# ------------------------------# 核心查询方法# ------------------------------def execute_query(self, sql, params=None, fetchone=False, return_last_id=False):"""执行SQL查询:param sql: SQL语句:param params: 查询参数(元组):param fetchone: 是否只返回第一条记录(SELECT专用):param return_last_id: 是否返回最后插入的ID(INSERT/UPDATE/DELETE专用):return: SELECT返回字典列表/单条字典,其他语句返回受影响行数或最后插入ID"""try:with connection.cursor() as cursor:cursor.execute(sql, params or ())# 打印sql# print(f"{sql}====\n===={params}")if sql.strip().lower().startswith(('select', 'show')):columns = [col[0] for col in cursor.description]results = [dict(zip(columns, row)) for row in cursor.fetchall()]return results[0] if fetchone and results else resultselse:if return_last_id:try:return cursor.lastrowidexcept AttributeError:# 如果数据库后端不支持lastrowid,则返回受影响行数return cursor.rowcountelse:return cursor.rowcountexcept IntegrityError as e:error_msg = f"数据完整性错误(可能原因:主键冲突、唯一约束重复):{str(e)}"print(error_msg)raise ValueError(error_msg) from eexcept OperationalError as e:error_msg = f"数据库连接/操作失败(可能原因:数据库未启动、网络中断):{str(e)}"print(error_msg)raise ConnectionError(error_msg) from eexcept ProgrammingError as e:error_msg = f"SQL语法/表结构错误(可能原因:表/字段不存在、SQL拼写错误):{str(e)}"print(error_msg)raise SyntaxError(error_msg) from eexcept DataError as e:error_msg = f"数据格式错误(可能原因:类型不匹配、长度超限):{str(e)}"print(error_msg)raise TypeError(error_msg) from eexcept Exception as e:error_msg = f"意外错误:{str(e)}"print(error_msg)raise# ------------------------------# 插入操作# ------------------------------def insert_data(self, table, data, auto_time=True, return_last_id=True):"""插入单条数据:param table: 表名字符串:param data: 数据字典,格式 {字段名: 值}:param auto_time: 是否自动添加时间字段(默认True):param return_last_id: 是否返回最后插入的ID:return: 最后插入的ID或受影响的行数"""fields = list(data.keys())values = list(data.values())if auto_time:now = timezone.now()fields.extend(['created_at', 'updated_at'])values.extend([now, now])placeholders = ', '.join(['%s'] * len(fields))sql = f"INSERT INTO {table} ({', '.join(fields)}) VALUES ({placeholders})"return self.execute_query(sql, values, return_last_id=return_last_id)def batch_insert(self, table, data_list, auto_time=True, batch_size=1000):"""批量插入数据(自动分批次):param table: 表名字符串:param data_list: 数据字典列表,格式 [{字段名: 值}, ...]:param auto_time: 是否自动添加时间字段(默认True):param batch_size: 每批次处理的记录数(默认1000):return: 总共插入的行数"""if not data_list:return 0total_rows = 0total_batches = (len(data_list) + batch_size - 1) // batch_sizefor i in range(total_batches):start = i * batch_sizeend = start + batch_sizebatch_data = data_list[start:end]first_item = batch_data[0].copy()fields = list(first_item.keys())if auto_time:now = timezone.now()fields.extend(['created_at', 'updated_at'])for item in batch_data:item['created_at'] = nowitem['updated_at'] = nowplaceholders = ', '.join(['%s'] * len(fields))value_groups = [tuple(item.values()) for item in batch_data]flat_values = [val for group in value_groups for val in group]sql = f"INSERT INTO {table} ({', '.join(fields)}) VALUES "sql += ', '.join([f"({placeholders})"] * len(batch_data))rows = self.execute_query(sql, flat_values)total_rows += rowsreturn total_rows# ------------------------------# 更新操作# ------------------------------def update_data(self, table, data, where, params=None, auto_time=True, return_last_id=False):"""更新数据:param table: 表名字符串:param data: 要更新的数据字典,格式 {字段名: 值}:param where: WHERE条件(不带WHERE关键字),例如 "id = %s":param params: WHERE条件的参数列表:param auto_time: 是否自动更新updated_at字段(默认True):param return_last_id: 是否返回最后插入的ID(在支持的数据库中可能返回更新的行ID):return: 受影响的行数或最后插入ID"""set_items = []values = list(data.values())if auto_time:data['updated_at'] = timezone.now()set_items = [f"{field} = %s" for field in data.keys()]values = list(data.values())else:set_items = [f"{field} = %s" for field in data.keys()]set_clause = ', '.join(set_items)sql = f"UPDATE {table} SET {set_clause} WHERE {where}"if params:values.extend(params)return self.execute_query(sql, values, return_last_id=return_last_id)def batch_update(self, table, data_list, where_field='id', auto_time=True, batch_size=1000):"""批量更新数据(使用CASE WHEN优化):param table: 表名字符串:param data_list: 数据字典列表,每个字典必须包含where_field字段:param where_field: 用于匹配记录的字段(默认id):param auto_time: 是否自动更新updated_at字段(默认True):param batch_size: 每批次处理的记录数(默认1000):return: 总共更新的行数"""if not data_list:return 0total_rows = 0total_batches = (len(data_list) + batch_size - 1) // batch_sizefor i in range(total_batches):start = i * batch_sizeend = start + batch_sizebatch_data = data_list[start:end]case_clauses = []values = []update_fields = {k for item in batch_data for k in item.keys() if k != where_field}for field in update_fields:case_sql = f"{field} = CASE {where_field} "for item in batch_data:case_sql += f"WHEN %s THEN %s "values.extend([item[where_field], item[field]])case_sql += "END"case_clauses.append(case_sql)where_ids = [item[where_field] for item in batch_data]values.extend(where_ids)if auto_time:now = timezone.now()case_clauses.append(f"updated_at = %s")values.append(now)set_clause = ', '.join(case_clauses)where_placeholders = ', '.join(['%s'] * len(where_ids))sql = f"UPDATE {table} SET {set_clause} WHERE {where_field} IN ({where_placeholders})"rows = self.execute_query(sql, values)total_rows += rowsreturn total_rows# ------------------------------# 删除/软删除操作# ------------------------------def soft_delete(self, table, where, params=None, return_last_id=False):"""软删除数据(标记is_deleted=1):param table: 表名字符串:param where: WHERE条件(不带WHERE关键字),例如 "id = %s":param params: WHERE条件的参数列表:param return_last_id: 是否返回最后插入的ID(在支持的数据库中可能返回删除的行ID):return: 受影响的行数或最后插入ID"""data = {'is_deleted': 1, 'deleted_at': timezone.now()}return self.update_data(table, data, where, params, auto_time=False, return_last_id=return_last_id)def delete_data(self, table, where, params=None, hard_delete=False, return_last_id=False):"""删除数据(默认软删除):param table: 表名字符串:param where: WHERE条件(不带WHERE关键字),例如 "id = %s":param params: WHERE条件的参数列表:param hard_delete: 是否执行硬删除(物理删除):param return_last_id: 是否返回最后插入的ID(在支持的数据库中可能返回删除的行ID):return: 受影响的行数或最后插入ID"""if hard_delete:sql = f"DELETE FROM {table} WHERE {where}"return self.execute_query(sql, params, return_last_id=return_last_id)else:return self.soft_delete(table, where, params, return_last_id=return_last_id)# ------------------------------# 查询操作# ------------------------------def get_list(self, table, where=None, params=None, order_by=None, limit=None, offset=None,with_deleted=False, only_deleted=False, fields=None):"""查询列表数据:param table: 表名字符串:param where: WHERE条件(不带WHERE关键字):param params: WHERE条件的参数列表:param order_by: 排序字段,例如 "created_at DESC":param limit: 返回记录数限制:param offset: 偏移量(用于分页):param with_deleted: 是否包含已删除数据:param only_deleted: 是否只返回已删除数据:param fields: 要返回的字段列表,默认返回所有字段:return: 符合条件的记录列表"""if fields:select_str = ', '.join(fields)else:select_str = '*'conditions = []query_params = []if where:conditions.append(where)if params:query_params.extend(params)if not with_deleted:if only_deleted:conditions.append("is_deleted = 1")else:conditions.append("is_deleted = 0")order_str = f"ORDER BY {order_by}" if order_by else ""limit_str = f"LIMIT {limit}" if limit is not None else ""offset_str = f"OFFSET {offset}" if offset is not None else ""where_clause = " AND ".join(conditions) if conditions else ""where_str = f"WHERE {where_clause}" if where_clause else ""sql = f"SELECT {select_str} FROM {table} {where_str} {order_str} {limit_str} {offset_str}"return self.execute_query(sql, query_params)def get_one(self, table, where, params=None, with_deleted=False, only_deleted=False, fields=None):"""查询单条数据:param table: 表名字符串:param where: WHERE条件(不带WHERE关键字):param params: WHERE条件的参数列表:param with_deleted: 是否包含已删除数据:param only_deleted: 是否只返回已删除数据:param fields: 要返回的字段列表,默认返回所有字段:return: 符合条件的单条记录或None"""return self.get_list(table, where, params,with_deleted=with_deleted,only_deleted=only_deleted,fields=fields,limit=1)def get_count(self, table, where=None, params=None, with_deleted=False, only_deleted=False):"""查询记录总数:param table: 表名字符串:param where: WHERE条件(不带WHERE关键字):param params: WHERE条件的参数列表:param with_deleted: 是否包含已删除数据:param only_deleted: 是否只返回已删除数据:return: 记录总数"""conditions = []query_params = []if where:conditions.append(where)if params:query_params.extend(params)if not with_deleted:if only_deleted:conditions.append("is_deleted = 1")else:conditions.append("is_deleted = 0")where_clause = " AND ".join(conditions) if conditions else ""where_str = f"WHERE {where_clause}" if where_clause else ""sql = f"SELECT COUNT(*) AS count FROM {table} {where_str}"result = self.execute_query(sql, query_params, fetchone=True)return result['count'] if result else 0# ------------------------------# 事务操作# ------------------------------def execute_transaction(self, operations):"""执行一组SQL操作作为事务:param operations: SQL操作列表,格式 [(SQL语句, 参数元组), ...]:return: 每个操作的返回结果列表:raises: 任何操作失败时抛出异常,所有操作回滚"""with transaction.atomic():results = []for idx, (sql, params) in enumerate(operations):try:result = self.execute_query(sql, params)results.append(result)except Exception as e:raise RuntimeError(f"事务中第{idx + 1}条SQL执行失败:{str(e)}") from ereturn results# ------------------------------# 数据恢复# ------------------------------def restore_data(self, table, where, params=None):"""恢复软删除的数据(is_deleted=0):param table: 表名字符串:param where: WHERE条件(不带WHERE关键字),例如 "id = %s":param params: WHERE条件的参数列表:return: 受影响的行数"""data = {'is_deleted': 0, 'deleted_at': None}return self.update_data(table, data, where, params, auto_time=True)
    def get_count(self, table, where=None, params=None, with_deleted=False, only_deleted=False):"""查询记录总数:param table: 表名字符串:param where: WHERE条件(不带WHERE关键字):param params: WHERE条件的参数列表:param with_deleted: 是否包含已删除数据:param only_deleted: 是否只返回已删除数据:return: 记录总数"""conditions = []query_params = []if where:conditions.append(where)if params:query_params.extend(params)# if not with_deleted:#     if only_deleted:#         conditions.append("is_deleted = 1")#     else:#         conditions.append("is_deleted = 0")where_clause = " AND ".join(conditions) if conditions else ""where_str = f"WHERE {where_clause}" if where_clause else ""sql = f"SELECT COUNT(*) AS count FROM {table} {where_str}"result = self.execute_query(sql, query_params, fetchone=True)return result['count'] if result else 0

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/91646.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/91646.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/91646.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FreeRTOS---基础知识2

1. FreeRTOS 调度机制概述FreeRTOS 是一个实时操作系统(RTOS),其核心功能是通过 调度器(Scheduler) 管理多个任务的执行。调度机制决定了 何时切换任务 以及 如何选择下一个运行的任务,以满足实时性、优先级…

Docker安装(精简述版)

1. 安装:Docker 环境(Docker desktop) #Windows架构版本查看,Win R‌ 输入 ‌cmd‌ 打开命令提示符;输入命令‌: bash echo %PROCESSOR_ARCHITECTURE%#安装Docker desktop(安装时勾选 WSL2&am…

Postman-win64-7.3.5-Setup.exe安装教程(附详细步骤+桌面快捷方式设置)​

Postman 是一款超常用的接口调试工具,程序员和测试人员用它来发送网络请求、测试API接口、调试数据交互​ 1. 双击安装包​ 安装包下载地址:https://pan.quark.cn/s/4b2960d60ae9,找到你下的 Postman-win64-7.3.5-Setup.exe 文件&#xff08…

149. Java Lambda 表达式 - Lambda 表达式的序列化

文章目录149. Java Lambda 表达式 - Lambda 表达式的序列化为什么要序列化 Lambda 表达式?Lambda 表达式的序列化规则示例代码:序列化 Lambda 表达式代码解析:Lambda 序列化的限制总结:149. Java Lambda 表达式 - Lambda 表达式的…

颐顿机电携手观远BI数据:以数据驱动决策,领跑先进制造智能化升级

颐顿机电签约观远数据,聚焦财务分析、销售管理等场景,以 BI 数据解决方案推进数据驱动决策,助力先进制造企业提效与竞争力升级。一、合作官宣:颐顿机电 观远数据,开启数据应用新征程浙江颐顿机电有限公司(…

【PHP】几种免费的通过IP获取IP所在地理位置的接口(部分免费部分收费)

目录 一、获取客户端IP地址 二、获取IP所在地理位置接口 1、IP域名归属地查询 2、腾讯地图 - IP定位 3、聚合数据 - IP地址(推荐) 4、高德地图 - IP定位(推荐) 5、360分享计划 - IP查询 6、天聚ip地址查询 7、百度IP地址…

【Excel】制作双重饼图

一、效果话不多说,直接上数据和效果图!(示例软件:WPS Office)类别现金刷卡小计苹果10.005.0015.00荔枝20.0015.0035.00西瓜30.0025.0055.00总计60.0045.00105.00二、步骤(一)制作底图插入饼图&a…

gcc-arm-none-eabi安装后,找不到libgcc.a的拉置

位置在:/usr/lib/gcc/arm-none-eabi/6.3.1/libgcc.a查找方法:arm-none-eabi-gcc --print-libgcc-file-name以前没找到,是因为进错目录:/usr/lib/arm-none-eabi/lib

上证50期权2400是什么意思?

本文主要介绍上证50期权2400是什么意思?“上证50期权2400”通常指上证50ETF期权的某个具体合约代码,其中“2400”是合约代码的一部分,需结合完整代码格式理解其含义。上证50期权2400是什么意思?一、上证50期权合约代码的组成上证5…

发那科机器人P点位置号码自动变更功能为禁用状态

通过改变变量的状态,发那科机器人可以实现,当在程序中进行记录、修改、插入、删除、复制/粘贴包含有P点位置号码的行时,P点位置号码会自动从小到大自动排列,可以实现自动排列,或者点击编辑变更编号也可以下图所示女变量…

什么叫湖仓一体

文章目录概念一、理解湖仓一体:先搞懂“数据湖”和“数据仓库”1. 数据仓库(Data Warehouse)2. 数据湖(Data Lake)3. 传统架构的痛点:“湖”与“仓”的割裂二、湖仓一体的核心特点:融合“湖”与…

网络安全突发事件应急预案方案

最近有要求需要出一个网络安全突发事件应急预案方案,本文仅就应急预案问题提出一点初步思考,意在抛砖引玉,盼各位读者不吝赐教,共同完善对这一领域的认识。一、总则 (一)目的 为有效应对规划建筑设计院企业…

【基于3D Gaussian Splatting的三维重建】保姆级教程 | 环境安装 | 制作-训练-测试自己数据集 | torch | colmap | ffmpeg | 全过程图文by.Akaxi

目录 一.【3DGS环境配置】 1.1 克隆3DGS仓库 1.2 安装Visual Studio 2022 1.2.1 下载Visual Studio 2022 1.2.2 更改环境变量 1.3 创建环境 1.3.1 创建python环境 1.3.2 离线安装torch包 1.3.3 安装依赖包 1.3.4安装子模块 (1)报错解决&…

C#泛型委托讲解

1. 泛型&#xff08;Generics&#xff09; 泛型允许编写类型安全且可重用的代码&#xff0c;避免装箱拆箱操作&#xff0c;提高性能。 泛型类 // 定义泛型类 public class GenericList<T> {private T[] items;private int count;public GenericList(int capacity){items …

【DL学习笔记】DL入门指南

DL入门指南 资料课程 李沐老师 《动手学深度学习》 https://tangshusen.me/Dive-into-DL-PyTorch/李宏毅老师课程 https://speech.ee.ntu.edu.tw/~hylee/ml/2021-spring.php DL入门必掌握知识点 数据处理 &#xff1a; numpy、torch地址处理 &#xff1a; os、pathlib文件处…

在 uni-app 中进行路由跳转前的权限验证(检查用户是否登录)

使用场景&#xff1a; 适用于需要登录才能访问的 uni-app 应用保护需要认证的页面不被未授权用户访问统一处理路由跳转的权限控制 /utils/cookies.js下的部分代码内容&#xff1a; // #ifdef H5 import Cookies from js-cookie // #endif// ums const tokenKey user_center_to…

垃圾收集器ParNewCMS与底层三色标记算法详解

垃圾收集技术详解笔记 1. 分代收集理论 当前虚拟机的垃圾收集采用分代收集算法&#xff0c;根据对象存活周期将内存分为不同代区&#xff0c;以优化回收效率。 核心分区&#xff1a; 新生代&#xff08;Young Generation&#xff09;&#xff1a;对象存活周期短&#xff0c;约9…

全排列(回溯算法)

本文参考代码随想录 给定一个 没有重复 数字的序列&#xff0c;返回其所有可能的全排列。 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 思路 排列是有序的&#xff0c;在排列问题中不需要startIndex&#xff1b;但排列问题需要一个…

在线任意长度大整数计算器

具体请前往&#xff1a;在线大整数计算器--支持超大整数的加减乘除,幂运算/模运算,最大公约数&#xff0c;最小公倍数

AT6668B芯片说明书

这颗北斗专用单芯片解决方案AT6668B&#xff0c;采用射频前端与基带处理一体化设计&#xff0c;集成北斗二号/三号双模B1IB1C信号处理器。通过优化星历解码算法实现秒级卫星锁定&#xff0c;配合硬件加速的干扰监测模块&#xff0c;在电磁环境复杂的应用场景中仍可维持10Hz高频…