Mysql常用语句

36 篇文章 3 订阅
17 篇文章 2 订阅

目录

0.命令行连接数据库

1.创建数据库

2.删除数据库

3.选择数据库

4.创建表

5.删除表

6.修改表结构

7.插入数据

8.更改表数据

9.删除表数据

10.like子句

11.查询语句

(1)where型子查询

(2)from型子查询

(3)exists型子查询

12.排序

13.分组

14.数据库表字段类型

多表连接

1.左连接

2.右连接

3.内连接

4.外连接

5.表连接的类型

【表的纵向连接】

1.横向连接的底层原理


0.命令行连接数据库

mysql -u root -p

1.创建数据库

CREATE DATABASE 数据库名;

2.删除数据库

drop database 数据库名
命令行删除数据库
mysqladmin -u root -p drop RUNOOB

3.选择数据库

use 数据库名称

4.创建表

    CREATE TABLE IF NOT EXISTS `user`(
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',
    `username` VARCHAR(100) NOT NULL COMMENT '账号',
    `password` VARCHAR(500) NOT NULL COMMENT '密码',
    `type` VARCHAR(100) NOT NULL COMMENT '账号类型',
    `uuid` VARCHAR(500) NOT NULL COMMENT '唯一uuid',
    `is_delete` TINYINT NOT NULL COMMENT '是否使用',
    `create_date` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '日期',
    `update_date` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新日期',
    PRIMARY KEY (`id`)
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • UNSIGNED    无符号,非负数
  • NOT NULL  值不为空
  • AUTO_INCREMENT 定义列为自增的属性,一般用于主键,数值会自动加1。
  • COMMENT   注释
  • PRIMARY KEY  关键字用于定义列为主键,可以使用多列来定义主键,列间以逗号分隔。
  • DEFAULT  默认值
  • CURRENT_TIMESTAMP(0)  当前时间戳
  • ON UPDATE  在字段值发生变更时
  • ENGINE 设置存储引擎,CHARSET 设置编码。
  • FOREIGN KEY 外键
CREATE TABLE user_account (
    id INTEGER NOT NULL,
    name VARCHAR(30),
    fullname VARCHAR,
    PRIMARY KEY (id)
)

CREATE TABLE address (
    id INTEGER NOT NULL,
    email_address VARCHAR NOT NULL,
    user_id INTEGER NOT NULL,
    PRIMARY KEY (id),
    FOREIGN KEY(user_id) REFERENCES user_account (id)
)

5.删除表

use 数据库名
drop table 表名

6.修改表结构

(1)使用ALTER 命令及 DROP 子句来删除以上创建表的字段:

ALTER TABLE 表名  DROP 字段名;

如果数据表中只剩余一个字段则无法使用DROP来删除字段。

MySQL 中使用 ADD 子句来向数据表中添加列,如下实例在表 testalter_tbl 中添加字段,并定义数据类型:

ALTER TABLE 表名 ADD 字段名 字段数据类型;

执行以上命令后,字段会自动添加到数据表字段的末尾。

SHOW COLUMNS FROM 表;

(2)修改字段类型及名称

如果需要修改字段类型及名称, 你可以在ALTER命令中使用 MODIFY 或 CHANGE 子句 。

例如,把字段 c 的类型从 CHAR(1) 改为 CHAR(10),可以执行以下命令:

ALTER TABLE testalter_tbl MODIFY c CHAR(10);

使用 CHANGE 子句, 语法有很大的不同。

在 CHANGE 关键字之后,紧跟着的是你要修改的字段名,然后指定新字段名及类型

ALTER TABLE testalter_tbl CHANGE i j BIGINT;
ALTER TABLE testalter_tbl CHANGE j j INT;

(3)修改字段默认值

ALTER TABLE user ALTER username SET DEFAULT 1000;

(4)删除字段默认值

ALTER TABLE user ALTER username DROP DEFAULT;

(5)修改表名

ALTER TABLE user RENAME TO user2;

7.插入数据

INSERT INTO user 
     (username, password, type,uuid,is_delete)
      VALUES
     ("liyinchi", "菜鸟123456", "admin","asd123b1jh3",0);

 或者

8.更改表数据

UPDATE user SET username='jackLi',password='6666666' WHERE id=3;

9.删除表数据

DELETE FROM user WHERE username like '%liyinchi%';

10.like子句

SELECT * from user  WHERE username LIKE '%liyinchi%';
  • 可以在 WHERE 子句中指定任何条件。
  • 可以在 WHERE 子句中使用LIKE子句。
  • 可以使用LIKE子句代替等号 =。
  • LIKE 通常与 % 一同使用,类似于一个元字符的搜索。
  • 可以使用 AND 或者 OR 指定一个或多个条件。
  • 可以在 DELETE 或 UPDATE 命令中使用 WHERE...LIKE 子句来指定条件。

LIKE 子句中使用百分号 %字符来表示任意字符,类似于UNIX或正则表达式中的星号 *

11.查询语句

select *
from user
where username like "%liyinchi%"
  • 查询语句中可以使用一个或者多个表,表之间使用逗号, 分割,并使用WHERE语句来设定查询条件。
  • 可以在 WHERE 子句中指定任何条件。
  • 可以使用 AND 或者 OR 指定一个或多个条件。
  • WHERE 子句也可以运用于 SQL 的 DELETE 或者 UPDATE 命令。
  • WHERE 子句类似于程序语言中的 if 条件,根据 MySQL 表中的字段值来读取指定的数据。
操作符描述实例
=等号,检测两个值是否相等,如果相等返回true(A = B) 返回false。
<>, !=不等于,检测两个值是否相等,如果不相等返回true(A != B) 返回 true。
>大于号,检测左边的值是否大于右边的值, 如果左边的值大于右边的值返回true(A > B) 返回false。
<小于号,检测左边的值是否小于右边的值, 如果左边的值小于右边的值返回true(A < B) 返回 true。
>=大于等于号,检测左边的值是否大于或等于右边的值, 如果左边的值大于或等于右边的值返回true(A >= B) 返回false。
<=小于等于号,检测左边的值是否小于或等于右边的值, 如果左边的值小于或等于右边的值返回true(A <= B) 返回 true。

 子查询


(1)where型子查询

#  查询比“小李”的工资高的员工编号
SELECT * FROM t_salary
WHERE basic_salary > (SELECT basic_salary FROM t_employee INNER JOIN t_salary ON t_employee.eid=t_salary.eid WHERE t_employee.ename='小李');

 IN、ANY

# 查询和小李,小张在同一个部门的员工
SELECT * FROM t_employee
WHERE dept_id IN(SELECT dept_id FROM t_employee WHERE ename='小李' OR ename = '小张');
SELECT * FROM t_employee
WHERE dept_id = ANY(SELECT dept_id FROM t_employee WHERE ename='小李' OR ename = '小张');

 ALL

# 查询全公司工资最高的员工编号,基本工资
SELECT eid,basic_salary FROM t_salary
WHERE basic_salary = (SELECT MAX(basic_salary) FROM t_salary);
SELECT eid,basic_salary FROM t_salary
WHERE basic_salary >= ALL(SELECT basic_salary FROM t_salary);

(2)from型子查询

from型子查询即把内层sql语句查询的结果作为临时表供外层sql语句再次查询。

# 找出比部门平均工资高的员工编号,基本工资
SELECT t_employee.eid,basic_salary
FROM t_salary INNER JOIN t_employee INNER JOIN (
SELECT emp.dept_id AS did,AVG(s.basic_salary) AS avg_salary
FROM t_employee AS emp,t_salary AS s
WHERE emp.eid = s.eid
GROUP BY emp.dept_id) AS temp
ON t_salary.eid = t_employee.eid AND t_employee.dept_id = temp.did
WHERE t_salary.basic_salary > temp.avg_salary;

(3)exists型子查询

# 查询部门信息,该部门必须有员工
SELECT * FROM t_department
WHERE EXISTS (SELECT * FROM t_employee WHERE t_employee.dept_id = t_department.did);

(4) INSERT 语句中加入子查询。

不必书写 VALUES 子句,子查询中的值列表应与 INSERT 子句中的列名对应。

INSERT INTO emp2

SELECT * FROM employees WHERE department_id = 90;
INSERT INTO sales_reps(id, name, salary, commission_pct)

SELECT employee_id, last_name, salary, commission_pct

FROM employees

WHERE job_id LIKE '%REP%';

12.排序

SELECT * from user ORDER BY id ASC;
  • 可以使用任何字段来作为排序的条件,从而返回排序后的查询结果。
  • 可以设定多个字段来排序。
  • 可以使用 ASC 或 DESC 关键字来设置查询结果是按升序或降序排列。 默认情况下,它是按升序排列。
  • 可以添加 WHERE...LIKE 子句来设置条件。

13.分组

使用 GROUP BY 语句 将数据表按名字进行分组,并统计每个人有多少条记录:

SELECT username,password,COUNT(*) FROM user GROUP BY username;

14.数据库表字段类型

(1)数值

tinyint、smallint、mediumint、integer、bigint、float、double、decimal

类型大小范围(有符号)范围(无符号)用途
TINYINT1 Bytes(-128,127)(0,255)小整数值
SMALLINT2 Bytes(-32 768,32 767)(0,65 535)大整数值
MEDIUMINT3 Bytes(-8 388 608,8 388 607)(0,16 777 215)大整数值
INT或INTEGER4 Bytes(-2 147 483 648,2 147 483 647)(0,4 294 967 295)大整数值
BIGINT8 Bytes(-9,223,372,036,854,775,808,9 223 372 036 854 775 807)(0,18 446 744 073 709 551 615)极大整数值
FLOAT4 Bytes(-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38)0,(1.175 494 351 E-38,3.402 823 466 E+38)单精度
浮点数值
DOUBLE8 Bytes(-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)双精度
浮点数值
DECIMAL对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2依赖于M和D的值依赖于M和D的值小数值

(2)日期和时间类型

DATETIME、DATE、TIME、TIMESTAMO、YEAR

类型大小( bytes)范围格式用途
DATE31000-01-01/9999-12-31YYYY-MM-DD日期值
TIME3'-838:59:59'/'838:59:59'HH:MM:SS时间值或持续时间
YEAR11901/2155YYYY年份值
DATETIME81000-01-01 00:00:00/9999-12-31 23:59:59YYYY-MM-DD HH:MM:SS混合日期和时间值
TIMESTAMP4

1970-01-01 00:00:00/2038

结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07

YYYYMMDD HHMMSS混合日期和时间值,时间戳

timestamp一般和current_timestamp使用,如创建表字段值默认使用当前时间戳。

`create_date` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '日期',

(3)字符串类型

CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM、SET

类型大小用途
CHAR0-255 bytes定长字符串
VARCHAR0-65535 bytes变长字符串
TINYBLOB0-255 bytes不超过 255 个字符的二进制字符串
TINYTEXT0-255 bytes短文本字符串
BLOB0-65 535 bytes二进制形式的长文本数据
TEXT0-65 535 bytes长文本数据
MEDIUMBLOB0-16 777 215 bytes二进制形式的中等长度文本数据
MEDIUMTEXT0-16 777 215 bytes中等长度文本数据
LONGBLOB0-4 294 967 295 bytes二进制形式的极大文本数据
LONGTEXT0-4 294 967 295 bytes极大文本数据

多表连接

表的横向连接主要有left join、right join、inner join、outer join四种方式。

表1:order_info

orderid,userid,gmv
101,E001,10
102,E002,20
103,E001,30
104,E004,40
105,E003,50
106,E002,60

表2:order

userid,first_time,orders_7,orders_14
E001,2019/1/2,5,11
E002,2019/5/1,7,14
E003,2018/12/31,6,13
E007,2019/2/5,9,12
E008,2019/1/5,10,13
E009,2019/2/20,7,14

表3:user

userid,sex,city_name,level
E001,男,北京,金牌
E002,男,上海,银牌
E003,女,北京,金牌
E004,男,泉州,铜牌
E005,女,厦门,银牌
E006,女,成都,金牌

1.左连接

left join是左连接,左连接就是以左边的表为主表,然后将右边的表根据两张表的公共列往左边的表上连接。比如我们将user表当作主表,放在左边,然后将order往左连接,两张表的公共列为userid,具体实现代码如下:

select user.userid,
       user.sex,
       user.city_name,
       user.level,
       order.userid,
       order.first_time,
       order.orders_7,
       order.orders_14
from user
    left join order
        on user.userid = order.userid;

在进行表连接时,我们用on来指明两张表中的公共列。运行上面的代码,会得到左表中的全部信息、右表中的部分信息,具体运行结果如下表所示。

2.右连接

right join是右连接,右连接与左连接相对应。右连接是以右边的表为主表,然后将左边的表根据两张表的公共列往右边的表上连接。比如,我们将order表当作主表,放在右边,然后将user表往右连接,两张表的公共列为userid,具体实现代码如下:

select user.userid,
       user.sex,
       user.city_name,
       user.level,
       order.userid,
       order.first_time,
       order.orders_7,
       order.orders_14
from user
    right join order
        on order.userid = user.userid;

运行上面代码,具体运行结果如下表所示: 

3.内连接

inner join是内连接,内连接是针对两张表取交集的,即获取公共列中都出现的值的信息。比如,我们将user表与order表进行内连接,两张表的公共列为userid,具体实现代码如下:

select user.userid,
       user.sex,
       user.city_name,
       user.level,
       order.userid,
       order.first_time,
       order.orders_7,
       order.orders_14
from user
    inner join order
        on order.userid = user.userid;

运行上面的代码,具体运行结果如下表所示:

4.外连接

outer join是外连接,外连接与内连接相对应,是针对两张表取并集的,要查询的信息只要在任意一张表中存在,最后就会显示在结果中。

但是MySQL暂不支持外连接的方式,我们就可以用左连接和右连接相组合的方式来达到外连接的效果,具体实现代码如下:

select user.userid,
       user.sex,
       user.city_name,
       user.level,
       order.userid,
       order.first_time,
       order.orders_7,
       order.orders_14
from user
    left join order
        on user.userid = order.userid
union 
select user.userid,
       user.sex,
       user.city_name,
       user.level,
       order.userid,
       order.first_time,
       order.orders_7,
       order.orders_14
from user
    right join order
        on order.userid = user.userid;

运行上面的代码,具体运行结果如下表所示

5.表连接的类型

【表的横向连接】

主要有一对一、一对多、多对多三种。

(1)一对一
一对一是指用于连接两张表的公共列的值在左表和右表中都是没有重复值的。

(2)一对多
一对多是指用于连接两张表的公共列的值在左表或右表中是有重复值的。
现在如果我们要对chapter12_user表和chapter12_order_info表根据userid列进行连接时,就是一对多连接,因为userid在chapter12_order_info表中会有重复值,比如E001、E002。

这个时候程序就会自动把一对多中没有重复值的一列复制成多条记录,具体实现代码如下:

select
    *
from user
    right join order_info
        on order_info.userid = user.userid
order by user.userid;

(3)多对多
多对多相当于多个一对多,就是用于连接两张表的公共列的值在左右表中都有重复。这个时候就是传说中的笛卡儿积(Cartesian product)。

笛卡儿乘积是指在数学中,两个集合X和Y的笛卡儿积,又称为直积,表示为X × Y,第一个对象是X的成员,而第二个对象是Y的所有可能有序对的其中一个成员。

如果用于连接两张表的一个公共列的值在左表中重复出现了m次,在右表中重复出现了n次,最后连接下来的结果会是m×n条记录。我们在实际工作中要尽量避免一对多及多对多情况的出现,在对两张表进行连接时,一定要先检查用于连接表的公共列是否有重复值,如果有,则先处理完重复值以后再去与别的表进行连接。

(4)多张表连接
有时候,我们需要的信息不止分布在两张表中,这个时候就需要对大于两张的表进行连接,此处以chapter12_order_info表、chapter12_order表、chapter12_user表为例进行三表连接。具体实现代码如下:

select order_info.orderid,
       order_info.userid,
       order_info.gmv,
       user.level,
       order.first_time
from order_info
    left join user
        on order_info.userid = user.userid
    left join order
        on order_info.userid = order.userid;

 运行上面的代码,最后就会得到三张表中不同的信息,具体运行结果如下表所示。

【表的纵向连接】

在SQL中进行纵向连接时,我们使用的是union和union all,两者的区别是,前者会对纵向连接后的结果进行删除重复值处理,而后者是不进行任何处理的,只是把两张表连接在一起。

如果表中没有重复值,建议使用union all,这样程序就不会执行删除重复值这个过程,可以提高程序的运行效率。

1.横向连接的底层原理

join主要有Nested Loop、Hash Join、Merge Join三种方式。

Nested Loop又有三种细分的连接方式,分别是Simple Nested-Loop Join、Index Nested-Loop Join、Block Nested-Loop Join。

在介绍原理之前,先介绍两个概念:驱动表(也称为外表)和被驱动表(也称为非驱动表、匹配表或内表)。简单理解一下,驱动表就是主表,left join中的左表是驱动表,right join中的右表是驱动表,一张是驱动表,那么另一张就只能是非驱动表了,在join的过程中,其实就是从驱动表中依次(注意理解这里面的依次)取出每一个值。

(1)Simple Nested-Loop Join(简单的嵌套循环联接)
Simple Nested-Loop Join是最简单、最好理解,也是最符合认知的一种连接方式,现在有table A和table B两张表,我们对两张表进行左连接,如果用Simple Nested-Loop Join连接方式去实现,通过下面这张图来理解。

首先从驱动表table A中依次取出每个值,然后在非驱动表table B中从上往下依次匹配,接着把匹配到的值进行返回,最后把所有返回的值进行合并,这样我们就查找到了table A left join table B的结果。利用这种方式,如果table A表有10行,table B表有10行,则总共需要执行10×10 = 100次查询。

这种“暴力”匹配的方式在数据库中一般不使用。

(2)Index Nested-Loop Join(索引嵌套循环联接)
在Index Nested-Loop Join方式中,这里的Index表示要求非驱动表上要有索引,有了索引以后可以减少匹配的次数,匹配次数减少了就可以提高查询的效率了。

上图中左边是普通列的存储方式,右边是树结构索引,什么是树结构呢?就是数据分布像树一样一层一层的,树结构有一个特点就是左边的数小于顶点的数,右边的数大于顶点的数,如上图中的右图,左边的数3小于顶点的数6,右边的数7大于顶点的数6;左边的数1小于顶点的数3,右边的数4大于顶点的数3。

假如我们现在要匹配值9,如果使用左边这种数据存储方式,系统需要从第一行依次匹配到最后一行才能找到值9,总共需要匹配7次;但是如果我们使用右边这种树结构索引,先拿9和顶点6去匹配,发现9比6大,然后就去顶点的右边找,再去和7匹配,发现9仍然比7大,再去7的右边找,就找到了9,这样只匹配了3次就把我们想要的9找到了。相比匹配7次节省了很多时间。


数据库中的索引一般用B+树,为了让读者更好地理解,上图只是最简单的一种树结构,而非真实的B+树。

如果索引是主键,则效率会更高,因为主键必须是唯一的,所以如果非驱动表是用主键连接的,则只会出现多对一或者一对一的情况,而不会出现多对多和一对多的情况。

(3)Block Nested-Loop Join(块嵌套循环联接)
在理想情况下,用索引匹配是最高效的一种方式,但是在现实工作中,并不是所有的列都是索引列,这个时候就需要用到Block Nested-Loop Join方式了,这种方式与Simple Nested-Loop Join方式比较类似,唯一的区别就是它会把驱动表中left join涉及的列(不只是用来on的列,还有select部分的列)先取出来放到一个缓存区域,然后去和非驱动表进行匹配,这种方式和Simple Nested-Loop Join方式相比所需要的匹配次数是一样的,差别就在于驱动表的列数不同,也就是数据量的多少不同。所以虽然匹配次数没有减少,但是总体的查询性能还是有所提升的。

Simple Nested-Loop Join方式的连接原理如下图所示,驱动表会拿表中全部列去和非驱动表进行匹配连接。


Block Nested-Loop Join方式的连接原理如下图所示,驱动表会把select中用到的列和on中用到的列拿出来去和非驱动表进行匹配连接。

 

TODO
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liyinchi1988

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值