MySQL相关知识
总结积累MySQL相关原理和操作。
1. 原理
2. 基本操作
2.1 建库
1 | DROP DATABASE IF EXISTS sampledb; |
2.2 MySQL按行导入text
1 | mysql --local-infile=1 -u root -p |
2.3 设置默认值
The MySQL DEFAULT keyword is a database CONSTRAINT or RULE that is applied when inserting new records into a table. If the value is not provided to any column while inserting a new row in the table, the default value will be used instead. In this article, we will explain the benefits of using MySQL DEFAULT values and show step-by-step applications.
2.3.1 Why use the MySQL DEFAULT value?
- For most of the data types, MySQL provides ‘NULL’ as a DEFAULT value. In the case of Primary Key columns, these cannot contain ‘NULL’ values. In this case, a DEFAULT unique value is a good way to handle this.
- For predefined standards or business rules, we can use DEFAULT values instead of manually specifying the field every time.
- Inserting DATETIME value in a DATE column to identify when the record inserted in a table.
2.3.2 What are the types of DEFAULT values?
Implicit: MySQL automatically sets a default value if not provided.For numeric data types, the default is 0. If a column is declared as an integer and with the AUTO_INCREMENT attribute, the default is the next value in the sequence.
Explicit: We can explicitly set a DEFAULT value when creating or altering a table.
2.3.3 How to set the DEFAULT value in MySQL?
2.3.3.1 Set DEFAULT value on CREATE TABLE
We can set the DEFAULT value for a column while creating a table using the MySQL DEFAULT constraint.
- Syntax:
1 | CREATE TABLE table_name( |
- Example:
1 | CREATE TABLE Employee ( |
The MySQL statement above sets a DEFAULT value for the “Location” column upon creation of the “Employee” table.
2.3.3.2 Set DEFAULT value on ALTER TABLE
We can set the DEFAULT value for a column when the table is already created using MySQL DEFAULT constraint.
- Syntax:
1 | ALTER TABLE |
- Example:
1 | ALTER TABLE |
2.3.3.3 How to DROP a DEFAULT constraint in MySQL?
We can also remove an existing MySQL DEFAULT constraint. To drop a DEFAULT value constraint, we use the SQL statement below.
- Syntax:
1 | ALTER TABLE |
- Example:
1 | ALTER TABLE |
2.3.3.4 How to set DEFAULT values to a VARCHAR column in MySQL
- Step 1: Create a table with “London” as a DEFAULT value for the Location column.
1 | CREATE TABLE Employee ( |
- Step 2: Insert a row into a table without value for the Location column.
1 | INSERT INTO |
- Step 3: Check what is inserted in the table for the Location column.
1 | SELECT |
2.3.3.5 Setting the MySQL DEFAULT value for the Location column.
As we have already set “London” as a DEFAULT value to Location column, we can see
Location = ”London” for the inserted record.
How to set DEFAULT values to a DateTime column in MySQL
- Step 1: CREATE table with setting CURRENT_TIMESTAMP() as DEFAULT value to the Joining_Date column.
1 | CREATE TABLE Employee ( |
- Step 2: Insert a row in to table without a value for the Joining_Date column.
1 | INSERT INTO |
- Step 3: Check what is inserted in the table for the Joining_Date column.
1 | SELECT |
Setting the MySQL DEFAULT value for the Joining_Date column.
As we have already set CURRENT_TIMESTAMP() as the DEFAULT value for the Joining_Date column, we can see a value for Joining_Date. This value represents the CURRENT_TIMESTAMP ( or the TIMESTAMP when we inserted record in the table).
3. 常用SQL
3.1 按照时间统计
3.1.1 按月统计
1 | select |
3.1.2 按天统计
1 | select |
1 | select |
1 | SELECT |
3.1.3 时间格式化
1 | select |
3.2 substring_index的用法
MySQL中一个很好用的截取字符串的函数:substring_index。
3.2.1 用法规则
substring_index(“待截取有用部分的字符串”,“截取数据依据的字符”,截取字符的位置N)
3.2.2 详细说明
首先,设待处理对象字符串为“15,151,152,16”(虽然这里指的不是iP,可以看作是IP来处理吧)
这里截取的依据是逗号:“,”
具体要截取第N个逗号前部分的字符;
意思是:在字符串中以逗号为索引,获取不同索引位的字符。
3.2.2.1 举例
- 取第一个逗号前的字符串 :
root@localhost|iris>SELECT SUBSTRING_INDEX(‘15,151,152,16’,’,’,1);
+————————————————————+
| SUBSTRING_INDEX(‘15,151,152,16’,’,’,1) |
+————————————————————+
| 15 |
+————————————————————+
1 row in set (0.00 sec)
==>得到结果为: 15
- 截取第二个逗号前面部分
root@localhost|iris>SELECT SUBSTRING_INDEX(‘15,151,152,16’,’,’,2);
+————————————————————+
| SUBSTRING_INDEX(‘15,151,152,16’,’,’,2) |
+————————————————————+
| 15,151 |
+————————————————————+
1 row in set (0.00 sec)
==>得到结果为:15,151
N可以为负数,表示倒数第N个索引字符后面的字符串。有负号的时候,可以将整个字符倒过来看,依旧是第N个字符前面的部分。
- 截取目标字符串中最后一个含 “,” 位子的后的部分:
root@localhost|iris>SELECT SUBSTRING_INDEX(‘15,151,152,16’,’,’,-1) as ‘subrting’;
+—————+
| subrting |
+—————+
| 16 |
+—————+
1 row in set (0.00 sec)
==>得到结果为: 16
- 取倒数第2个逗号前那部分字符串里,最后逗号后面的部分
root@localhost|iris>SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(‘15,151,152,16’,’,’,2),’,’,-1) as ‘subrting’;
+—————+
| subrting |
+—————+
| 151 |
+—————+
1 row in set (0.00 sec)
==>得到结果为: 151
- 取倒数第二个逗号后面部分字符串,再去这部分里第一个都号前的部分:
root@localhost|iris>SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(‘15,151,152,16’,’,’,-2),’,’,1) as ‘subrting’;
+—————+
| subrting |
+—————+
| 152 |
+—————+
1 row in set (0.00 sec)
==> 得到结果为:152
原文链接:https://blog.csdn.net/iris_xuting/article/details/38415181
4. 经验总结
4.1 解决逻辑删除与数据库唯一约束冲突
4.1.1 前言
不知道大家有没有遇到这么一种业务场景,在业务中有个唯一约束A,当该业务进行逻辑删除后(设置标记为删除状态),再往唯一约束列插入相同的值时,此时会报Duplicate entry,但在业务上,该值时必须要插入的。今天我们就来聊聊处理这种业务场景的几种思路
4.1.2 解决思路
编号 | 方案 | 备注 |
---|---|---|
1 | 不采用逻辑删除,直接物理删除 | |
2 | 新建历史表 | 主表进行物理删除,同时将删除的记录保存到历史表中 |
3 | 取消表的唯一约束,同时引入redis来保证唯一约束 | 取消表的唯一约束,在项目中引入redis,通过redis来判重,新增时往redis set记录,删除时,删除redis记录 |
4 | 变更删除标记为时间戳 | 将删除状态不以0,1表示,而是以时间戳为值,然后将删除状态为与之前的唯一约束A重新组成唯一联合约束index(A、del_flag),删除时变更del_flag的时间戳 |
5 | 保留删除标记,同时新建一个字段del_unique_key | 保留删除状态位,再新增一个字段del_unique_key,该字段默认值为0,字段类型和大小与主键id保持一致,同时与原先的唯一约束重新组成联合唯一约束index(A,del_unique_key),业务进行逻辑删除,变更del_unique_key的值为该删除行的主键id |
4.1.3 方案的取舍
方案一得从业务的角度上考虑了,如果物理删除,对业务无损,那就无所谓了。方案二等于需要删除的记录的表都需要有历史表,如果仅仅是用来实现记录删除记录,感觉有点大材小用。方案三引入redis,虽然也可以解决问题,但是又额外增加复杂度,同时还得保证redis和数据库的一致性。方案四和方案五其实实现的思路是一样,不过如果已经是在线上跑的业务,还是推荐用第五种方案,毕竟新增字段正常对已有的业务影响相对较小,如果是第四种方案,直接将标志位修改为时间戳,可能还会涉及改业务。如果是新增业务,第四种和第五种方案比较推荐
4.2 事务
**铁律:对代码中的事务是否生效必须加以验证!**4.2.1 开启事务
Spring使用@Transactional注解,需要首先添加启动注解。
1 | (exclude={DataSourceAutoConfiguration.class}) |
4.2.1 事务使用错误和失败场景
编号 | 场景 | 示例 |
---|---|---|
1 | 不要在接口上声明@Transactional ,而要在具体类的方法上使用 @Transactional 注解,否则注解可能无效。 | |
2 | 不要图省事,将@Transactional放置在类级的声明中。放在类声明,会使得所有方法都有事务。故@Transactional应该放在方法级别,不需要使用事务的方法,就不要放置事务,比如查询方法。否则对性能是有影响的。 | |
3 | 使用了@Transactional的方法,对同一个类里面的方法调用, @Transactional无效。比如有一个类Test,它的一个方法A,A再调用Test本类的方法B(不管B是否public还是private),但A没有声明注解事务,而B有。则外部调用A之后,B的事务是不会起作用的。原因是在同一个类之中,方法互相调用,切面无效 ,而不仅仅是事务。这里事务之所以无效,是因为spring的事务是通过aop实现的。 | Spring在扫描Bean的时候会自动为标注了@Transactional注解的类生成一个代理类(proxy),当有注解的方法被调用的时候,实际上是代理类调用的,代理类在调用之前会开启事务,执行事务的操作,但是同类中的方法互相调用,相当于this.B(),此时的B方法并非是代理类调用,而是直接通过原有的Bean直接调用,所以注解会失效。 |
4 | 使用了@Transactional的方法,只能是public,@Transactional注解的方法都是被外部其他类调用才有效,故只能是public。道理和上面的有关联。故在protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错,但事务无效。 | @Transactional注解使用的是AOP,在使用动态代理的时候只能针对public方法进行代理,源码依据在AbstractFallbackTransactionAttributeSource类中的computeTransactionAttribute方法中,如下: |
5 | 如果在加有事务的方法内,使用了try...catch..语句块对异常进行了捕获,而catch语句块没有throw new RuntimeExecption异常,事务也不会回滚。 |