一文掌握如何编写可重复执行的SQL

一文掌握如何编写可重复执行的SQL

文章已同步个人博客:一文掌握如何编写可重复执行的SQL

背景

先提出问题,这里的可重复执行是指什么?我们为什么要编写可重复执行的sql?

可重复执行是指一条sql重复多次执行都不会报错,不会因为报错而中断同sql脚本的其它sql语句。
比如如下的建表sql只能执行一次,再次执行就会报错,提示我们example_table 表已存在。

CREATE TABLE `example_table` (`id` INT NOT NULL AUTO_INCREMENT,`name` VARCHAR(100) NOT NULL,`age` INT DEFAULT 0,`email` VARCHAR(200),PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

通常来说项目发版的执行SQL脚本语句是由DDL 和 DML 组成的,如果SQL脚本文件中某个SQL执行异常就会中断整个SQL脚本文件的执行。我们还要根据报错SQL的位置,重新将SQL脚本文件中未执行的SQL摘出来重新整理执行。一旦报错,整个SQL脚本执行过程就变得繁琐起来。

编写可重复执行的SQL,变成了解决这一痛点的利器。当SQL脚本中的SQL语句都是可重复执行的,脚本中某个SQL有问题,直接在当前SQL脚本中就可以修改,我们若需要重新执行,只需要重新执行该SQL脚本就可以。其他已经执行成功的SQL,依然会成功执行,也不会对库表数据造成影响。接下来我们梳理一下各类SQL可重复执行的写法和注意点,本文中的SQL均基于MySql语法。

如何实现

表格列举出编写SQL中常见的sql需求:

SQLSQL类型
创建表DDL
对表新增字段DDL
对表修改字段DDL
对表新增索引DDL
插入一条新记录DML
对表中记录进行更新DML
对表中记录进行删除DML

编写SQL涉及到的Mysql语法和系统表

  1. IF NOT EXISTS
  2. MySql 预处理语句原生语法
  3. 字段表 INFORMATION_SCHEMA.COLUMNS
  4. 索引表 INFORMATION_SCHEMA.STATISTICS
  5. 查询当前数据库名称 SCHEMA()
预处理语句语法介绍

预处理语句(Prepared Statements)是一种将 SQL 查询与其参数分离的机制。与传统的查询方式不同,预处理语句首先会将 SQL 查询进行编译、优化,并将其缓存,随后可以多次执行该查询,而不必每次都重新编译和解析 SQL 语句。每次执行时,预处理语句只需要提供不同的参数即可,这使得它在需要执行多次相同 SQL 查询的场景中具有明显的性能优势。

-- 准备预处理语句
PREPARE stmt FROM 'SELECT name, age FROM users WHERE id = ?';-- 设置参数并执行语句
SET @userId = 1;
EXECUTE stmt USING @userId;-- 释放预处理语句
DEALLOCATE PREPARE stmt;
  • PREPARE 将带有占位符 ? 的 SQL 语句预处理并编译。
  • SET 用于设置查询参数。
  • EXECUTE 执行预处理语句并传递参数。
  • DEALLOCATE PREPARE 释放预处理语句,避免占用资源。

接下来具体说明一下各种sql如何改写为可重复执行的写法。

创建表

原写法:

CREATE TABLE `example_table` (`id` INT NOT NULL AUTO_INCREMENT,`name` VARCHAR(100) NOT NULL,`age` INT DEFAULT 0,`email` VARCHAR(200),PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

创建表可以使用IF NOT EXISTS 语法进行判断,仅当表不存在的时候才会创建表。

可重复执行的写法:

CREATE TABLE IF NOT EXISTS `example_table` (`id` INT NOT NULL AUTO_INCREMENT,`name` VARCHAR(100) NOT NULL,`age` INT DEFAULT 0,`email` VARCHAR(200),PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
对表新增字段

原写法:

ALTER TABLE example_table ADD COLUMN create_time datetime null comment '创建时间';

我们能不能也判断如果这个表中没有这个字段才执行新增字段,答案是可以的。在这里就要用到 MySql 预处理语句的语法了。

判断,如果在当前数据库中,存在当前这个表,表中没有这个字段,那么才会执行新增该字段。

  • INFORMATION_SCHEMA.COLUMNS 系统级的字段表,记录了全部的字段信息
  • SCHEMA() 当前数据库名称

可重复执行的写法:

set @sql = 'select 1 from dual;';
select ' ALTER TABLE example_table add COLUMN create_time datetime NULL comment ''创建时间'' ;' into @sql
from dual where (select count(1) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=SCHEMA() AND TABLE_NAME='example_table' AND COLUMN_NAME='sort')=0;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
对表修改字段

原写法:

ALTER TABLE example_table MODIFY COLUMN email VARCHAR(500) DEFAULT '' comment '邮箱';

同样使用 MySql 预处理语句的语法,判断在当前数据库中,存在这个表,且有这个字段,那么才会执行修改字段的语句。

可重复执行的写法:

set @sql = 'select 1 from dual;';
select ' ALTER TABLE example_table MODIFY COLUMN email VARCHAR(500) DEFAULT '''' comment ''邮箱'' ;' into @sql
from dual where (select count(1) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=SCHEMA() AND TABLE_NAME='example_table' AND COLUMN_NAME='email')=1;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
对表新增索引

原写法:

ALTER TABLE example_table add index idx_name (name) COMMENT '名称索引';

要判断当前数据库中,这个表中,根据索引名查询,未查到该索引就进行添加索引。

  • INFORMATION_SCHEMA.STATISTICS 系统级的索引表,记录了全部的索引信息

可重复执行的写法:

set @sql = 'select 1 from dual;';
select 'ALTER TABLE example_table add index idx_name (name) COMMENT ''名称索引'';' into @sql from dual
where (select count(1) FROM INFORMATION_SCHEMA.STATISTICS where TABLE_SCHEMA=SCHEMA() and TABLE_NAME='example_table' and index_name='idx_name')=0;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
插入一条新记录

原写法:

insert into example_table(name, age, email, create_time) VALUE ('jack', 18, 'jackaaa@gmail.com', now());

在这里我们判断如果这个表中没有jack这个name,才进行插入记录。使用DUAL虚拟表帮助我们添加判断条件。

可重复执行的写法:

INSERT INTO example_table
(name, age, email, create_time)
SELECT 'jack', 18, 'jackaaa@gmail.com', now()
FROM DUAL
WHERE NOT EXISTS (select id from example_table where name = 'jack');
对表中记录进行更新

update 语句因为其天生的幂等特质,不需要改写,就支持可重复执行。

update example_table set age = 20 where name = 'jack';
对表中记录进行删除

delete 语句因为其天生的幂等特质,不需要改写,就支持可重复执行。

delete from example_table where name = 'tom';

总结

至此,SQL脚本中常见的7类SQL写法如何改写为可重复执行的SQL,就整理完成了。可重复执行的SQL脚本不仅在执行时提供了便利,也为项目迁移,项目本地化部署带来了便利。

参考

  1. mysql性能优化-预处理语句(Prepared Statements)

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

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

相关文章

C语言-结构体内存大小

#include <stdio.h> #include <string.h> struct S1 { char a;//1 int b;//4 char c;//1 }; //分析 默认对齐数 成员对齐数 对齐数(前两个最小值) 最大对齐数 // 8 1 …

直流电源如何输出恒压源和恒流源

输出电流达到预定值时&#xff0c;变成稳流特性。 输出电压达到预定值时&#xff0c;变成稳压特性。 电流变大&#xff0c;成稳压。 电压变大&#xff0c;成稳流。

【软考高级】系统架构设计师复习笔记-精华版

文章目录 前言0 系统架构设计师0.1 考架构还是考系分0.2 架构核心知识0.3 架构教材变化 1 计算机操作系统1.1 cpu 组成1.2 内核的五大功能1.3 流水线技术1.4 段页式存储1.5 I/O 软件1.6 文件管理1.7 系统工程相关 2 嵌入式2.1 嵌入式技术2.2 板级支持包&#xff08;BSP&#xf…

如何识别钓鱼邮件和诈骗网站?(附网络安全意识培训PPT资料)

识别钓鱼邮件和诈骗网站是网络安全中的一个重要环节。以下是一些识别钓鱼邮件和诈骗网站的方法&#xff1a; 识别钓鱼邮件&#xff1a; 检查发件人地址&#xff1a; 仔细查看发件人的电子邮件地址&#xff0c;看是否与官方域名一致。 检查邮件内容&#xff1a; 留意邮件中是否…

查询 MySQL 默认的存储引擎(SELECT @@default_storage_engine;)

要查询 MySQL 默认的存储引擎&#xff0c;可以使用以下 SQL 查询语句&#xff1a; SELECT default_storage_engine;解释&#xff1a; SELECT: 表示你要执行一个查询。default_storage_engine: 这是一个 MySQL 系统变量&#xff0c;它存储着当前 MySQL 服务器的默认存储引擎。…

ROM修改进阶教程------修改刷机包init.rc 自启用户自定义脚本的一些基本操作 代码格式与注意事项

在很多定制化固件中。我们需要修改系统的rc文件来启动自己的一些脚本。但有时候修改会不起作用,其具体原因在于权限与代码格式的问题。博文将系统的解析代码操作编写的注意事项与各种权限分别。了解以上. 轻松编写自定义启动脚本. 通过博文了解💝💝💝 1-------💝💝…

openwrt 负载均衡方法 openwrt负载均衡本地源接口

openwrt 负载均衡方法 openwrt负载均衡本地源接口_mob6454cc647bdb的技术博客_51CTO博客 本人注重原理分析&#xff0c;要求对其原理掌握&#xff0c;否则按教程操作&#xff0c;你怕是什么都学不会&#xff0c;仔细看&#xff0c;认真记比较好。 首先确认一下基本细节 1、路由…

InnoDB引擎的内存结构

InnoDB擅长处理事务&#xff0c;具有自动崩溃恢复的特性 架构图&#xff1a; 由4部分组成&#xff1a; 1.Buffer Pool&#xff1a;缓冲池&#xff0c;缓存表数据和索引数据&#xff0c;减少磁盘I/O操作&#xff0c;提升效率 2.change Buffer&#xff1a;写缓冲区&#xff0c…

从 GitLab.com 到 JihuLab.com 的迁移指南

本文分享从 GitLab.com 到 JihuLab.com 的迁移指南。 近期&#xff0c;GitLab Inc. 针对其 SaaS 产品做了限制&#xff0c;如果被判定为国内用户&#xff0c;则会建议使用其在国内的发布版本极狐GitLab。从 GitLab SaaS 产品&#xff08;GitLab.com&#xff09;迁移到极狐GitL…

基于STM32F103控制L298N驱动两相四线步进电机

文章目录 前言一、模块参数二、接口说明三、准备工作四、直流电机驱动引脚接线效果展示 五、两相四线步进电机驱动步进电机相关概念拍数驱动时序引脚接线效果展示 六、参考示例 前言 L298N 是一种常见的双 H 桥电机驱动模块&#xff0c;广泛用于驱动直流电机和步进电机。它基于…

【赵渝强老师】MongoDB逻辑存储结构

MongoDB的逻辑存储结构是一种层次结构&#xff0c;主要包括了三个部分&#xff0c;即&#xff1a;数据库&#xff08;Database&#xff09;、集合&#xff08;Collection&#xff0c;也可以叫做表&#xff09;和文档&#xff08;Document&#xff0c;也可以叫做记录&#xff09…

观察者模式和发布-订阅模式有什么异同?它们在哪些情况下会被使用?

大家好&#xff0c;我是锋哥。今天分享关于【观察者模式和发布-订阅模式有什么异同&#xff1f;它们在哪些情况下会被使用&#xff1f;】面试题。希望对大家有帮助&#xff1b; 观察者模式和发布-订阅模式有什么异同&#xff1f;它们在哪些情况下会被使用&#xff1f; 1000道 …

多目标应用(一):多目标麋鹿优化算法(MOEHO)求解10个工程应用,提供完整MATLAB代码

一、麋鹿优化算法 麋鹿优化算法&#xff08;Elephant Herding Optimization&#xff0c;EHO&#xff09;是2024年提出的一种启发式优化算法&#xff0c;该算法的灵感来源于麋鹿群的繁殖过程&#xff0c;包括发情期和产犊期。在发情期&#xff0c;麋鹿群根据公麋鹿之间的争斗分…

Word窗体联动Excel实现级联组合框

在Word中的使用用户窗体&#xff08;UserForm&#xff09;定制界面如下图所示&#xff0c;其中控件如下&#xff08;忽略Label控件&#xff09;&#xff1a; CompanyName 组合框Attention 组合框CommandButton1 按钮 现在需要实现级联组合框效果&#xff0c;即用户在 CompanyN…

浅谈TARA在汽车网络安全中的关键角色

随着现代汽车技术的迅猛发展&#xff0c;网络安全成为汽车行业一个不可忽视的领域。为了应对日益复杂的网络威胁&#xff0c;ISO/SAE 21434标准和UN R155法规提供了系统化的网络安全管理框架。其中&#xff0c;TARA&#xff08;威胁分析与风险评估&#xff09;作为核心方法论&a…

领克Z20结合AI技术,革新自动驾驶辅助系统

眼瞅着&#xff0c;再有不到 5 个星期&#xff0c;春节就要热热闹闹地登场啦&#xff01;对于在外辛苦打拼了一整年的打工人而言&#xff0c;回家过年可不就是这一年里心心念念、最最期盼的高光时刻嘛。这不&#xff0c;这几天各地的高速公路愈发熙熙攘攘起来&#xff0c;川流不…

C语言结构体位定义(位段)的实际作用深入分析

1、结构体位段格式 struct struct_name {type [member_name] : width; };一般定义结构体&#xff0c;成员都是int、char等类型&#xff0c;占用的空间大小是固定的在成员名称后用冒号来指定位宽&#xff0c;可以指定每个成员所占用空间&#xff0c;并且也不用受结构体成员起始…

Android--java实现手机亮度控制

文章目录 1、开发需求2、运行环境3、主要文件4、布局文件信息5、手机界面控制代码6、debug 1、开发需求 需求&#xff1a;开发一个Android apk实现手机亮度控制 2、运行环境 Android studio最新版本 3、主要文件 app\src\main\AndroidManifest.xml app\src\main\res\layou…

Modbus数据网关在制造企业的应用与效果

Modbus是一种广泛应用于工业通信的协议&#xff0c;支持多种设备间的数据交换&#xff0c;如传感器、仪器仪表、PLC、工业机器人、数控机床等。Modbus数据网关则是一种网络通信转换设备&#xff0c;它能够将Modbus协议的数据转换为其他主流协议&#xff08;如MQTT、OPC UA、HTT…

秒鲨后端之MyBatis【2】默认的类型别名、MyBatis的增删改查、idea中设置文件的配置模板、MyBatis获取参数值的两种方式、特殊SQL的执行

别忘了请点个赞收藏关注支持一下博主喵&#xff01;&#xff01;&#xff01;! ! ! 下篇更新&#xff1a; 秒鲨后端之MyBatis【3】自定义映射resultMap、动态SQL、MyBatis的缓存、MyBatis的逆向工程、分页插件。 默认的类型别名 MyBatis的增删改查 添加 <!--int insertUs…