sql语句
1.mysql null值处理
mysql 使用sql select 命令以及where 子句来读取数据表中的数据,但是当提供的查询条件字段为null时,该命令可能无法正常工作。
为了处理这种情况,mysql提供了三大运算符:
- is null:当列的值是NULL,此运算符返回true
- is not null:当列的值不为NULL,运算符返回true
- <=>:比较运算符(不同于 = 运算符),当比较的两个值相等或者都为null时返回true
关于null的条件比较运算是比较特殊的。你不能使用 =NULL 或!=NULL,在列中查找NULL值。
在MySQL中,NULL值与任何其它的值比较(即使是NULL)永远返回NULL,即NULL=NULL返回NULL。
mysql中处理NULL使用IS NULL 和IS NOT NULL运算符。
注意:
mysql> create table test_table_two
-> (
-> countName1 int,
-> countName2 int
-> );
Query OK, 0 rows affected (0.01 sec)
mysql> insert into test_table_two(countName1,countName2) values(1,2);
Query OK, 1 row affected (0.00 sec)
mysql> insert into test_table_two(countName1,countName2) values(1,null);
Query OK, 1 row affected (0.00 sec)
mysql> select *, countName1+ifnull(countName2,0) from test_table_two;
+------------+------------+---------------------------------+
| countName1 | countName2 | countName1+ifnull(countName2,0) |
+------------+------------+---------------------------------+
| 1 | 2 | 3 |
| 1 | NULL | 1 |
+------------+------------+---------------------------------+
2 rows in set (0.00 sec)
columnName1,columnName2为int型时,当columnName2中有null时,columnName1+columnName2=null,ifnull(columnName2,0)把columnName2中null值转为0。
在命令提示符中使用NULL
┌[zhonghua☮zhonghuadeMacBook-Pro.local]-(~)
└> mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.28 MySQL Community Server - GPL
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> create database NullTest;
Query OK, 1 row affected (0.01 sec)
mysql> use NullTest;
Database changed
mysql> create table test_table
-> (
-> name varchar(40) not null,
-> number int
-> );
Query OK, 0 rows affected (0.01 sec)
mysql> insert into test_table(name,number) values ('qiuqiu',20);
Query OK, 1 row affected (0.01 sec)
mysql> insert into test_table(name,number) values ('qiangzi',null);
Query OK, 1 row affected (0.01 sec)
mysql> insert into test_table(name,number) values('google',null);
Query OK, 1 row affected (0.00 sec)
mysql> select * from test_table;
+---------+--------+
| name | number |
+---------+--------+
| qiuqiu | 20 |
| qiangzi | NULL |
| google | NULL |
+---------+--------+
3 rows in set (0.01 sec)
在以下实例中你可以看到 = 和 != 运算符是不起作用的:
mysql> select * from test_table where number=NULL;
Empty set (0.00 sec)
mysql> select * from test_table where number != NULL;
Empty set (0.00 sec)
查找表中的number列是否为NULL,必须使用IS NULL 和 IS NOT NULL,如下:
mysql> select * from test_table where number is null;
+---------+--------+
| name | number |
+---------+--------+
| qiangzi | NULL |
| google | NULL |
+---------+--------+
2 rows in set (0.00 sec)
mysql> select * from test_table where number is not null;
+--------+--------+
| name | number |
+--------+--------+
| qiuqiu | 20 |
+--------+--------+
1 row in set (0.00 sec)
2.order by 关键字
order by 关键字用于对结果集按照一列或者多个列进行排序。
order by 关键字默认按照升序对记录进行排序。如果需要按照降序对记录进行排序,可以desc关键字。
SQL ORDER BY 语法:
SELECT column_name1,column_name2 FROM table_name ORDER BY column_name3 ASC|DESC;
例子:
mysql> select * from websites;
+------+----------+-------+---------+
| id | name | alexa | country |
+------+----------+-------+---------+
| 1 | google | 1 | USA |
| 2 | 淘宝 | 13 | CN |
| 3 | 微博 | 4689 | CN |
| 4 | Facebook | 23 | USA |
+------+----------+-------+---------+
4 rows in set (0.00 sec)
mysql> select * from websites order by alexa;
+------+----------+-------+---------+
| id | name | alexa | country |
+------+----------+-------+---------+
| 1 | google | 1 | USA |
| 2 | 淘宝 | 13 | CN |
| 4 | Facebook | 23 | USA |
| 3 | 微博 | 4689 | CN |
+------+----------+-------+---------+
4 rows in set (0.00 sec)
mysql> select * from websites order by country;
+------+----------+-------+---------+
| id | name | alexa | country |
+------+----------+-------+---------+
| 2 | 淘宝 | 13 | CN |
| 3 | 微博 | 4689 | CN |
| 1 | google | 1 | USA |
| 4 | Facebook | 23 | USA |
+------+----------+-------+---------+
4 rows in set (0.01 sec)
mysql> select * from websites order by country,alexa;
+------+----------+-------+---------+
| id | name | alexa | country |
+------+----------+-------+---------+
| 2 | 淘宝 | 13 | CN |
| 3 | 微博 | 4689 | CN |
| 1 | google | 1 | USA |
| 4 | Facebook | 23 | USA |
+------+----------+-------+---------+
4 rows in set (0.00 sec)
3.select distinct
在表中,一个列可能会包含多个重复值,有时会希望仅仅列出不同(distinct)的值,select distinct 语句用于返回唯一不同的值。
语法:
SELECT DISTINCT column_name1,column_name2 FROM table_name;
例子:
mysql> select * from websites;
+------+----------+-------+---------+
| id | name | alexa | country |
+------+----------+-------+---------+
| 1 | google | 1 | USA |
| 2 | 淘宝 | 13 | CN |
| 3 | 微博 | 4689 | CN |
| 4 | Facebook | 23 | USA |
+------+----------+-------+---------+
4 rows in set (0.00 sec)
mysql> select distinct country from websites;
+---------+
| country |
+---------+
| USA |
| CN |
+---------+
2 rows in set (0.00 sec)
常用SQL语句
1.SQL语句主要分为哪几类?
- 数据定义语言:CREATE、DROP、ALTER 等对逻辑结构等有操作的,其中包括表结构、视图和索引。
- 数据查询语言:SELECT
- 数据操纵语言:INSERT、UPDATE、DELETE
- 数据控制语言:GRANT、REVOKE、COMMIT、ROLLBACK等对数据库完整性有操作的,可以简单理解为权限控制等。
2.超键、候选键、主键、外键分别是什么?
超键:在关系中能唯一的标识元组的属性集称为关系模式的超键。一个属性可以作为一个超键,多个属性组合在一起也可以作为一个超键。超键包含候选键和主键。
候选键:是最小超键,即没有冗余元素的超键
主键:数据库表中对存储数据对象以唯一和完整标识的数据列或属性的组合。一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值(Null)
外键:在一个表中存在的另一个表的主键称为此表的外键
3. SQL约束有哪几种?
- NOT NULL:用于控制字段的内容一定不能为空(NULL)
- UNIQUE:控制字段内容不能重复,一个表允许有多个UNIQUE约束
- PRIMARY KEY:也是用于控制字段内容不能重复,但它在一个表只允许出现一个。
- FOREIGN KEY:用于预防破坏表之间连接的动作,也能防止非法数据插入外键列,因为它必须是它指向的那个表的值之一
- CHECK:用于控制字段的值范围
4.六种关联查询
- 交叉连接:cross join
- 内连接:inner join
- 外连接:left join/right join
- 联合查询:union 与 union all
- 全连接:full join
交叉连接:没有任何关联条件,结果是笛卡尔积,没有意义,很少使用。语法:select * from A,B; -- 等价于 select * from A cross join B;
例如:
mysql> select * from test_table;
+---------+--------+
| name | number |
+---------+--------+
| qiuqiu | 20 |
| qiangzi | NULL |
| google | NULL |
+---------+--------+
3 rows in set (0.01 sec)
mysql> select * from test_table_two;
+------------+------------+
| countName1 | countName2 |
+------------+------------+
| 1 | 2 |
| 1 | NULL |
+------------+------------+
2 rows in set (0.00 sec)
mysql> select * from test_table cross join test_table_two;
+---------+--------+------------+------------+
| name | number | countName1 | countName2 |
+---------+--------+------------+------------+
| google | NULL | 1 | 2 |
| qiangzi | NULL | 1 | 2 |
| qiuqiu | 20 | 1 | 2 |
| google | NULL | 1 | NULL |
| qiangzi | NULL | 1 | NULL |
| qiuqiu | 20 | 1 | NULL |
+---------+--------+------------+------------+
6 rows in set (0.00 sec)
mysql> select * from test_table,test_table_two;
+---------+--------+------------+------------+
| name | number | countName1 | countName2 |
+---------+--------+------------+------------+
| google | NULL | 1 | 2 |
| qiangzi | NULL | 1 | 2 |
| qiuqiu | 20 | 1 | 2 |
| google | NULL | 1 | NULL |
| qiangzi | NULL | 1 | NULL |
| qiuqiu | 20 | 1 | NULL |
+---------+--------+------------+------------+
6 rows in set (0.00 sec)
内连接:
内连接分为三类:
- 等值连接:
ON A.id = B.id
多表中同时符合某种条件的数据记录的集合。如: - 不等值连接:
ON A.id > B.id
- 自连接:
SELECT * FROM A T1 INNER JOIN A T2 ON T1.id = T2.pid
mysql> select * from A;
+--------+------+
| name | id |
+--------+------+
| qingzi | 1 |
| qiuqiu | 2 |
+--------+------+
2 rows in set (0.00 sec)
mysql> select * from B;
+------+------+
| name | id |
+------+------+
| dog | 1 |
| bone | 2 |
| cow | 3 |
+------+------+
3 rows in set (0.00 sec)
mysql> select * from A inner join B on A.id = B.id;
+--------+------+------+------+
| name | id | name | id |
+--------+------+------+------+
| qingzi | 1 | dog | 1 |
| qiuqiu | 2 | bone | 2 |
+--------+------+------+------+
2 rows in set (0.00 sec)
mysql> select * from A join B on A.id = B.id;
+--------+------+------+------+
| name | id | name | id |
+--------+------+------+------+
| qingzi | 1 | dog | 1 |
| qiuqiu | 2 | bone | 2 |
+--------+------+------+------+
2 rows in set (0.00 sec)
外连接(left join/right join)
- 左外连接:left outer join,以左表为主,先查询出左表,按照on后的关联条件匹配右表,没有匹配到用NULL值填充,可以简写left join
- 右外连接:right outer join,以右表为主,先查询出右表,按照on后的关联条件匹配左表,没有匹配到的用NULL填充,可以简写成right join
联合查询(union与union all)
- 联合查询就是把多个结果集集中在一起,union前的结果为基准,需要注意的是联合查询的列数要相等,相同的记录行会合并
- 如果使用union all 不会合并重复的记录行
- union 效率高于 union all
全连接(full join) - MySQL不支持全连接
- left join 和union 和 right join 可以联合使用
mysql> select * from A;
+--------+------+
| name | id |
+--------+------+
| qingzi | 1 |
| qiuqiu | 2 |
+--------+------+
2 rows in set (0.00 sec)
mysql> select * from B;
+------+------+
| name | id |
+------+------+
| dog | 1 |
| bone | 2 |
| cow | 3 |
+------+------+
3 rows in set (0.00 sec)
mysql> select * from A left join B on A.id = B.id union select * from A right join B on A.id = B.id;
+--------+------+------+------+
| name | id | name | id |
+--------+------+------+------+
| qingzi | 1 | dog | 1 |
| qiuqiu | 2 | bone | 2 |
| NULL | NULL | cow | 3 |
+--------+------+------+------+
3 rows in set (0.02 sec)
5.什么是子查询
1.条件:一条SQL语句的查询结果作为另一条查询语句的条件或查询结果。
2.嵌套:多条SQL语句嵌套使用,内部的SQL查询语句成为子查询
6.子查询的三种情况
1.子查询是单行单列的情况:结果集是一个值,父查询使用:=、<、>等运算符
-- 查询工资最高的员工是谁
select * from employee where salary=(select max(salary) from employee);
实例:
mysql> select * from employee;
+--------+------------+------+---------+------+
| salary | join_date | id | dept_id | name |
+--------+------------+------+---------+------+
| 2000 | 2013-09-01 | 1 | 2 | John |
| 6000 | 2020-09-01 | 2 | 2 | Tom |
+--------+------------+------+---------+------+
2 rows in set (0.00 sec)
mysql> select * from employee where salary=(select max(salary) from employee);
+--------+------------+------+---------+------+
| salary | join_date | id | dept_id | name |
+--------+------------+------+---------+------+
| 6000 | 2020-09-01 | 2 | 2 | Tom |
+--------+------------+------+---------+------+
1 row in set (0.01 sec)
2.子查询是多行单列的情况:结果集类似于一个数组,父查询使用:in 运算符
-- 查询工资最高的员工是谁
select * from employee where salary in (select max(salary) from employee);
-- 实例
mysql> select * from employee;
+--------+------------+------+---------+-------+
| salary | join_date | id | dept_id | name |
+--------+------------+------+---------+-------+
| 2000 | 2013-09-01 | 1 | 2 | John |
| 6000 | 2020-09-01 | 2 | 2 | Tom |
| 6000 | 2014-09-01 | 3 | 3 | Marry |
+--------+------------+------+---------+-------+
3 rows in set (0.00 sec)
mysql> select * from employee where salary=(select max(salary) from employee);
+--------+------------+------+---------+-------+
| salary | join_date | id | dept_id | name |
+--------+------------+------+---------+-------+
| 6000 | 2020-09-01 | 2 | 2 | Tom |
| 6000 | 2014-09-01 | 3 | 3 | Marry |
+--------+------------+------+---------+-------+
2 rows in set (0.01 sec)
mysql> select * from employee where salary in (select max(salary) from employee);
+--------+------------+------+---------+-------+
| salary | join_date | id | dept_id | name |
+--------+------------+------+---------+-------+
| 6000 | 2020-09-01 | 2 | 2 | Tom |
| 6000 | 2014-09-01 | 3 | 3 | Marry |
+--------+------------+------+---------+-------+
2 rows in set (0.01 sec)
3.子查询是多行多列的情况:结果集类似于一张虚拟表,不能用于where条件,用于select子句中作为子表
!!! 有问题
-- 1)查询出2011年以后入职的员工信息
-- 2)查询所有的部门数据,与上面的虚拟表中的信息对比,找出所有部门id相等的员工
select * from dept d,(select * from employee where join_date>'2011-01-01') e where e.dept_id=d.id;
-- 使用表连接:
select d.*,e.* from dept d inner join employee e on d.id = e.dept_id where e.join_date>'2011-01-01';
7.mysql中 in 和 exists区别
mysql中的in语句是把外表和内表作hash连接,而exists语句是对外表作loop循环,每次loop循环再对内表进行查询。一直大家都认为exists比in语句的效率要高,这种说法其实是不准确的。这个是要区分环境的。
- 如果查询的两个表大小相当,那么用in和exists差别不大
- 如果两个表中一个较小一个是大表,则子查询表大的用exists,子查询表小的用in.
- not in 和 not exists:如果查询语句中使用了not in,那么内外表都进行全表扫描,没有用到索引;而not exists的子查询依然能用到表上的查询。所以无论哪个表大,用not exists都比用not in 要快。
8. varchar 与 char的区别
char的特点:
- char表示定长字符串,长度是固定的
- 如果插入数据的长度小于char的固定长度时,则用空格填充
- 因为长度固定,所以存取速度要比varchar快很多,甚至能快50%,但正因为其长度固定,所以会占用多余的空间,是空间换时间的做法。
- 对于char来说,最多能存放的字符个数为255,和编码无关。
varchar的特点: - varchar表示可变长字符串,长度是可变的;
- 插入的数据是多长,就按照多长来存储;
- varchar在存取方面与char相反,它存取慢,因为长度不固定,但正因如此,不占据多余的空间,是时间置换空间的做法;
- 对于varchar来说,最多能存放的字符个数为65532
!!! 不是65535吗
总之,结合性能角度(char更快)和节省磁盘空间角度(varchar更小),具体情况还需具体来设计数据库才是最妥当的。
9.varchar(50)中50的含义
最多存放50个字符,varchar(50)和varchar(200)存储hello多占空间一样,但是后者在排序时会消耗更多的内存。因为order by col采用fixed_length计算col长度(memory引擎也一样)。
10.int(20) 中20的含义
是指显示字符的长度。20表示最大显示宽度为20,但仍占4字节存储,存储范围不变;不影响内部存储,只是影响带zerofill定义的int时,前面补多少个0,易于报表展示;对大多数应用没有意义,只是规定一些工具来显示自负的。
11.mysql 中int(10)和char(10)以及varchar(10)的区别
- int(10)的10表示显示的数据的长度,不是存储的大小;char(10)和varchar(10)的10 表示存储数据的大小,即表示存储多少字符。
int(10):10位的数据长度9999999999,占32个字节,int型4位
char(10):10位固定字符串,不足补空格,最多10个字符
varchar(10):10位可变字符串,不补空格,最多10个字符 - char(10)表示存储定长的10个字符,不足10个就用空格补齐,占用更多的存储空间
- varchar(10):表示存储变长的10个字符,存储多少个就是多少个,空格也按一个字符存储,这一点是和char(10)的空格不同的,char(10)的空格表示占位,不算一个字符。
12.float 和double的区别
- float 类型数据可以存储至多8位十进制数,并在内存占4字节。
- double类型数据可以存储至多18位十进制数,并在内存中占8字节。
13.drop、delete与truncate的区别
三者都表示删除,但是三者有一些差别:
drop | delete | truncate | |
---|---|---|---|
类型 | 属于DDL | 属于DML | 属于DDL |
回滚 | 不可回滚 | 可回滚 | 不可回滚 |
删除内容 | 从数据库中删除表,所有的数据行,索引和权限也会被删除 | 表结构还在,删除表的全部或者一部分数据行 | 表结构还在,删除表中所有数据 |
删除速度 | 删除速度最快 | 删除速度慢,需要逐行删除 | 删除速度快 |
因此,在不再需要一张表时,用drop;在想删除部分数据行时候,用delete;在保留表而删除所有数据的时候用trancate |
14.union 与union all的区别?
- 如果使用union all,不会合并重复的记录行
- union的效率高于union all
15.基本语句
1.创建数据库
create database 数据库名;
eg:
mysql> create database zhtest;
Query OK, 1 row affected (0.04 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sakila |
| sys |
| world |
| zhtest |
+--------------------+
7 rows in set (0.00 sec)
或者
create database if not exists zhtest2 default charset utf8;
该命令的作用:
- 如果数据库库不存在则创建,存在则不创建
- 创建zhtest2数据库,并设定编码集为utf8
2.删除数据库
drop database 数据库名;
eg:
mysql> drop database zhtest;
Query OK, 0 rows affected (0.14 sec)
3.选择数据库
use 数据库名;
eg:
mysql> use zhtest2
Database changed
4.创建表
create table 表名 (列名 列的数据类型);
eg:
mysql> create table tb1(
-> id int unsigned auto_increment,
-> title varchar(100) not null,
-> author varchar(100) not null,
-> submit_date date,
-> primary key(id)
-> )engine= innodb default charset=utf8;
Query OK, 0 rows affected, 1 warning (0.56 sec)
注:
- auto_increment:定义列为自增的属性,一般用于主键,数值会自动加一
- primary key 关键字用于定义列为主键,可以使用多列来定义主键,列间以逗号分隔。
- engine 设置存储引擎,charset设置编码
结果:
mysql> select * from tb1;
+----+--------+--------+-------------+
| id | title | author | submit_date |
+----+--------+--------+-------------+
| 1 | C++ | John | 2022-09-05 |
| 2 | Python | May | 2022-09-05 |
+----+--------+--------+-------------+
2 rows in set (0.00 sec)
5.删除数据表
- 删除表内数据,用delete
delete from 表名 where 删除条件;
eg:
mysql> delete from tb1 where author = "John";
Query OK, 1 row affected (0.18 sec)
mysql> select * from tb1;
+----+--------+--------+-------------+
| id | title | author | submit_date |
+----+--------+--------+-------------+
| 2 | Python | May | 2022-09-05 |
+----+--------+--------+-------------+
1 row in set (0.00 sec)
- 清除表内数据,保存表结构用 truncate
truncate table 表名;
eg:
mysql> truncate table tb1;
Query OK, 0 rows affected (0.22 sec)
mysql> select * from tb1;
Empty set (0.00 sec)
- 删除表,啥都没有了,用drop
drop table 表名;
eg:
mysql> drop table tb1;
Query OK, 0 rows affected (0.17 sec)
mysql> select * from tb1;
ERROR 1146 (42S02): Table 'zhtest2.tb1' doesn't exist
注意:
- delete 是DML,操作完后如果没有提交事务,可以回滚;truncate 和drop 是DDL,操作完马上生效,不能回滚。
- 执行速度上:drop>truncate>delete
6.插入数据
单条数据:
insert into 表名(列1,列2,列3...) values(val1,val2,val3);
多条数据:
insert into 表名(col1,col2,col3) values (valA1,valA2,valA3),(valB1,valB2,valB3),(valC1,valC2,valC3);
注意:
添加数据的时候可以规定列进行添加,如果所有的列都要添加数据可以不规定列添加数据。
eg:
mysql> insert into tb1(title,author,submit_date) values ("Python","John","2022-09-05");
Query OK, 1 row affected (0.13 sec)
mysql> insert into tb1(title,author,submit_date) values ("C++","May","2022-09-06"),("Java","Sara",now());
Query OK, 2 rows affected, 1 warning (0.13 sec)
Records: 2 Duplicates: 0 Warnings: 1
mysql> select * from tb1;
+----+--------+--------+-------------+
| id | title | author | submit_date |
+----+--------+--------+-------------+
| 1 | Python | John | 2022-09-05 |
| 2 | C++ | May | 2022-09-06 |
| 3 | Java | Sara | 2022-09-05 |
+----+--------+--------+-------------+
3 rows in set (0.00 sec)
mysql> insert into tb1 values(6,"Go","Dog","2033-01-23");
Query OK, 1 row affected (0.12 sec)
mysql> select * from tb1;
+----+--------+--------+-------------+
| id | title | author | submit_date |
+----+--------+--------+-------------+
| 1 | Python | John | 2022-09-05 |
| 2 | C++ | May | 2022-09-06 |
| 3 | Java | Sara | 2022-09-05 |
| 6 | Go | Dog | 2033-01-23 |
+----+--------+--------+-------------+
4 rows in set (0.00 sec)
7.查询数据
select column_name,column_name
from table_name
[where clause]
[limit n][offset m]
注:
-
查询语句中可以使用一个或者多个表,表之间用逗号分隔,并使用where语句来设定查询条件。
-
可以使用where语句来包含任何条件
-
limit n:返回n条记录。
-
offset m:跳过m条记录。默认偏移量为0
-
limit m,n:相当于limit n offset m,从第m条记录开始,返回n条记录;limit n = limit 0,n。用其实现分页
select * from book limit pagesize offset (pagenum-1)*pagesize
-
where 子句
select field1,field2,..fieldn
from table1,table2..
where condition1 [and/or] condition2...
注意:
- 查询语句中可以使用一张或者多张表,表之间用,分隔,并使用where语句来设定查询条件。
- 可以在where子句中指定任何条件
- 可以使用and/or指定一个或者多个条件
- where子句也可以运用于sql的delete或者update命令
- ’可用操作符:
= 、<>、!=、>=、<=
- mysql 的where 子句的字符串比较不区分大小写。可以用binary 关键字来设定where子句字符串的比较区分大小写。
eg:
mysql> select * from tb1 where title='go';
+----+-------+--------+-------------+
| id | title | author | submit_date |
+----+-------+--------+-------------+
| 6 | Go | Dog | 2033-01-23 |
| 7 | go | duck | 2022-09-06 |
+----+-------+--------+-------------+
2 rows in set (0.00 sec)
mysql> select * from tb1 where binary title = 'Go';
+----+-------+--------+-------------+
| id | title | author | submit_date |
+----+-------+--------+-------------+
| 6 | Go | Dog | 2033-01-23 |
+----+-------+--------+-------------+
1 row in set, 1 warning (0.10 sec)
7.update 更新
update 表名 set field1=new-value1,field2=new-value2
[where Clause]
注意:
- 可以同时更新一个或者多个字段
- 可以在where字句中指定任何条件
- 可以在一个单独表中同时更新数据
eg:
mysql> update tb1 set title="学习Python" where id =2;
Query OK, 1 row affected (0.20 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from tb1;
+----+------------+--------+-------------+
| id | title | author | submit_date |
+----+------------+--------+-------------+
| 1 | Python | John | 2022-09-05 |
| 2 | 学习Python | May | 2022-09-06 |
| 3 | Java | Sara | 2022-09-05 |
| 6 | Go | Dog | 2033-01-23 |
+----+------------+--------+-------------+
4 rows in set (0.00 sec)
当需要将字段中的特定字符串批量修改为其他字符串时:
update table_name set field = replace(field,'old-string','new-string')
[where Clause] 不能加!!!!!
eg:
mysql> select * from tb1;
+----+------------+--------+-------------+
| id | title | author | submit_date |
+----+------------+--------+-------------+
| 1 | Python | John | 2022-09-05 |
| 2 | 学习Python | May | 2022-09-06 |
| 3 | Java | Sara | 2022-09-05 |
| 6 | Go | Dog | 2033-01-23 |
+----+------------+--------+-------------+
4 rows in set (0.00 sec)
mysql> update tbl set title = replace(title,'Python','C++') where id = 1;
ERROR 1146 (42S02): Table 'zhtest2.tbl' doesn't exist
mysql> select * from tb1;
+----+------------+--------+-------------+
| id | title | author | submit_date |
+----+------------+--------+-------------+
| 1 | Python | John | 2022-09-05 |
| 2 | 学习Python | May | 2022-09-06 |
| 3 | Java | Sara | 2022-09-05 |
| 6 | Go | Dog | 2033-01-23 |
+----+------------+--------+-------------+
4 rows in set (0.00 sec)
mysql> update tbl set title = replace(title,'Python','C++') where id=1;
ERROR 1146 (42S02): Table 'zhtest2.tbl' doesn't exist
mysql> update tb1 set title = replace(title,'Python','C++');
Query OK, 2 rows affected (0.19 sec)
Rows matched: 4 Changed: 2 Warnings: 0
mysql> select * from tb1;
+----+---------+--------+-------------+
| id | title | author | submit_date |
+----+---------+--------+-------------+
| 1 | C++ | John | 2022-09-05 |
| 2 | 学习C++ | May | 2022-09-06 |
| 3 | Java | Sara | 2022-09-05 |
| 6 | Go | Dog | 2033-01-23 |
+----+---------+--------+-------------+
4 rows in set (0.00 sec)
8.like 子句
SQL LIKE子句中使用%字符来表示任意字符,如果没有使用%,like子句与=的效果是一样的。
select field1,field2,field3,..
from table_name
where field1 like condition1 [and/or] field2 = 'somevalue'
注意:
- 可以在where子句中使用like子句
- 可以使用like子句代替=
- like通常与%一起使用,类似于一个元字符的搜索
- 可以使用and/or指定一个或者多个条件
- 可以在delete或update命令中使用where…like子句来指定条件
mysql> select * from tb1 where author like '%g';
+----+-------+--------+-------------+
| id | title | author | submit_date |
+----+-------+--------+-------------+
| 6 | Go | Dog | 2033-01-23 |
+----+-------+--------+-------------+
1 row in set (0.10 sec)
sql 提供的四种匹配方式:
% | 表示任意0个或多个字符。可匹配任意类型和长度的字符,有些情况下若是中文,使用两个百分号(%%)表示 |
_ | 表示任意单个字符。匹配任意单个字符,通常用来限制表达式的字符长度语句 |
[] | 表示括号内所列字符中的一个(类似正则表达式)。指定一个字符、字符串或范围,要求匹配对象为他们中的任一个 |
[^] | 表示不在括号所列之内的单个字符。其取值和[]相同,但它要求所匹配对象为指定字符以外的任一字符 |
!!! |
注:
查询内容包含通配符时,由于通配符的缘故,导致我们查询特殊字符"%“,”_“,”[“语句的无法正常实现,而把特殊字符用”[]"括起来便可正常查询。
eg:
!!!
mysql> select * from tb1 where title like '%o';
+----+-------+--------+-------------+
| id | title | author | submit_date |
+----+-------+--------+-------------+
| 6 | Go | Dog | 2033-01-23 |
| 7 | go | duck | 2022-09-06 |
| 8 | goo | dck | 2022-09-06 |
| 9 | ogoo | apple | 2016-06-08 |
+----+-------+--------+-------------+
4 rows in set (0.00 sec)
mysql> select * from tb1 where title like '_o';
+----+-------+--------+-------------+
| id | title | author | submit_date |
+----+-------+--------+-------------+
| 6 | Go | Dog | 2033-01-23 |
| 7 | go | duck | 2022-09-06 |
+----+-------+--------+-------------+
2 rows in set (0.00 sec)
mysql> select * from tb1 where title like 'g%';
+----+-------+--------+-------------+
| id | title | author | submit_date |
+----+-------+--------+-------------+
| 6 | Go | Dog | 2033-01-23 |
| 7 | go | duck | 2022-09-06 |
| 8 | goo | dck | 2022-09-06 |
+----+-------+--------+-------------+
3 rows in set (0.00 sec)
mysql> select * from tb1 where binary title like 'g_';
+----+-------+--------+-------------+
| id | title | author | submit_date |
+----+-------+--------+-------------+
| 7 | go | duck | 2022-09-06 |
+----+-------+--------+-------------+
1 row in set, 1 warning (0.00 sec)
9.union操作符
mysql中的union操作用于连接两个以上的select语句的结果到一个结果集合中,多个select语句会删除重复的数据。
select col1,col2,col3,...coln
from table1
where conditions
union [all|distinct]
select col1,col2,col3..coln
from table2
where conditions;
注:
distinct :可选,删除结果中重复的数据。默认情况下union操作符已经删除了重复数据,所以distinct修饰符对结果没啥影响。
all:可选,返回所有结果,包含重复数据
eg:
mysql> select * from teacher;
+-------+---------+
| name | country |
+-------+---------+
| Amry | CN |
| March | USA |
+-------+---------+
2 rows in set (0.00 sec)
mysql> select * from student;
+-----------+---------+----------+
| name | country | hobby |
+-----------+---------+----------+
| Febraury | CN | swimming |
| October | USA | singing |
| September | Janpa | running |
+-----------+---------+----------+
3 rows in set (0.00 sec)
mysql> select country
-> from teacher
-> union
-> select country
-> from student;
+---------+
| country |
+---------+
| CN |
| USA |
| Janpa |
+---------+
3 rows in set (0.11 sec)
mysql> select country
-> from teacher
-> union all
-> select country
-> from student;
+---------+
| country |
+---------+
| CN |
| USA |
| CN |
| USA |
| Janpa |
+---------+
5 rows in set (0.00 sec)
10.order by排序
如果需要对读取的数据进行排序,就可以使用mysql的order by 子句设定按哪个字段哪种方式进行排序,再返回搜索结果。
select field1,field2,...fieldn
from table1,table2,table3...
order by field1 [ASE[DESC][默认ASE]],[field2...]
注:
- 可使用任何字段作为排序的条件,从而返回排序后的查询结果。
- 可以设定多个字段来排序。
- 可以使用ASC 或 DESC 关键字来设置查询结果是升序或降序。默认情况下,按升序。
- 可添加where…like子句来设置条件
mysql> select * from tb1 order by submit_date;
+----+---------+--------+-------------+
| id | title | author | submit_date |
+----+---------+--------+-------------+
| 9 | ogoo | apple | 2016-06-08 |
| 1 | C++ | John | 2022-09-05 |
| 3 | Java | Sara | 2022-09-05 |
| 2 | 学习C++ | May | 2022-09-06 |
| 7 | go | duck | 2022-09-06 |
| 8 | goo | dck | 2022-09-06 |
| 6 | Go | Dog | 2033-01-23 |
+----+---------+--------+-------------+
7 rows in set (0.00 sec)
mysql> select * from tb1 order by submit_date desc;
+----+---------+--------+-------------+
| id | title | author | submit_date |
+----+---------+--------+-------------+
| 6 | Go | Dog | 2033-01-23 |
| 2 | 学习C++ | May | 2022-09-06 |
| 7 | go | duck | 2022-09-06 |
| 8 | goo | dck | 2022-09-06 |
| 1 | C++ | John | 2022-09-05 |
| 3 | Java | Sara | 2022-09-05 |
| 9 | ogoo | apple | 2016-06-08 |
+----+---------+--------+-------------+
7 rows in set (0.00 sec)
mysql>
注:
mysql 汉子字段按拼音排序:
如果字符集采用的是gbk(汉字编码字符集),直接在查询语句后添加order,egselect * from teacher order by country
;
如果字符集采用的是utf(万国码),需要先对字段进行转码然后排序,eg:select * from teacher order by convert(teacher using gbk);
eg:
mysql> select * from pinyin order by hanzi;
+--------+----+
| hanzi | id |
+--------+----+
| 中国 | 1 |
| 安哥拉 | 3 |
| 韩国 | 2 |
+--------+----+
3 rows in set (0.09 sec)
mysql> select * from pinyin order by convert(hanzi using gbk);
+--------+----+
| hanzi | id |
+--------+----+
| 安哥拉 | 3 |
| 韩国 | 2 |
| 中国 | 1 |
+--------+----+
3 rows in set (0.07 sec)
11.group by 语句
根据一个或者多个列对结果集进行分组。在分组的列上可以使用count,sum,avg等函数。
select col1,function(col2),..
from table_name
where col operator value
group by col;
eg:
1.创建表,并插入数据
use zhtest2;
create table if not exists employee_tb1(
id int not null,
user_name varchar(30) not null default '',
riqi datetime not null,
signin tinyint not null default '0' comment '登录次数',
primary key(id)
)engine= InnoDB;
insert into employee_tb1 values ('1', '小明', '2016-04-22 15:25:33', '1'),('2', '小王', '2016-04-20 15:25:47', '3'), ('3', '小丽', '2016-04-19 15:26:02', '2'), ('4', '小王', '2016-04-07 15:26:14', '4'), ('5', '小明', '2016-04-11 15:26:40', '4'), ('6', '小明', '2016-04-04 15:26:54', '2');
mysql> select * from employee_tb1;
+----+-----------+---------------------+--------+
| id | user_name | riqi | signin |
+----+-----------+---------------------+--------+
| 1 | 小明 | 2016-04-02 15:25:33 | 1 |
| 2 | 小王 | 2016-04-20 15:25:47 | 3 |
| 3 | 小丽 | 2016-04-19 15:26:02 | 2 |
| 4 | 小王 | 2016-04-07 15:26:14 | 4 |
| 5 | 小明 | 2016-04-11 15:26:40 | 4 |
| 6 | 小明 | 2016-04-04 15:26:54 | 2 |
+----+-----------+---------------------+--------+
6 rows in set (0.00 sec)
2.使用group by 将数据按照名字分组,并统计每个人有多少条记录。
mysql> select user_name,count(*) from employee_tb1 group by user_name;
+-----------+----------+
| user_name | count(*) |
+-----------+----------+
| 小明 | 3 |
| 小王 | 2 |
| 小丽 | 1 |
+-----------+----------+
3 rows in set (0.00 sec)
3.with rollup 可以实现在分组统计数据的基础上在进相应的统计(sum,avg,count…)
eg: 将以上数据表按名字进行分组,再统计每个人登录的次数
mysql> select user_name,sum(signin) as signin_count from employee_tb1 group by user_name with rollup;
+-----------+--------------+
| user_name | signin_count |
+-----------+--------------+
| 小丽 | 2 |
| 小明 | 7 |
| 小王 | 7 |
| NULL | 16 |
+-----------+--------------+
4 rows in set (0.00 sec)
记录NULL表示所有人的登录次数。可以使用coalesce(a,b,c)来设置取代null 的名字。
select coalesce(a,b,c);
参数说明:如果anull,则选择b,如果bnull,则选择c,如果a!=null,则选择a,如果a,b,c都为null,则返回null(没意义)。
mysql> select coalesce(user_name,'总数'),sum(signin) as signin_count from employee_tb1 group by user_name with rollup;
+----------------------------+--------------+
| coalesce(user_name,'总数') | signin_count |
+----------------------------+--------------+
| 小丽 | 2 |
| 小明 | 7 |
| 小王 | 7 |
| 总数 | 16 |
+----------------------------+--------------+
4 rows in set (0.00 sec)
12.join 连接的使用
inner join(内连接,或等值连接) | 获取两个表中字段匹配关系的记录 |
left join(左连接) | 获取左表所有记录,即使右表没有对应匹配的记录 |
right join(右连接) | 与left join相反。 |
mysql> select * from runoob_tb1;
+-----------+-----------+---------------+-----------------+
| runoob_id | title | runoob_author | submission_date |
+-----------+-----------+---------------+-----------------+
| 1 | 学习php | google | 2017-04-12 |
| 2 | 学习mysql | edge | 2018-05-17 |
+-----------+-----------+---------------+-----------------+
2 rows in set (0.00 sec)
mysql> select * from tcount_tb1;
+---------------+--------------+
| runoob_author | runoob_count |
+---------------+--------------+
| edge | 15 |
| firefox | 20 |
| google | 22 |
+---------------+--------------+
3 rows in set (0.00 sec)
mysql> select a.runoob_id,a.runoob_author,b.runoob_count from runoob_tb1 a inner join tcount_tb1 ona.runoob_author = b.runoob_author;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.runoob_author = b.runoob_author' at line 1
mysql> select a.runoob_id,a.runoob_author,b.runoob_count from runoob_tb1 a inner join tcount_tb1 b on a.runoob_author = b.runoob_author;
+-----------+---------------+--------------+
| runoob_id | runoob_author | runoob_count |
+-----------+---------------+--------------+
| 1 | google | 22 |
| 2 | edge | 15 |
+-----------+---------------+--------------+
2 rows in set (0.00 sec)
mysql> select a.runoob_id,a.runoob_author,b.runoob_count from runoob_tb1 a,tcount_tb1 b where a.runoob_author = b.runoob_author;
+-----------+---------------+--------------+
| runoob_id | runoob_author | runoob_count |
+-----------+---------------+--------------+
| 1 | google | 22 |
| 2 | edge | 15 |
+-----------+---------------+--------------+
2 rows in set (0.00 sec)
mysql> select a.runoob_id,a.runoob_author,b.runoob_count from runoob_tb1 a left join tcount_tb1 b on a.runoob_author = b.runoob_author;
+-----------+---------------+--------------+
| runoob_id | runoob_author | runoob_count |
+-----------+---------------+--------------+
| 1 | google | 22 |
| 2 | edge | 15 |
+-----------+---------------+--------------+
2 rows in set (0.00 sec)
mysql> select a.runoob_id,a.runoob_author,b.runoob_count from runoob_tb1 a right join tcount_tb1 b on a.runoob_author = b.runoob_author;
+-----------+---------------+--------------+
| runoob_id | runoob_author | runoob_count |
+-----------+---------------+--------------+
| 2 | edge | 15 |
| NULL | NULL | 20 |
| 1 | google | 22 |
+-----------+---------------+--------------+
3 rows in set (0.00 sec)
13.null值处理
mysql中使用select 命令和where 子句来读取数据表中的数据,当提供的查询条件字段为null时,该命令可能无法正常工作。
为了出来这种情况mysql提供了三大运算符:
is null | 当列的值为null,此运算符返回true |
is not null | 当列的值不为null,运算符返回true |
<=> | 比较运算符(不同于=运算符),当比较的两个值相等或者都为null时返回true |
关于null的条件运算是比较特殊的。不能使用=null 或者!=null在列中查找null值。 | |
在mysql中,null值与任何其他值的比较(即使是null)永远返回null,即null =null返回null。 | |
在mysql中处理null使用is null 和 is not null 运算符。 | |
注意: |
select * from col1+ifnull(col2,0) from tab1;
col1,col2为int型,当col2中,有值为null时,col1+col2=null, ifnull(col2,0)把col2中null值转换为0
eg:
mysql> create table tb3(
-> author char(50) not null,
-> id int auto_increment,
-> num int,
-> primary key(id)
-> );
Query OK, 0 rows affected (0.65 sec)
mysql> insert into tb3(author,num) values('A',33),('B',null),('C',55),('D',56);
Query OK, 4 rows affected (0.12 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from tb3;
+--------+----+------+
| author | id | num |
+--------+----+------+
| A | 1 | 33 |
| B | 2 | NULL |
| C | 3 | 55 |
| D | 4 | 56 |
+--------+----+------+
4 rows in set (0.00 sec)
mysql> select * from tb3 where num=null;
Empty set (0.00 sec)
mysql> select * from tb3 where num is null;
+--------+----+------+
| author | id | num |
+--------+----+------+
| B | 2 | NULL |
+--------+----+------+
1 row in set (0.00 sec)
mysql> select * from tb3 where num is not null;
+--------+----+------+
| author | id | num |
+--------+----+------+
| A | 1 | 33 |
| C | 3 | 55 |
| D | 4 | 56 |
+--------+----+------+
3 rows in set (0.00 sec)
14.mysql 正则表达式
!!!!!!!
15.事务
mysql事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,删除一个人员,既需要删除人员的基本资粮,也要删除和该人相关的信息,如信箱、文章等等,这样这些数据库操作就构成一个事务。
- 在mysql中只有使用了Innodb数据库引擎的数据库或表才支持事务;
- 事务处理可以用来维护数据库的完整性,保证成批的数据库语句要么全部执行,要么完全不执行。
- 事务用来管理insert、update、delete语句。
一般来说,事务必须满足四个条件:ACID 。即原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)
- 原子性:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,就会回滚到事务开始前的状态,就像这个事务从来没有执行过一样。
- 一致性:事务开始之前和事务结束之后,数据库的完整性没有被破坏。这表示写入的资料完全符合所有的预设规则,这包括资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 隔离性:数据库允许多个并发事务同时对数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read) 和串行化(Serializable)
- 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
在Mysql命令行的默认设置下,事务都是自动提交的,即执行SQL语句后就会马上执行jCOMMIT操作。因此要显式地开启一个事务必须使用命令BEGIN或START TRANSACTIOIN,或者执行命令SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交
事务控制语句
- begin 或start transaction 显式地开启一个事务
- commit 也可以使用 commit work,不过二者是等价的。commit 会提交事务,并使已对数据库进行的 所有修改都成为永久性的。
- rollback 也可以使用rollback work,二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改
- savepoint identifier,savepoint允许在事务中创建一个保存点,一个事务中可以有多个savepoint;
- release savepoint identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常
- rollback to identifier 把事务回滚到标记点
- set transaction 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有:read uncommitted、read committed、repeatable read、serializable
mysql 处理事务主要有两种方法
1.用begin、rollback、commit 来实现
- begin 开始一个事务
- rollback 事务回滚
- commit 事务确认
2.直接用set来改变mysql的自动提交模式:
- set autocommit=0 禁止自动提交
- set autocommit =1 开启自动提交
mysql> create table transaction_test(id int)engine=innodb;
Query OK, 0 rows affected (0.21 sec)
mysql> select * from transaction_test;
Empty set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into transaction_test values(5);
Query OK, 1 row affected (0.00 sec)
mysql>
mysql> insert into transaction_test values(6);
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.14 sec)
mysql> select * from transaction_test;
+------+
| id |
+------+
| 5 |
| 6 |
+------+
2 rows in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into transaction_test values(7);
Query OK, 1 row affected (0.00 sec)
mysql> select * from transaction_test;
+------+
| id |
+------+
| 5 |
| 6 |
| 7 |
+------+
3 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.10 sec)
mysql> select * from transaction_test;
+------+
| id |
+------+
| 5 |
| 6 |
+------+
2 rows in set (0.00 sec)
savepoint 是在数据库事务处理中实现了"子事务",也称嵌套事务的方法。事务可以回滚到savepoint而不影响创建前的变化,不要放弃整个事务。
rollback 回滚的用法可以设置保留点savepoint,执行多条操作时,回滚到想要的那条语句之前。
用法:
1.使用savepoint:
savepoint savepoint_name; // 声明一个savepoint
rollback to savepoint_name; //回滚到savepoint
2.删除savepoint
保留点在事务处理完成后(执行一条rollback或commit)后自动释放。
mysql5以来,可以用release savepoint savepoint_name; //删除指定保留点
16.alter命令
当我们需要修改数据表名或者修改数据表字段时,就需要使用mysql的alter命令。
1.删除、添加或修改表字段
mysql> create table alter_test(
-> i int,
-> c char(1)
-> );
Query OK, 0 rows affected (0.19 sec)
mysql> show columns from alter_test;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| i | int | YES | | NULL | |
| c | char(1) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.01 sec)
//使用alter命令及drop子句来删除以上创建表的i字段。如果数据表中只剩下一个字段,则无法使用drop来删除字段。
mysql> alter table alter_test drop i;
Query OK, 0 rows affected (0.19 sec)
mysql> show columns from alter_test;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| c | char(1) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)
//mysql 中使用add子句来向数据表中添加列,如下实例在表中添加i字段,并定义数据类型 注意:执行以上命令后,i字段会自动添加到数据表字段的末尾
mysql> alter table alter_test add i int;
Query OK, 0 rows affected (0.17 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show columns from alter_test;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| c | char(1) | YES | | NULL | |
| i | int | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
//如果需要指定新增字段的位置,可使用first关键字(设定位于第一列),alter 字段名(设定位于某个字段之后)。注:first 和 after关键字可用于add 与modify子句,所以如果你想重置数据表字段的位置就需要先用drop删除字段然后使用add来添加字段并设置位置。
mysql> alter table alter_test add d varchar(50) first;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show columns from alter_test;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| d | varchar(50) | YES | | NULL | |
| c | char(1) | YES | | NULL | |
| i | int | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> alter table alter_test add e blob after c;
Query OK, 0 rows affected (0.12 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show columns from alter_test;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| d | varchar(50) | YES | | NULL | |
| c | char(1) | YES | | NULL | |
| e | blob | YES | | NULL | |
| i | int | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
2.修改字段类型及名称
如果想要修改字段类型及名称,可以在alter命令中使用modify或change子句
mysql> show columns from alter_test;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| d | varchar(50) | YES | | NULL | |
| c | char(1) | YES | | NULL | |
| e | blob | YES | | NULL | |
| i | int | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> alter table alter_test modify c char(10);
Query OK, 0 rows affected (0.50 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show columns from alter_test;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| d | varchar(50) | YES | | NULL | |
| c | char(10) | YES | | NULL | |
| e | blob | YES | | NULL | |
| i | int | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
//使用change子句,语法和modify 有很大区别。在change关键字之后,紧跟的是你要修改的字段名,然后指定新的字段名及类型。
mysql> alter table alter_test change i j bigint;
Query OK, 0 rows affected (0.22 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show columns from alter_test;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| d | varchar(50) | YES | | NULL | |
| c | char(10) | YES | | NULL | |
| e | blob | YES | | NULL | |
| j | bigint | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> alter table alter_test change j j int;
Query OK, 0 rows affected (0.32 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show columns from alter_test;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| d | varchar(50) | YES | | NULL | |
| c | char(10) | YES | | NULL | |
| e | blob | YES | | NULL | |
| j | int | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
alter table对null值和默认值的影响
// 当你修改字段时,可以指定是否包含空值或者是否设置默认值,如果你不设置默认值,mysql会自动设置该字段默认值为null
mysql> alter table alter_test modify j bigint not null default 100;
Query OK, 0 rows affected (0.16 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show columns from alter_test;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| d | varchar(50) | YES | | NULL | |
| c | char(10) | YES | | NULL | |
| e | blob | YES | | NULL | |
| j | bigint | NO | | 100 | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
修改字段默认值
mysql> alter table alter_test alter c set default 'G';
Query OK, 0 rows affected (0.07 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show columns from alter_test;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| d | varchar(50) | YES | | NULL | |
| c | char(10) | YES | | G | |
| e | blob | YES | | NULL | |
| j | bigint | NO | | 100 | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
//可以使用alter 命令及drop 子句来删除字段的默认值
mysql> alter table alter_test alter j drop default;
Query OK, 0 rows affected (0.20 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show columns from alter_test;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| d | varchar(50) | YES | | NULL | |
| c | char(10) | YES | | G | |
| e | blob | YES | | NULL | |
| j | bigint | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
//可以使用alter 修改存储引擎
mysql> show table status like 'alter_test'\G
*************************** 1. row ***************************
Name: alter_test
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 0
Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2022-09-07 17:17:38
Update_time: NULL
Check_time: NULL
Collation: utf8mb3_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.05 sec)
mysql> alter table alter_test engine='myisam';
Query OK, 0 rows affected (0.24 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show table status like 'alter_test'\G
*************************** 1. row ***************************
Name: alter_test
Engine: MyISAM
Version: 10
Row_format: Dynamic
Rows: 0
Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2022-09-07 17:20:19
Update_time: NULL
Check_time: NULL
Collation: utf8mb3_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
修改表名
如果需要修改数据表的名称,可以在alter table语句中使用rename子句来实现
mysql> alter table alter_test rename to alter_test2;
Query OK, 0 rows affected (0.20 sec)
删除外键约束
alter table tableName drop foreign key keyName;
16 索引
- 索引的建立对于数据库的高效运行非常重要,可以大大提高检索速度。类似于字典中的目录。
- 索引分为单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。
- 创建索引时,需要确保该索引是where子句的条件。实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。
- 缺点:虽然索引大大提高了查询速度,同时会降低更新表的速度,如对表进行insert、update 和delete。因为更新表时,Mysql不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。
普通索引
(1)创建索引
如果是char、varchar类型,length可以小于字段实际长度;如果是blob和text类型,必须指定length
create index index_name on table_name(col_name)
eg:
mysql> select * from student;
+-----------+---------+----------+
| name | country | hobby |
+-----------+---------+----------+
| Febraury | CN | swimming |
| October | USA | singing |
| September | Janpa | running |
+-----------+---------+----------+
3 rows in set (0.03 sec)
mysql> create index index_test on student (name);
Query OK, 0 rows affected (0.87 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from student\G
*************************** 1. row ***************************
Table: student
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: name
Collation: A
Cardinality: 3
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
*************************** 2. row ***************************
Table: student
Non_unique: 1
Key_name: index_test
Seq_in_index: 1
Column_name: name
Collation: A
Cardinality: 3
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
2 rows in set (0.16 sec)
(2)修改表结构(添加索引)
alter table tableName add index indexName(col_name)
eg:
mysql> alter table student add index index_test2 (hobby);
Query OK, 0 rows affected (0.21 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from student\G;
*************************** 1. row ***************************
Table: student
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: name
Collation: A
Cardinality: 3
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
*************************** 2. row ***************************
Table: student
Non_unique: 1
Key_name: index_test
Seq_in_index: 1
Column_name: name
Collation: A
Cardinality: 3
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
*************************** 3. row ***************************
Table: student
Non_unique: 1
Key_name: index_test2
Seq_in_index: 1
Column_name: hobby
Collation: A
Cardinality: 3
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
3 rows in set (0.00 sec)
(3)创建表的时候直接指定
mysql> create table mytable(
-> id int not null,
-> username varchar(16) not null,
-> index index_test (username)
-> );
Query OK, 0 rows affected (0.22 sec)
mysql> show index from mytable\G;
*************************** 1. row ***************************
Table: mytable
Non_unique: 1
Key_name: index_test
Seq_in_index: 1
Column_name: username
Collation: A
Cardinality: 0
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
1 row in set (0.11 sec)
ERROR:
No query specified
(4)删除索引的语法
drop index [indexName] on tableName;
eg:
mysql> drop index index_test on mytable;
Query OK, 0 rows affected (0.14 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from mytable\G;
Empty set (0.00 sec)
唯一索引
它与前面的普通索引类似,不同就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
(1)创建索引
mysql> select * from teacher;
+-------+---------+
| name | country |
+-------+---------+
| Amry | CN |
| March | USA |
+-------+---------+
2 rows in set (0.00 sec)
mysql> create unique index index_test on teacher(name);
Query OK, 0 rows affected (0.24 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from teacher\G;
*************************** 1. row ***************************
Table: teacher
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: name
Collation: A
Cardinality: 2
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
*************************** 2. row ***************************
Table: teacher
Non_unique: 0
Key_name: index_test
Seq_in_index: 1
Column_name: name
Collation: A
Cardinality: 2
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
2 rows in set (0.10 sec)
(2)修改表结构
mysql> alter table teacher add unique index index_test2 (country);
Query OK, 0 rows affected (0.40 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from teacher\G;
*************************** 1. row ***************************
Table: teacher
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: name
Collation: A
Cardinality: 2
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
*************************** 2. row ***************************
Table: teacher
Non_unique: 0
Key_name: index_test
Seq_in_index: 1
Column_name: name
Collation: A
Cardinality: 2
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
*************************** 3. row ***************************
Table: teacher
Non_unique: 0
Key_name: index_test2
Seq_in_index: 1
Column_name: country
Collation: A
Cardinality: 2
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
3 rows in set (0.01 sec)
ERROR:
No query specified
(3)创建表的时候直接指定
mysql> create table mytable(
-> id int not null,
-> username varchar(16) not null,
-> unique index_test (username)
-> );
Query OK, 0 rows affected (0.18 sec)
mysql> show index from mytable\G;
*************************** 1. row ***************************
Table: mytable
Non_unique: 0
Key_name: index_test
Seq_in_index: 1
Column_name: username
Collation: A
Cardinality: 0
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
1 row in set (0.11 sec)
使用alter命令添加和删除索引
有四种方式来添加数据表的索引:
alter table tb_name add primary key(col_name)
:该语句添加一个主键,这意味着索引值必须是唯一的,且不能为null。alter table tb_name add unique index_name(col_name)
:这条语句创建索引的值必须是唯一的(除了null外,null可能会出现多次)alter table tb_name add index index_name(col_name)
:添加普通索引,索引值可出现多次。alter table tb_name add fulltext index_name(col_name)
:该语句指定了索引为fulltext,用于全文索引。
使用alter命令添加和删除主键
主键作用于一个列上(可以一个列或多个列联合主键),添加主键索引时,要确保主键默认不为空(not null)
mysql> alter table mytable modify id int not null;
Query OK, 0 rows affected (0.06 sec)
mysql> alter table mytable add primary key(id);
Query OK, 0 rows affected (0.31 sec)
mysql> show columns from mytable;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| username | varchar(16) | NO | UNI | NULL | |
+----------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
//可以使用alter命令删除主键,注意:删除主键时只需要指定primary key,但在删除索引时,必须知道索引名
mysql> alter table mytable drop primary key;
Query OK, 0 rows affected (0.23 sec)
mysql> show columns from mytable;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id | int | NO | | NULL | |
| username | varchar(16) | NO | PRI | NULL | |
+----------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
显式索引信息
可以使用show index
命令来列出表中相关的索引信息。可以通过添加\G
来格式化输出信息。
show index from table_name\G;
18 临时表
临时表在我们需要保存一些临时数据时非常有用,临时表只在当前连接可见,当关闭连接,mysql会删除表并释放所有的空间。如果使用了其他mysql客户端程序连接mysql数据库服务来创建临时表,那么只有在关闭客户端程序时才会销毁临时表,也可手动销毁。
创建临时表在创建和插入数据时基本没有区别,只是在创建时加一个temporary
mysql> create temporary table saleSummary(
-> product_name varchar(50) not null,
-> total_sale decimal(12,2) not null default 0.00,
-> avg_unit_price decimal(7,2) not null default 0.00
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> insert into saleSummary(product_name,total_sale,avg_unit_price) values('cucumber',100.25,80);
Query OK, 1 row affected (0.10 sec)
mysql> select * from saleSummary;
+--------------+------------+----------------+
| product_name | total_sale | avg_unit_price |
+--------------+------------+----------------+
| cucumber | 100.25 | 80.00 |
+--------------+------------+----------------+
1 row in set (0.00 sec)
当使用show tables命令显式数据表列表时,无法看到saleSummary表。当你退出当前mysql会话,再使用select命令来读取原先创建的临时表数据,你就会发现没有该表的存在,因为在你退出时该临时表已经被销毁了。
删除临时表
默认情况下,当断开与数据库的连接后,临时表就会自动被销毁。也可在当前mysql会话使用drop table 命令来手动删除临时表。
用查询直接创建临时表的方式:
create temporary table 临时表名 as(
select * from 旧的临时表名
limit 0,10
);
eg:
mysql> create temporary table temporary_test as(
-> select * from teacher
-> limit 0,10
-> );
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from temporary_test;
+-------+---------+
| name | country |
+-------+---------+
| Amry | CN |
| March | USA |
+-------+---------+
2 rows in set (0.00 sec)
19 复制表
如果我们需要完全的复制MySQL的数据表,包括表的结构、索引、默认值等。有两种方法:
方法一:
步骤如下:
- 使用
show create table
命令获取创建数据表(create table)语句,该语句包含了元数据表的结构、索引等。 - 复制以下命令显示的SQL语句,修改数据表名,并执行SQL语句,通过以上命令将完全的复制数据表结构。
- 如果你想复制表的内容,可使用
insert into...select
语句来实现。
eg:
mysql> create database zhtest;
Query OK, 1 row affected (0.04 sec)
mysql> use zhtest;
Database changed
mysql> create table test_clone_table(
-> id int not null auto_increment,
-> title varchar(100) not null default '',
-> author varchar(40) not null default '',
-> submission_date date default null
-> primary key(id),
-> unique key 'AUTHOR_INDEX'(author)
-> )engine=InnoDB;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(id),
unique key 'AUTHOR_INDEX'(author)
)engine=InnoDB' at line 6
mysql> create table test_clone_table(
-> id int not null auto_increment,
-> title varchar(100) not null default '',
-> author varchar(40) not null default '',
-> submission_date date default null,
-> primary key(id),
-> unique key AUTHOR_INDEX (author)
-> )engine=InnoDB;
Query OK, 0 rows affected (0.67 sec)
mysql> insert into test_clone_table(title,author,submission_date) values('C++','John','2020-08-09');
Query OK, 1 row affected (0.26 sec)
mysql> select * from test_clone_table;
+----+-------+--------+-----------------+
| id | title | author | submission_date |
+----+-------+--------+-----------------+
| 1 | C++ | John | 2020-08-09 |
+----+-------+--------+-----------------+
1 row in set (0.00 sec)
// 1.获取表的完整结构
mysql> show create table test_clone_table\G;
*************************** 1. row ***************************
Table: test_clone_table
Create Table: CREATE TABLE `test_clone_table` (
`id` int NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL DEFAULT '',
`author` varchar(40) NOT NULL DEFAULT '',
`submission_date` date DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `AUTHOR_INDEX` (`author`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.11 sec)
ERROR:
No query specified
// 2.修改SQL语句的数据表名,并执行SQL语句
mysql> create table clone_tb1(
-> id int not null auto_increment,
-> author varchar(40) not null default '',
-> title varchar(100) not null default '',
-> submission_date date default null,
-> primary key(id),
-> UNIQUE KEY AUTHOR_INDEX (author)
-> );
Query OK, 0 rows affected (0.23 sec)
// 3.执行完步骤二后,将在数据库中创建新的克隆表clone_tb1.如果想拷贝数据可以使用insert into ... select 语句实现
mysql> insert into clone_tb1(id,
-> author,
-> title,
-> submission_date)
-> select id,author,title,submission_date
-> from test_clone_table;
Query OK, 1 row affected (0.04 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from clone_tb1;
+----+--------+-------+-----------------+
| id | author | title | submission_date |
+----+--------+-------+-----------------+
| 1 | John | C++ | 2020-08-09 |
+----+--------+-------+-----------------+
1 row in set (0.00 sec)
//执行完上述步骤后,会完整的复制表的内容,包括表结构及表数据。
方法二:完整复制表
mysql> create table clone_tb2 like test_clone_table;
Query OK, 0 rows affected (0.60 sec)
mysql> insert into clone_tb2 select * from test_clone_table;
Query OK, 1 row affected (0.11 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from clone_tb2;
+----+-------+--------+-----------------+
| id | title | author | submission_date |
+----+-------+--------+-----------------+
| 1 | C++ | John | 2020-08-09 |
+----+-------+--------+-----------------+
1 row in set (0.00 sec)
方法三:
(1)可以拷贝一个表中其中的一些字段
mysql> create table clone_tb3 as(
-> select id,author,title
-> from test_clone_table);
Query OK, 1 row affected (0.20 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> show columns from clone_tb3;
+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| id | int | NO | | 0 | |
| author | varchar(40) | NO | | | |
| title | varchar(100) | NO | | | |
+--------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
(2)将新建的表的字段改名
mysql> create table clone_tb4 as(
-> select id,author as ath,title as timu
-> from test_clone_table);
Query OK, 1 row affected (0.21 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> show columns from clone_tb4;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int | NO | | 0 | |
| ath | varchar(40) | NO | | | |
| timu | varchar(100) | NO | | | |
+-------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
注意:
最简单的两种方式:
//第一种:只复制表结构到新表
create table 新表 like 旧表;
或者
create table 新表 select * from 旧表 where 1=2;
// 第二种:复制表结构及数据到新表
create table 新表 select * from 旧表
21 序列使用
mysql 序列是一组整数:1,2,3…由于一张数据表只能有一个字段自增主键,如果你想实现其他字段也实现自动增加,可以使用mysql序列来实现。
(1)使用auto_increment
mysql 中最简单使用序列的方法就是mysql auto_increment来定义序列。
mysql> create table insect(
-> id int not null auto_increment,
-> name varchar(30) not null,
-> date date not null,
-> origin varchar(30) not null,
-> primary key(id)
-> );
Query OK, 0 rows affected (0.81 sec)
mysql> insert into insect(id,name,date,origin) values(null,'housefly','2001-09-10','kitchen'),(null,'millipede','2001-09-10','driveway');
Query OK, 1 row affected (0.19 sec)
mysql> select * from insect group by id;
+----+-----------+------------+----------+
| id | name | date | origin |
+----+-----------+------------+----------+
| 1 | housefly | 2001-09-10 | kitchen |
| 2 | millipede | 2001-09-10 | driveway |
+----+-----------+------------+----------+
2 rows in set (0.00 sec)
(2) 重置序列
如果你删除了数据表中的多条记录,并希望对剩下数据的auto_increment列进行重新排列,那么可以通过删除自增的列,然后重新添加来实现。该操作要非常小心,如果在删除的同时又有新的记录添加,有可能会出现数据混乱。
mysql> select * from insect;
+----+-----------+------------+------------+
| id | name | date | origin |
+----+-----------+------------+------------+
| 1 | housefly | 2001-09-10 | kitchen |
| 2 | millipede | 2001-09-10 | driveway |
| 3 | anyone | 2021-09-10 | front yard |
+----+-----------+------------+------------+
3 rows in set (0.00 sec)
mysql> delete from insect where id='2';
Query OK, 1 row affected (0.17 sec)
mysql> select * from insect;
+----+----------+------------+------------+
| id | name | date | origin |
+----+----------+------------+------------+
| 1 | housefly | 2001-09-10 | kitchen |
| 3 | anyone | 2021-09-10 | front yard |
+----+----------+------------+------------+
2 rows in set (0.00 sec)
mysql> alter table insect drop id;
Query OK, 2 rows affected (0.56 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> alter table insect
-> add id int not null auto_increment first,
-> add primary key(id);
Query OK, 0 rows affected (0.64 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select * from insect;
+----+----------+------------+------------+
| id | name | date | origin |
+----+----------+------------+------------+
| 1 | housefly | 2001-09-10 | kitchen |
| 2 | anyone | 2021-09-10 | front yard |
+----+----------+------------+------------+
2 rows in set (0.00 sec)
(3)设置序列的开始值
一般情况下序列的开始值为1,但如果你需要指定一个开始值为100
mysql> create table insect(
-> id int not null auto_increment,
-> primary key(id),
-> name varchar(30) not null,
-> date date not null,
-> origin varchar(30) not null
-> )engine=InnoDB auto_increment = 100 charset = utf8;
Query OK, 0 rows affected, 1 warning (0.27 sec)
mysql> insert into insect(id,name,date,origin) values(null,'qiuqiu','2022-9-10','google');
Query OK, 1 row affected (0.14 sec)
mysql> select * from insect;
+-----+--------+------------+--------+
| id | name | date | origin |
+-----+--------+------------+--------+
| 100 | qiuqiu | 2022-09-10 | google |
+-----+--------+------------+--------+
1 row in set (0.00 sec)
22 处理重复数据
有些mysql数据表中可能存在重复数据,有些情况我们允许重复数据的存在,有时候我们也要删除这些重复的数据。
1.防止表中出现重复数据
可以在mysql 数据表中设置指定的字段为primary key(主键) 或者 unique(唯一) 索引来保证数据的唯一性。
如果设置了主键则那个键的默认值不能为null,可设置为not null。
如果设置了唯一索引,那么在插入重复数据时,SQL语句将无法执行成功,并抛出错。
insert ignore into 和insert into的区别就是insert ignore into 会忽略数据库中已经存在的数据,如果数据库没有数据,就插入新的数据,如果有数据的话就跳过这条数据。这样就可以保留数据库中已经存在的数据,达到在间隙中插入数据的目的。
insert ignore into 当插入数据时,在设置了记录的唯一性后,如果插入重复数据,将不会返回错误,只以警告形式返回。而replace into 如果存在primary key 或unique 相同的记录,则先删除掉,再插入新记录。
2.统计重复数据
//以下我们将统计表中first_name 和last_name的重复记录数
mysql> select count(*) as repetitions,first_name,last_name
-> from person_tb1
-> group by first_name,last_name
-> having repetitions>1;
+-------------+------------+-----------+
| repetitions | first_name | last_name |
+-------------+------------+-----------+
| 2 | HUA | ZHONG |
+-------------+------------+-----------+
1 row in set (0.14 sec)
以上查询语句将返回person_tb1表中重复的记录数
3 过滤重复数据
如果你需要读取不重复的数据可以在select 语句中使用distinct 关键字来过滤重复数据。
mysql> select distinct first_name,last_name
-> from person_tb1;
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| HUA | ZHONG |
| SIYUAN | YAN |
+------------+-----------+
2 rows in set (0.00 sec)
也可以使用group by 来读取数据表中不重复的数据
mysql> select first_name,last_name
-> from person_tb1
-> group by first_name,last_name;
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| HUA | ZHONG |
| SIYUAN | YAN |
+------------+-----------+
2 rows in set (0.00 sec)
删除重复数据
mysql> create table temp
-> select first_name,last_name,sex
-> from person_tb1
-> group by first_name,last_name,sex;
Query OK, 2 rows affected (0.22 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from temp;
+------------+-----------+------+
| first_name | last_name | sex |
+------------+-----------+------+
| HUA | ZHONG | NULL |
| SIYUAN | YAN | NULL |
+------------+-----------+------+
2 rows in set (0.00 sec)
mysql> drop table person_tb1;
Query OK, 0 rows affected (0.16 sec)
mysql> alter table temp rename to person_tb1;
Query OK, 0 rows affected (0.22 sec)
mysql> select * from person_tb1;
+------------+-----------+------+
| first_name | last_name | sex |
+------------+-----------+------+
| HUA | ZHONG | NULL |
| SIYUAN | YAN | NULL |
+------------+-----------+------+
2 rows in set (0.00 sec)
总结:
select col1,col2,count(*) as count
from tab_name
group by col1,col2
having count>1 and 其他条件;
eg:
mysql> select first_name,last_name,sex,count(*) as count
-> from person_tb1
-> group by first_name,last_name
-> having count>1 and first_name = 'HUA';
+------------+-----------+-------+-------+
| first_name | last_name | sex | count |
+------------+-----------+-------+-------+
| HUA | ZHONG | FEMAL | 2 |
+------------+-----------+-------+-------+
1 row in set (0.12 sec)
23 SQL注入
如果通过网页获取用户输入的数据并将其插入一个MYSQL数据库,那么就有可能发生SQL注入安全的问题。本章将介绍如何防止SQL注入,并通过脚本来过滤SQL中注入的字符。
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL语句。
我们永远不要信任用户的输入,我们必须认定用户输入的数据都是不安全的,我们都需要对用户输入的数据进行过滤处理。
在PHP的mysqli_query()是不允许执行多个SQL语句的,但是在SQLLite和PostgreSQL是可以同时执行多条SQL语句的,所以我们对这些用户的数据需要进行严格的验证。
防止SQL注入,需要注意以下几个要点:
- 永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和双"-"进行转换等。
- 永远不要使用动态拼装SQL,可以使用参数化的sql或直接使用存储过程进行数据查询存取。
- 永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
- 不要把机密信息直接存放,加密或者Hash掉密码和敏感的信息。
- 应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装。
- sql注入的检测方法一般采取辅助软件或网站平台来检测,软件一般采用SQL注入检测工具jsky,网站平台有MDCSOFT SCAN等,采用MDCSOFT-IPS可以有效的防御SQL注入。
防止SQL 注入
在脚本语言,如PHP和Perl你可以对用户输入的数据进行转义从而来防止SQL注入。
Like语句的注入
like查询时,如果用户输入的值有"“和”%",则会出现这种情况:用户本来只是想查询"abcd",查询结果中却有"abcdd_",“abcde”,“abcdf"等等,用户要查询"30%”(注:百分之30)时也会出现问题。
在PHP脚本中,我们的可以使用addcslashes()函数来处理以上情况。
24 导出数据
mysql中可使用select …into outfile语句导出数据
select … into outfile 语句有以下属性:
load dat infile
是select ...into outfile
的逆向操作的select 句法。 为了将一个数据库的数据写入文件,使用select ...into outfile
,为了将文件读回数据库,使用load data infile
select ... into outfile 'file_name'
形式的select 可以把选择的行写入一个文件中。该文件被创建到服务器主机中,因此你必须拥有file权限,才能使用该语法。- 输出不能是一个已经存在的文件。防止文件数据被篡改
- 需要有一个登录服务器的账号来检索文件。否则select …into outfile不会起任何作用。
- 在UNIX中,该文件被创建后是可读的,权限由MySQL服务器所拥有。这意味着,虽然你可以读取该文件,但可能无法将其删除。
eg:
//将数据表insect 数据导入到test.txt文件中
mysql> show variables like "%secure%";
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| require_secure_transport | OFF |
| secure_file_priv | |
+--------------------------+-------+
2 rows in set, 1 warning (0.11 sec)
mysql> select * from insect
-> into outfile 'D:/test.txt';
Query OK, 2 rows affected (0.13 sec)
//下面的例子,生成一个文件,各值用逗号隔开。这种格式被许多程序使用。
mysql> select * from test_outfile;
+---+---+
| a | b |
+---+---+
| 3 | 5 |
| 6 | 7 |
+---+---+
2 rows in set (0.00 sec)
mysql> select a,b,a+b
-> into outfile 'D:/test2,text'
-> fields terminated by ',' enclosed by '"'
-> lines terminated by '\r\n';
ERROR 1054 (42S22): Unknown column 'a' in 'field list'
mysql> select a,b,a+b
-> into outfile 'D:/test2,text'
-> fields terminated by ',' optionally enclosed by '"'
-> lines terminated by '\r\n'
-> from test_outfile;
Query OK, 2 rows affected (0.00 sec)
结果样式:
3,5,8
6,7,13
导出表为原始数据
mysqldump是mysql用于转存储数据库的实用程序。它主要产生一个SQL脚本,其中包含从头重新创建数据库库所必须 的命令create table insert
等。
使用mysqldump导出数据需要使用–tab选项来指定导出文件指定的目录,该目录必须是可写的。
导出SQL格式的数据
将数据表及数据库拷贝至其他主机
25 导入数据
1.SQL命令导入
2.source 命令导入
26 函数
mysql 有很多内置的函数
MySQL字符串函数
ASCII(s) | 返回字符串s的第一个字符的ASCII码 |
CHAR_LENGTH(s) | 返回字符串s的字符数 |
CHARACTER_LENGTH(s) | 返回字符串s的字符数=CHAR_LENGTH(s) |
CONCAT(s1,s2…sn) | 字符串s1,s2等多个字符串合并为一个字符串 |
CONCAT_WS(x,s1,s2…sn) | 同CONCAT(s1,s2…)函数,但是每个字符串之间加上x,x可以是分隔符 |
FIELD(s,s1,s2…) | 返回第一个字符串s在字符串列表(s1,s2…)中的位置 |
FIND_IN_SET(s1,s2) | 返回在字符串s2中与s1匹配的字符串的位置 |
FORMAT(x,n) | 函数可以将数字x进行格式化"#,###.##",将x保留到小数点后n位,最后一位四舍五入 |
INSERT(s1,x,len,s2) | 字符串s2替换s1的x位置开始长度为len的字符串 |
LOCATE(s1,s) | 从字符串s中获取s1的开始位置,第一个位置为1 |
LCASE(s) | 将字符串s的所有字母转换为小写字母 |
LEFT(s,n) | 返回字符串s的前n个字符 |
LOWER(s) | 将字符串s的所有字母变成小写字母 |
LPAD(s1,len,s2) | 在字符串s1的开始处填充字符串s2,是字符串长度达到len |
LTRIM(s) | 去掉字符串s开始处的空格 |
MID(s,n,len) | 从s的n位置截取长度为len的子字符串,同substring(s,n,len) |
POSITION(s1 in s) | 从字符串s中获取s1的开始位置 |
REPEAT(s,n) | 将字符串s重复n次 |
REPLACE(s,s1,s2) | 将s2代替s中的s1 |
REVERSE(s) | 将字符串s的顺序反过来 |
RIGHT(s,n) | 返回字符串s的后n个字符 |
RPAD(s1,len,s2) | 在字符串s1的结尾处添加s2,使字符串的长度达到len |
RTRIM(s) | 去掉字符串s结尾处的空格 |
SPACE(n) | 返回n个空格 |
STRCMP(s1,s2) | |
SUBSTR(s,start,length) | 从s的start位置截取长度为length的子字符串 |
SUBSTRING(s,start,length) | 从s的start位置截取长度为length的子字符串,等同于substr(s,start,length) |
SUBSTRING_INDEX(s,delimiter,number) | |
TRIM(s) | 去掉字符串s开始和结尾处的空格 |
UCASE(s) | 将字符串转换为大写字母 |
UPPER(s) | 将字符串转换为大写字母 |
MySQL日期函数 | |
– | – |
ADDDATE(d,n) | |
ADDTIME(t,n) | |
CURDATE() | |
CURRENT_DATE() | |
CURRENT_TIME | |
CURRENT_TIMESTAMP() | |
CURTIME() | |
DATE() | |
DATEDIFF(d1,d2) | |
DATE_ADD(d,INTERVAL expr type) | |
DATE_FORMAT(d,f) | |
DATE_SUB(date,INTERVAL expr type) | |
DAY(d) | |
DAYNAME(d) | |
DAYOFMONTH() | |
DAYOFWEEK | |
DAYOFYEAR | |
FROM_DAYS(n) | |
HOUR(t) | |
LAST_DAY(d) | |
LOCALTIME() | |
LOCALTIMESTAMP() | |
MAKEDATE(year, day-of-year) | |
MAKETIME(hour, minute, second) | |
MINUTE(t) | |
MONTHNAME(d) | |
MONTH(d) | |
NOW() | |
PERIOD_ADD(period, number) | |
PERIOD_DIFF(period1, period2) | |
QUARTER(d) | |
SECOND(t) | |
SEC_TO_TIME(s) | |
STR_TO_DATE(string, format_mask) | |
SUBDATE(d,n) | |
SUBTIME(t,n) | |
SYSDATE() | |
TIME(expression) | |
TIME_FORMAT(t,f) | |
TIME_TO_SET(t) | |
TIMDDIFF(time1,time2) | |
TIMESTAMP(expression,interval) | |
TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2) | |
TO_DAYS(d) | |
WEEK(d) | |
WEEKDAY(d) | |
WEEKOFYEAR(d) | |
YEAR(d) | |
YEARWEEK(date,mode) |
MySQL数字函数
ABS(x) | 返回x的绝对值 |
ACOS(x) | 求x的反余弦值(单位为弧度),x为一个数值 |
ASIN(x) | 求x的反正弦值,x为一个数值 |
ATAN(x) | 求反正切值,x为一个数值 |
ATAN2(n,m) | |
AVG(expression) | 返回一个表达式的平均值,expression是一个字段 |
CEIL(x) | 返回大于等于x的最小整数 |
CEILING(x) | 返回大于等于x的最小整数 |
COS(x) | 求余弦值(参数是弧度) |
COT(x) | 求余切值(参数是弧度) |
COUNT(expression) | 返回查询的记录总数,expression是一个字符或* |
DEGRESS(x) | 将弧度转换为角度 |
n DIV m | 整除,n为被除数,m为除数 |
EXP(x) | 返回e的x次方 |
FLOOR(x) | 返回小于等于x的最大整数 |
GREATEST(expr1,expr2,expr3…) | 返回列表中的最大值 |
LEAST(expr1,expr2,expr3…) | 返回列表中的最小值 |
LN(x) | 返回数字的自然对数,以e为底 |
LOG(x)或LOG(base,x) | 返回自然对数(以e为底的对数),如果带有base参数,则base为指定底数 |
LOG10(x) | 返回以10为底的对数 |
LOG2(x) | 返回以2为底的对数 |
MAX(expression) | 返回字段expression中的最大值 |
MIN(expression) | 返回字段expression中的最小值 |
MOD(x,y) | 返回x除以y以后的余数 |
PI() | 返回圆周率 |
POW(x,y) | 返回x的y次方 |
POWER(x,y) | 返回x的y次方 |
RADIANS(x) | 将角度转换为弧度 |
RAND() | 返回0到1的随机数 |
ROUND(x) | 返回离x最近的整数 |
SIGN(x) | 返回x的符号,x是负数、0、正数分别返回-1、0、1 |
SIN(x) | 求正弦值(参数是弧度) |
SQRT(x) | 返回x的平方根 |
SUM(expression) | 返回指定字段的总和 |
TAN(x) | 求正切值(参数是弧度) |
TRUNCATE(x,y) | 返回数值x保留到小数点后y位的值(与ROUND最大的区别是不会进行四舍五入) |
**MySQL高级函数 **
BIN(x) | 返回x的二进制编码 |
BINARY(s) | 将字符串s转换为二进制字符串 |
CAST(x AS type) | 转换数据类型 |
COALESCE(expr1,expr2,…exprn) | 返回参数中的第一个非空表达式(从左向右) |
CONNECTION_ID() | 返回唯一的连接ID |
CONV(x,f1,f2) | 将f1进制数变成f2进制数 |
CONVERT(s,using cs) | 将字符串s的字符集转变成cs |
CURRENT_USER() | 返回当前用户 |
DATABASE() | 返回当前数据库名 |
IF(expr,v1,v2) | 如果表达式expr成立,返回结果v1,否则返回v2 |
IFNULL(v1,v2) | 如果v1的值不为null,则返回v1,否则返回v2 |
ISNULL(expression) | 判断表达式是否为空 |
LAST_INSERT_ID() | 返回最近生成的auto_increment的值 |
NULLIF(expr1,expr2) | 比较两个字符串,如果expr1和expr2相等返回NULL,否则返回expr1 |
SESSION_USER() | 返回当前用户 |
SYSTEM_USER() | 返回当前用户 |
USER() | 返回当前用户 |
VERSION() | 返回数据库的版本号 |
CASE expression
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
WHEN conditionN THEN resultN
ELSE result
END
CASE表示函数开始,END表示函数结束。如果condition1 成立,则返回result1,如果condition2成立,则返回result2,当全部不成立则返回result,而当有一个成立后,后面的就不执行了。
27 运算符
算术运算符
运算符 | 作用 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ 或 DIV | 除法 |
% 或 MOD | 取余 |
在除法运算和模运算中,如果除数为0,将是非法除数,返回结果为NULL。 |
mysql> select 1+2;
+-----+
| 1+2 |
+-----+
| 3 |
+-----+
1 row in set (0.00 sec)
mysql> select 1-2;
+-----+
| 1-2 |
+-----+
| -1 |
+-----+
1 row in set (0.02 sec)
mysql> select 1*2;
+-----+
| 1*2 |
+-----+
| 2 |
+-----+
1 row in set (0.00 sec)
mysql> select 2/1;
+--------+
| 2/1 |
+--------+
| 2.0000 |
+--------+
1 row in set (0.00 sec)
mysql> select 3%2;
+------+
| 3%2 |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
比较运算符
select语句中的条件语句经常要使用比较运算符。通过这些比较运算符,可以判断表中的记录哪些是符合条件的。比较结果为真返回1,为假返回0,比较结果不确定则返回NULL。
= | |
<>,!= | 不等于 |
> | |
< | |
<= | |
>= | |
BETWEEN | |
NOT BETWEEN | |
IN | 在集合中 |
NOT IN | 不在集合中 |
<=> | 严格比较两个NULL值是否相等。两个操作码均为NULL时,其所得值为1;而当一个操作码为NULL时,其所得值为0 |
LIKE | 模糊匹配 |
REGEXP 或 RLIKE | 正则正则式匹配 |
IS NULL | 为空 |
IS NOT NULL | 不为空 |
eg: |
mysql> select 2=3;
+-----+
| 2=3 |
+-----+
| 0 |
+-----+
1 row in set (0.00 sec)
mysql> select NULL=NULL;
+-----------+
| NULL=NULL |
+-----------+
| NULL |
+-----------+
1 row in set (0.00 sec)
mysql> select null <=> null;
+---------------+
| null <=> null |
+---------------+
| 1 |
+---------------+
1 row in set (0.00 sec)
mysql> select 2<>3;
+------+
| 2<>3 |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
mysql> select 2<=>3;
+-------+
| 2<=>3 |
+-------+
| 0 |
+-------+
1 row in set (0.00 sec)
mysql> select 2<3;
+-----+
| 2<3 |
+-----+
| 1 |
+-----+
1 row in set (0.01 sec)
mysql> select 2<=3;
+------+
| 2<=3 |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
mysql> select 2>=3;
+------+
| 2>=3 |
+------+
| 0 |
+------+
1 row in set (0.00 sec)
mysql> select 5 between 1 and 10;
+--------------------+
| 5 between 1 and 10 |
+--------------------+
| 1 |
+--------------------+
1 row in set (0.00 sec)
mysql> select 5 in (3,4,5);
+--------------+
| 5 in (3,4,5) |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
mysql> select 5 not in (1,2,4,5);
+--------------------+
| 5 not in (1,2,4,5) |
+--------------------+
| 0 |
+--------------------+
1 row in set (0.00 sec)
mysql> select null is null;
+--------------+
| null is null |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
mysql> select 'a' is null;
+-------------+
| 'a' is null |
+-------------+
| 0 |
+-------------+
1 row in set (0.00 sec)
mysql> select null is not null;
+------------------+
| null is not null |
+------------------+
| 0 |
+------------------+
1 row in set (0.00 sec)
mysql> select 'a' is not null;
+-----------------+
| 'a' is not null |
+-----------------+
| 1 |
+-----------------+
1 row in set (0.00 sec)
mysql> select '12345' like '12%';
+--------------------+
| '12345' like '12%' |
+--------------------+
| 1 |
+--------------------+
1 row in set (0.00 sec)
mysql> select '12345' like '12_';
+--------------------+
| '12345' like '12_' |
+--------------------+
| 0 |
+--------------------+
1 row in set (0.00 sec)
mysql> select 'beijing' regexp 'jing';
+-------------------------+
| 'beijing' regexp 'jing' |
+-------------------------+
| 1 |
+-------------------------+
1 row in set (0.15 sec)
mysql> select 'beijing' regexp 'xi';
+-----------------------+
| 'beijing' regexp 'xi' |
+-----------------------+
| 0 |
+-----------------------+
1 row in set (0.00 sec)
逻辑运算符
逻辑运算符用来判断表达式的地真假。如果表达式是真的,结果返回1,如果表达式
是假的,结果返回0.
NOT 或 ! | 逻辑非 |
AND | 逻辑与 |
OR 或者 | 逻辑或 |
XOR | 逻辑异或 |
mysql> select 2 and 0;
+---------+
| 2 and 0 |
+---------+
| 0 |
+---------+
1 row in set (0.00 sec)
mysql> select 2 and 1;
+---------+
| 2 and 1 |
+---------+
| 1 |
+---------+
1 row in set (0.00 sec)
mysql> select 2 or 0;
+--------+
| 2 or 0 |
+--------+
| 1 |
+--------+
1 row in set (0.00 sec)
mysql> select 0 or 0;
+--------+
| 0 or 0 |
+--------+
| 0 |
+--------+
1 row in set (0.00 sec)
mysql> select 1 ||0;
+-------+
| 1 ||0 |
+-------+
| 1 |
+-------+
1 row in set, 1 warning (0.00 sec)
mysql> select not 1;
+-------+
| not 1 |
+-------+
| 0 |
+-------+
1 row in set (0.00 sec)
mysql> select !0;
+----+
| !0 |
+----+
| 1 |
+----+
1 row in set, 1 warning (0.00 sec)
mysql> select 1 xor 0;
+---------+
| 1 xor 0 |
+---------+
| 1 |
+---------+
1 row in set (0.00 sec)
mysql> select 1 xor 1;
+---------+
| 1 xor 1 |
+---------+
| 0 |
+---------+
1 row in set (0.00 sec)
mysql> select null or 1;
+-----------+
| null or 1 |
+-----------+
| 1 |
+-----------+
1 row in set (0.00 sec)
mysql> select 1^0;
+-----+
| 1^0 |
+-----+
| 1 |
+-----+
1 row in set (0.00 sec)
位运算符
位运算符是在二进制数上进行计算的运算符。位运算会先将操作数变成二进制数,进行位运算。然后再将计算结果从二进制变成十进制数。
& | 按位与 |
^ | 按位异或 |
! | 取反 |
<< | 左移 |
>> | 右移 |
mysql> select 3&5;
+-----+
| 3&5 |
+-----+
| 1 |
+-----+
1 row in set (0.00 sec)
mysql> select 3|5;
+-----+
| 3|5 |
+-----+
| 7 |
+-----+
1 row in set (0.00 sec)
mysql> select 3^5;
+-----+
| 3^5 |
+-----+
| 6 |
+-----+
1 row in set (0.00 sec)
mysql> select 3>>1;
+------+
| 3>>1 |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
mysql> select 3<<1;
+------+
| 3<<1 |
+------+
| 6 |
+------+
1 row in set (0.00 sec)
运算符优先级
:= | |
&&,AND | |
NOT | |
between,case,when,then,else | |
=,<=>,>=,>,<,<=,<>,!=,is,like,regexp,in | |
& | |
<<,>> | |
-,+ | |
*,/,DIV,%,MOD | |
^ | |
-(一元减号 ) | |
! | |
优先级最高:!、BINARY,COLLATE | |
最低优先级::= |