【全文两万多字,涵盖大部分常见情况,建议点赞收藏】
目录
文章目录
- 目录
- 安装
- SQL语言
- 备份与恢复
- Linux防火墙修改
- 其他机器连接本地的MySQL
- Linux禁止更新(推荐设置)
- mysql无法输入中文
安装
检查安装(linux管理命令)
bash
rpm -qa | grep mysql
linux管理命令
systemcrl (start/restart/stop) mysql.service
service mysqld start
systemcrl start mysql.service 开启MySQL服务
(只要没有错误信息就表示已经正常启动了)
systemcrl stop mysql.service 关闭MySQL服务
systemctl restart mysql.servic 重启MySQL服务
service mysqld status 查看服务状态
systemcrl enable mysql.service 设置开机自启动(一般默认都开着)
Windows
管理员身份启动cmd
C:\WINDOWS\system32> net start mysql57 启动
C:\WINDOWS\system32> net stop mysql57 关闭
目前主要使用两种框架方式:
- LAMP
- WAMP
SQL语言
结构化查询语言,简称SQL(Structured Query Language),是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。
核心SQL的四个组成部分:
- 数据定义语言(DDL):用来定义数据库的表、库、列等对象。保留字:create、alter、drop、truncate。
- 数据操纵语言(DML):用来操纵数据库记录。保留字:insert、update、delete。
- 数据控制语言(DCL):用来定义访问权限和安全级别。保留字:commit,rollback、savepoint、grant、revoke。
- 数据查询语言(DQL):用来查询记录。保留字:select、where、order by、group by、having。
- 嵌入式SQL语言的使用规则
注意:MySQL中不分大小写
SQL的特点:
- 综合统一:集数据定义语言DDL、数据操纵语言DML、数据控制语言DCL的功能于一体,语言风格统一,可以独立完成数据库生命周期中的全部活动。定义关系模式,建立数据库,对数据进行查询和更新,数据库重构和维护,数据库完整性安全性控制等。可以在不影响数据库运行的情况下对数据库进行模式的修改。实体及实体间的联系都用关系表示,数据结构的单一性带来操作符的统一,简化了操作。
- 高度非过程化:用户只需提出"做什么",无须告诉"怎么做",不必了解存取路径,路径的选择及SQL的操作过程由系统自动完成,减轻了用户的负担,有利于提高数据独立性。
- 面向集合的操作方式:集合SQL采用集合操作方式,操作对象和操作结果都是关系 --- 元组,可以一次插入、删除、更新整个集合的元组。
- 两种使用方式,统一的语法结构:SQL既是自含式语言(用户使用),又是嵌入式语言(程序员使用), 不同的使用方式, 但语法结构基本是一致的。
- 语言简洁,语法简单,接近英语口语,易学易用:SQL完成核心的功能只用了9个命令动词。
基本表:基本表是独立、存在的表,SQL中一个关系就对应一个基本表(基表);一个基表上可以带多个索引,索引存放在存储文件里;
视图:视图是一个或多个基表导出的表,数据库中只存放视图定义以及与其关联的基本表名等信息,而不存放视图对应的数据;数据仍存放在导出视图的基本表中,因此视图又称为虚拟表。
存储文件:由多个基本表、视图、相关索引和存储过程等数据库对象组成;存储文件的逻辑结构对应数据库的内模式。
- 数据库
- 表
- 字段(列)
- 数据(约束)
例句标识:
[]
可省略
{|}
左右任意选择
db_name
库名称
tbl_name
表名称
col_name
字段,数据列名列表
expr
常量、变量、表达式
select_expr
要查询的内容
1.使用
登录mysql
sql
mysql -p
登录mysql的root
sql
mysql -u root -p
退出
sql
mysql> ctrl+c
mysql> exit
授予权限
mysql
grant privileges on dbname.tablename to'username'@'host'
- privileges:可以是SELECT,INSERT,UPDATE等,如果要授予所的权限则用ALL
- dbname:数据库名
- tablename:表名,若要授予该用户对数据库中所有表的操作权限则可用表示,如.*
例如:grant select on BookStore.* to UserA
撤销权限
mysql
revoke privilege on dbname.tablename from 'username'@'host';
使用
sql
use mysql;
设置/重置MySQL登录密码
sql
set password = password('我是密码');
新刷系统权限
sql
flush privileges;
查看所有编码字符
sql
show variables like "%character%";
2.DATABASE
查看所有库
like
关键字用于匹配名称where
关键字用于指定查找范围条件
sql
SHOW DATABASES [LIKE 'pattern'|WHERE expr];
【注意】是 databases 不是 database。
新建数据库
if not exists
表示查看是否已存在,避免出现创建已存在的数据库时出现的错误
sql
create database 数据库名称;
CREATE SCHEMA 库名称;
CREATE {DATABASE|SCHEMA} [IF NOT EXISTS] db_name
修改数据库
sql
ALTER DATABASE 库名称;
删除数据库
IF EXISTS
判断是否存在,避免出现删除不存在的数据库时出现的错误
sql
drop database [IF EXISTS] 数据库名称;
连接数据库
sql
use 数据库名称;
查看当前数据库信息
sql
status;
--------------
mysql Ver 14.14 Distrib 5.7.30, for Win64 (x86_64)
Connection id: 3
Current database:
Current user: root@localhost
SSL: Cipher in use is ECDHE-RSA-AES128-GCM-SHA256
Using delimiter: ;
Server version: 5.7.30 MySQL Community Server (GPL)
Protocol version: 10
Connection: localhost via TCP/IP
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: utf8mb4
Conn. characterset: utf8mb4
TCP port: 3306
Uptime: 1 day 2 hours 17 min 39 sec
Threads: 1 Questions: 5 Slow queries: 0 Opens: 105 Flush tables: 1 Open tables: 98 Queries per second avg: 0.000
--------------
1.当前链接的id号
2.当前选择的使用的数据库
3.当前链接的登录用户
4.是否使用SSL
5.行终结符是分号
6.当前mysql服务器的版本号
7.协议版本
8.使用的链接类型
9.服务器使用的字符类型
10.数据库使用的字符类型
11.客户端使用的字符类型
12.链接使用的字符类型
13.链接端口号
14.时间
3.TABLE
类型 | 描述 |
---|---|
CHAR(固定长度) | 表示字符串类型, 数字 |
VARCHAR(变长长度) | 可以存放数字,字母 |
INT(长度) | 整型 |
FLOAT/DOUBLE | 浮点类型 |
BOOL | 布尔型 |
DATE | 表示日期类型(不包含时分秒) |
DATETIME | 时间戳:表示时间类型(包含时分秒) |
TIME | 时间型 |
TEXT | 放大文本字符串 |
BLOB | 用于存放二进制文件,例如图片,电影,音乐 |
char与varchar后面接的数据大小为存储的字符数,而不是字节数。
char定义的是固定长度,长度范围为0-255,存储时,如果字符数没有达到定义的位数,会在后面用空格补全存入数据库中。
varchar是变长长度,长度范围为0-65535,存储时,如果字符没有达到定义的位数,也不会在后面补空格。
创建表的操作属于**DDL(数据库定义语言)**操作,所以是由命名要求的,对于表名称以及列名称的定义要求如下:
- 必须字母开头
- 长度为1~30个字符
- 对于同一用户不能用相同的表名称
- 不能使用保留字
创建表
(表创建定义+表选项+分区选项...)
sql
create table 表名称(
字段名称 数据类型 [DEFAULT 默认值],
字段名称 数据类型 [DEFAULT 默认值],
其他字段...,
[表级完整性约束条件]
)[engine=引擎类型];
创建表例子:
mysql> create table user_1(
-> id int AUTO_INCREMENT PRIMARY KEY,
-> name varchar(10) NOT NULL,
-> sex char(5) DEFAULT 0,
-> age int,
-> )
-> ;
-
TEMPORARY
关键字表示该语句创建的是临时表 ,默认是持久表 -
AUTO_INCREMENT
关键字可以为表中的int (整型)列设置自增 属性。每个表只能有一个自增列,并且它必须被索引 -
DEFAULT
关键字可以给列设置默认值 -
NOT NULL
关键字表示列不允许为空值,默认为NULL
,表示可以为空 -
PRIMARY KEY
关键字设置表的主键,主键必须唯一,必须是NOT NULL,如果有多个主键,则用都逗号隔开。sqlPRIMARY KEY(id) PRIMARY KEY(id, id2)
查看库所有表
sql
SHOW [FULL] TABLE [FROM 库名称] [LIKE 'pattern'|WHERE expr];
-- 例如:
show tables;
删除表
sql
drop table 表名;
查看表信息
sql
SHOW [FULL] COLUMNS {FROM|IN} 表名 [{FROM|IN} 数据库名] [LIKE 'pattern'|WHERE expr];
或者简写:
{DESCRIBE|desc} 表名称;
重命名表
sql
rename table 旧表名 to 新表名;
alter table 旧表名 rename [to] 新的表名;
修改表字段(列)
表中添加字段ADD
sql
alter table 操作的表名
add [column] 字段名称 字段类型 [NOT NULL] [default 默认内容][添加位置(after 后者字段)];
- 添加位置那里,
AFTER
则会添加到后者字段的后面,还可以使用first
添加到表的第一列,否则则默认添加到末尾。
修改字段名CHANGE
sql
alter table 表名字
change [column] 字段原名 字段新名 字段类型 [NOT NULL][DEFAULT],
change 字段原名2 字段新名2 字段类型2;
可以同时修改多个字段,只需要用逗号隔开
修改默认值ALTER
sql
alter table 表 ALTER [COLUMN] 字段名 SET DEFAULT 默认值;
修改字段类型MODIFY
只能修改字段类型,通过FIRST
和AFTER
在表中的位置,不能修改字段名
sql
alter table 表 modify [COLUMN] 字段名 字段类型 FIRST;
删除字段
sql
alter table 表名 drop [COLUMN] 字段名;
4.数据更新
插入数据INSERT
IDENTITY
属性的,系统会自动生成序列号值来唯一标识DEFAULT
默认属性,可以填DEFAULT来设置为默认值AUTO_INCREMENT
自增属性的,在insert语句中最后只会引用0,所以可以直接填0
sql
insert [into] 表(列1,列2) {values|value} ('内容','内容');
例子:
insert into user_1(id,name) values(1,'admin');
如果插入所有数据,可以不指定插入的字段名:但是带有字段名更加安全。
insert into user_1 values(0,'admin',1,DEFAULT);
插入部分列值数据:
sql
INSERT 表 SET 列="内容";
插入子查询数据
sql
INSERT 表 select ...
修改数据UPDATE
SQL
update 表 set 列名1='内容', 行名2='内容' [where 条件][order by...][limit...];
例子:
update user_1 set name='user' where id=1;
删除数据DELETE
delete删除的是表内的数据,不是关于表的定义
SQL
delete from 表 [where 条件][order by...][limit...];
例子:
delete from user_1 where id=0010;
清空表:
delete from user_1;
5.数据查询SELECT
select可以进行各种运算,例如执行下面的语句:
sql
select 1+1;
会返回数值2
必须按照下面的顺序:
sql
SELECT [ALL|distinct|distinctrow] 字段名 FROM 表名
[WHERE 条件]
[group by ]
[having]
[order by]
[limint]
[union]
distinct
和distinctrow
是同义词,用于消除查询结果集中的重复 的数据,没有指定这些选项则默认为ALL
。
关系运算
关系代数是一种过程化查询语言。它包括一个运算的集合,这些运算以一个或两个关系为输入,产生一个新的关系作为结果。关系代数的基本运算有:
名称 | 英文 | 符号 |
---|---|---|
选择 | select | σ |
投影 | project | Π |
并 | union | ∪ |
集合差 | set-difference | - |
笛卡儿积 | Cartesian-product | × |
更名 | rename | ρ |
除了上面的6种基本运算之外,还有一些其他运算,其他运算是可以用基本运算来表示的。但是在实际中,我们为了方便使用,单独的建立了一种运算来表示,其他运算有:
名称 | 英文 | 符号 |
---|---|---|
集合交 | intersection | ∩ |
自然连接 | natural join | ⋈ |
赋值 | assignment | ← |
选择σ
英文: select
字符: σ
选择运算在关系中选择出能够满足给定谓词的元组。将那些不满足谓词的元组剔除,组成一个新的关系。在σ后面小写谓词代表查询条件,括号中写要操作的关系。可以使用=,≠,>,<,≤,≥来进行谓词的判断。另外,也可以使用and(∧)or(∨)not(﹁)将多个谓词组合成一个较大的谓词。
σ 条件 ( 表 ) σ_{条件}(表) σ条件(表)
σ s a l s r y > 10000 ( i n s t r u c t o r ) σ_{salsry>10000}(instructor) σsalsry>10000(instructor):从集合
instructor
中取出工资salary
大于10000的大佬。σ a g e > 20 ∧ s a l a r y > 10000 ( U s e r ) σ_{age>20∧salary>10000}(User) σage>20∧salary>10000(User):在User关系中查找出年龄大于20并且工资高于10000的所有元组并返回这些元组组成的关系
你可能更加熟悉SQL,同样的操作,写成SQL就是
mysqlselect * from instructor where salary > 2000;
投影∏
英文: project
字符: Π
如果我们只对一个关系中的某些属性感兴趣而不是所有,那么我们使用投影关系来选择出我们想要的属性,投影关系返回一个仅含有这些属性的关系。因为关系是集合,所以将返回的关系中所有重复的元组将被剔除。
π 字段 ( 表 ) 或者 : ∏ 字段 ( 表 ) π_{字段}(表)\\ 或者:\\ ∏_{字段}(表) π字段(表)或者:字段∏(表)
如想从集合
instructor
中取出姓名name
和性别gender
,写成关系代数就是: ∏ n a m e , g e n d e r ( i n s t r u c t o r ) ∏_{name,gender}(instructor) ∏name,gender(instructor)。关系代数和SQL语句一样,可以「嵌套」,写法非常自然。从上面条件筛查出来的高工资大佬中拿到他们的姓名和性别,写成关系代数就是: ∏ n a m e , g e n d e r ( σ s a l s r y > 10000 ( i n s t r u c t o r ) ) ∏{name,gender}(σ{salsry>10000}(instructor)) ∏name,gender(σsalsry>10000(instructor))。
并∪
英文: union
字符: ∪
有时我们需要把两个关系中的内容联系起来,或者一个关系经过不同的查询,我们希望把结果联系在一起。这就要使用并运算。没有什么不同的,和集合中的并很相似。需要注意的是,并运算处理的两个关系必须具有相同的属性,否则并运算将没有意义。
Π n a m e ( σ a g e > 18 ( U s e r ) ) ∪ Π n a m e ( σ a d d r e s s = " N e w Y o r k " ( H o m e ) ) Π_{name}(σ_{age>18}(User))∪Π_{name}(σ_{address="NewYork"}(Home)) Πname(σage>18(User))∪Πname(σaddress="NewYork"(Home))
:在User关系中找出所有年龄大于18的姓名,在Home关系中找出所有家在NewYork的人的姓名,将这两个关系取并集,得到一个并关系。
差 -
英文: set-difference
字符: -
我们用一个关系A差运算另个一个关系B,表示剩下A中有但是B中没有的元组组成的关系。和并运算相同的,我们必须保证-运算在相容的关系之间进行。
Π n a m e ( σ a g e > 18 ( U s e r ) ) − Π n a m e ( σ a d d r e s s = " N e w Y o r k " ( H o m e ) ) Π_{name}(σ_{age>18}(User))-Π_{name}(σ_{address="NewYork"}(Home)) Πname(σage>18(User))−Πname(σaddress="NewYork"(Home))
在User关系中找出所有年龄大于18的姓名,在Home关系中找出所有家在NewYork的人的姓名,得到User中存在而Home中不存在的人的姓名的关系。
交∩
英文: intersection
字符: ∩
集合交运算表示出在A和B两个关系中都存在的元组的新关系。A和B两个元组应该是属性相同的。交运算是其他运算而不是基础运算。我们可以通过 A-(A-B) 得到A∩B。
Π n a m e ( σ a g e > 18 ( U s e r ) ) ∩ Π n a m e ( σ a d d r e s s = " N e w Y o r k " ( H o m e ) ) Π_{name}(σ_{age>18}(User))∩Π_{name}(σ_{address="NewYork"}(Home)) Πname(σage>18(User))∩Πname(σaddress="NewYork"(Home))
在User关系中找出所有年龄大于18的姓名,在Home关系中找出所有家在NewYork的人的姓名,将这两个关系中都存在的姓名取出作为新的关系。
笛卡尔乘积×
英文: Cartesian-product
字符: ×
有时我们需要把两个不相关的关系连接起来,但是这两个关系之中的属性却各不相同。对于这种不相容的情况我们不能使用交并差运算。笛卡儿乘积,用第一个关系A中的一个元组和第二个关系B中的所有元组结合,创造出一条包含着所有属性的新元组(如果在两个关系中有同名属性c,则在新关系中用A.c和B.c分别来表示)。这样得到的新关系中一共有A的元组数乘以B的元组数条信息。
如上图所示,最右边的表是左边两个表的乘积。表1的每一行一共可以和表2的3行组合,表1一共3行,故最终一共3×3=9行。
若两个表做笛卡尔乘积,结果集的行数是两个表行数的乘积。
User × Home 将User关系和Home关系做笛卡儿乘积运算
连接⋈
英文: natural join
字符: ⋈
有的时候我们需要把两个属性并不是完全相同的关系连接在一起,就像笛卡儿积做的那样。但是我们又不想直接使用笛卡儿积,因为这种方法实在是耗时耗力,我们希望得到更为简练有效的数据。这时我们就需要自然连接。自然连接将两个关系A和B的共同属性作为根本,将两个表中这些共同属性的值都相同元组拼接在一起作为一个新的元组,而将剩下不能拼接的部分全部舍弃,这样得到一个新的关系。
自然连接也是一个其他运算。我们可以先将A和B关系做笛卡儿积,然后基于两个关系中相同的属性做相等性判断,去掉不等的元组,最后将属性简化,得到自然连接的结果。
不过在操作多个表的时候,通常使用连接,而不是笛卡尔积。
R > i θ j < S = σ i θ j ( R × S ) R>{iθj}<S=σ{iθj}(R×S) R>iθj<S=σiθj(R×S)
R、S代表两个字段;
i、j代表两个字段第i列和第j列的属性;
θ代表运算符;
×笛卡尔积。
连接两个表格,只需要筛选结果集就可以了。如有两个表,一个表示授课教师
instructor
,一个是课程信息course
,他们分别包含name
属性和teacher
属性,都表示「教师姓名」。⋈ i n s t r u c t o r . n a m e = c o u r s e . t e a c h e r ( i n s t r u c t o r , c o u r s e ) ⋈_{instructor.name=course.teacher}(instructor,course) ⋈instructor.name=course.teacher(instructor,course)
User ⋈ Home 将User关系和Home关系做自然连接
更名ρ
英文: rename
字符: ρ
读音: rho
关系表达式的结果没有给我们能够引用的名字。如果想要引用一个产生的关系,最基础的就是把这句语句再写一遍,但是这种方法不是很好的。我们可以通过ρ表示更名或是命名,为一个关系起个名。
ρ a d u l t ( Π n a m e ( σ a g e > 18 ( U s e r ) ) ) ρ_{adult}(Π_{name}(σ_{age>18}(User))) ρadult(Πname(σage>18(User)))将User关系中所有年龄大于18的人的姓名取出作为一个新的关系,并把这个关系起名为adult。
赋值运算←
英文: assignment
字符: ←
实际上,赋值和更名很像,只不过赋值可以单独的写在一句话中,下面可以使用箭头左侧的名字作为右边关系的表示。
temp1 ← Π n a m e ( σ a d d r e s s = " N e w Y o r k " ( H o m e ) ) Π_{name}(σ_{address="NewYork"}(Home)) Πname(σaddress="NewYork"(Home))
temp2 ← Π n a m e ( σ a g e > 18 ( U s e r ) ) Π_{name}(σage>18(User)) Πname(σage>18(User))
temp1 ∩ temp2
在User关系中找出所有年龄大于18的姓名,在Home关系中找出所有家在NewYork的人的姓名,将这两个关系中都存在的姓名取出作为新的关系。
例题:
S(++SNO++ , SN, AGE, SEX)
C(++CNO++ , CN, CREDIT)
SC(++SNO++ , ++CNO++, SCORE)
- 查询课程号为
C1
的学生的学号和成绩:∏ S N O , S C O R E ( σ C N O = ′ C 1 ′ ( S C ) ) ∏{SNO,SCORE}(σ{CNO='C1'}(SC)) ∏SNO,SCORE(σCNO=′C1′(SC))
- 查询课程号为
C2
的学生的学号和姓名:∏ S N O , S N ( σ C N O = ′ C 2 ′ ( S ⋈ S C ) ) ∏{SNO,SN}(σ{CNO='C2'}(S⋈SC)) ∏SNO,SN(σCNO=′C2′(S⋈SC))
或者写为(先查找C2的学生号,在连接学生表S):
∏ S N O , S N ( ∏ S N O ( σ C N O = ′ C 2 ′ ( S C ) ) ⋈ S ) ∏{SNO,SN}( ∏{SNO}(σ_{CNO='C2'}(SC))⋈S) ∏SNO,SN(∏SNO(σCNO=′C2′(SC))⋈S)
课件上是这个: ∏ S N O , S N ( ∏ S N O , C N O ( σ C N O = ′ C 2 ′ ( S C ) ) ⋈ S ) ∏{SNO,SN}( ∏{SNO,CNO}(σ_{CNO='C2'}(SC))⋈S) ∏SNO,SN(∏SNO,CNO(σCNO=′C2′(SC))⋈S)
- 查询课程名字为
maths
的学生的学号和姓名:∏ S N O , S N ( σ C N = ′ m a t h s ′ ( S ⋈ S C ⋈ C ) ) ∏{SNO,SN}(σ{CN='maths'}(S⋈SC⋈C)) ∏SNO,SN(σCN=′maths′(S⋈SC⋈C))
- 查询课程号为
C3
或C4
的学生的学号:∏ S N O ( σ C N O = ′ C 3 ′ ∨ C N O = ′ C 4 ′ ( S C ) ) ∏{SNO}(σ{CNO='C3'∨CNO='C4'}(SC)) ∏SNO(σCNO=′C3′∨CNO=′C4′(SC))
- 查询没有选修课程号为
C5
的学生的学号,姓名:∏ S N O , S N ( S ) − ∏ S N O , S N ( σ C N O = ′ C 5 ′ ( S C ⋈ S ) ) ∏{SNO,SN}(S)-∏{SNO,SN}(σ_{CNO='C5'}(SC⋈S)) ∏SNO,SN(S)−∏SNO,SN(σCNO=′C5′(SC⋈S))
所有数据
使用*
通配符
sql
select * from 表名;
投影
显示部分数据
sql
select 字段名 from 表名;
例子:
select id, name from user_1;
别名
在打出e.后会自动出现后面的英文字段名,方便。
sql
select 别名.字段 [AS] 列别名, 别名.字段 [AS] 列别名 from 表 别名;
例子:
select e.sex, e.name from vipUser e;
select e.sex as'性别', e.name '名字' from user_1 e;
数据别名
sql
select e.sex
case when e.sex='0' then '女'
else '男'
end [as] '性别' from user_1 e;
连接显示:
sql
select concat("内容1:", 字段, "内容2:", 字段) as '别名' from 表;
例子:
select concat("内容1:", name, "内容2:", job) as '工作信息' from user_1;
则显示:
内容1:name内容2:job
限定查询WHERE
比较运算
比较运算符 | 说明 |
---|---|
= | 等于 |
<>、!= | 不等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
<=> | 不会返回unknown |
sql
select * from 表 where 条件;
select * from emp where sal>=2000 and sal<=8000;
select * from emp where sal <> '2000'; -- 这里<>是!=的意思
- between...and...
仅限于数值、日期、时间
sql
SELECT * FROM emp WHERE sal BETWEEN 2000 AND 8000;
- IN
SQL
select * from emp where sal in(2000,8000);
select * from emp where sal=2000 or sal=8000;
- NULL
SQL
select * from emp where sal not in(2000); -- 不是2000的其他数据
select * from emp where comm is not null; -- comm不是空
select * from emp where comm is null; -- comm是空
模糊查询
sql
select * from 表 where 字段 like 'm%'; -- 以 s 开头的
select * from emp where job like '_m%'; -- 第二的字母是m
select * from emp where job like '%m%'; -- 包含 m 的
select * from emp where job not like 'm%'; -- 不是m开头的
子查询
子查询就是指在一个完整的查询语句中,嵌套若干个不同功能的小查询,从而完成一个复杂的查询。把一个查询的结果当成另一个查询的条件。
分组查询GROUP BY
将结果集的数据行根据选择列的值进行逻辑分组,汇总表内容的子集,即实现对每个组的的聚合计算。
SQL
SELECT 1,2 count<*> as '总数' FROM 表 group by {col_name|expr|position} [ASC|DESC], ...[WITH ROLLUP];
例子:
SELECT 1,2 count<id> as '总数' FROM 表 group by 1,2;
ASC
表示升序分组,默认是升序DESC
表示降序分组with rollup
指定在结果集中不仅包含分组后的数据行,还包含汇总行,以及所有分组的整体汇总行
过滤分组HAVING
sql
SELECT 1,2 FROM 表 GROUP BY 1,2 HAVING 条件;
排序ORDER BY
SQL
select * from 表 order by 字段; -- 由小到大排序
select * from 表 order by 字段 desc; -- 由大到小排序
例子:
SELECT * FROM 表 ORDER BY 字段1 EDSC, 字段2 DESC;
分页LIMIT
当select返回的结果集中行数有很多时,使用limit
来限制用户对结果数据的浏览和操纵
offset
偏移量:从第几行开始显示(从0开始)
数量:显示几行
sql
LIMIT {[offset,]行数|行数 OFFSET 从第几行-1}
SELECT * 1,2 FROM 表 ORDER BY 1 LIMIT 4,3; -- 从第5行开始输出3行
SELECT * 1,2 FROM 表 ORDER BY 1 LIMIT 3 OFFSET 4;
多表查询
交叉连接
会产生笛卡尔积效应:
如果表1有100条数据,表2有100条数据,那么结果集就有100*100=10000条
sql
select * from 表1,表2;
select * from 表1 cross join 表2;
内连接
添加表与表之间的关联条件,消除笛卡尔积效应:
sql
select * from 表1 e, 表2 d where e.字段1 = d.字段1;
SELECT * FROM table1 e inner join table2 d on e.字段 = d.字段;
内连接是系统默认的表连接,所以在from字句中可以省略inner
只用join
就可以
- 等值连接
在ON
字句中的连接条件使用运算符=
- 非等值连接(不等连接)
在ON
字句中的连接条件使用运算符=
之外的比较运算符
- 自链接
sql
select e.1, e.2, e.3, m.1, m.2 from 表1 e, 表1 m where e.3 = m.2;
外连接
连接的两张表分为基表、参考表
- 左链接
以左边的数据为主(基表),所以保留的是左边关系是所有元组。右边数据(参考表)的如果匹配到了就显示,没有匹配到就用空值代替
sql
select e.1, e.2, d.1, d.2 from emp1 e left [OUTER] join emp2 d on e.3 = d.3;
- 右链接
以右面的数据为主(基表)
sql
select e.1, e.2, d.1, d.2 from emp1 e right [OUTER] join emp2 d on e.3 = d.3;
结果集合并
sql
select * from 表;
union -- 两个查询显示在一个结果里面,重复不显示
select * from 表;
sql
select * from dept;
union ALL -- 返回查询结果的全部内容,重复数据也会显示
select * from dept;
计算列值-函数
sql
select id+1000 FROM user_1;
函数名称 | 描述 | 函数类型 |
---|---|---|
COUNT(*列) | 求出全部的记录数(项数),返回int类型的整数 | 统计函数 |
SUM(列) | 求出总和(表达式中所有值的和) | 列=字段 |
AVG(列) | 平均值 | |
MAX(列) | 最大值 | |
MIN(列) | 最小值 | |
STD或stddev | 返回给定表达式中的所有值的标准值 | |
variance | 返回给定表达式中的所有值的方差 | |
group_concat | 返回由属于一组的列值连接而成的结果 | |
BIT_AND | 逻辑或 | |
BIT_OR | 逻辑与 | |
BIT_XOR | 逻辑异或 | |
ADDDATE(日期,数字) | 制定的日期加上指定的天数,求出新的日期 | 日期函数 |
LAST_DAY(日期) | 求出指定日期的最后一天 | |
now() | 获取当前时间 | |
ROUND(数字,保留位数) | 对小数进行四舍五入,可以指定保留的位数,如果不指定则表示将小数点之后的数字全部进行四舍五入如 | 数值函数 |
MOD(数字,数字) | 取模 | |
UPPER(列,字符串) | 将字符串的内容全部转为大写 | 字符函数 |
LOWER(列,字符串) | 将字符串的内容全部转为小写 | |
LENGTH(列,字符串) | 求出字符串的长度 | |
SUBSTR(列,字符串,起始索引,长度) | 截取字符串 | |
REPLACE(列,字符串) | 字符串替换 | |
TRIM(列,字符串) | 去掉左右空格 | |
INSTR(列,字符串,要查找的字符串) | 查找字符串中某个字符的索引,如果匹配到就返回索引,匹配不到就返回0 |
例如获取当前系统的时间:
sql
select now() '时间' from 表 where empno=7369;
6.约束
三种约束:
- 实体完整性约束
- 参照完整性约束
- 用户定义完整性约束
主键
sql
create table user_1(
id int primary key auto_increment, -- primary key主键约束,表示一个唯一的标识,auto_increment表示数据自增
name varchar(20) not null, -- 非空约束,此字段的内容不允许为null
email varchar(50) unique, -- 唯一约束,此列的内容不允许出现重复
sex char(4),
phone varchar(20)
);
有auto_increment
的数据不输入也会自增填入数据,必须是int类型,只能有一个和primary key
搭配
复合主键,在最后加上主键的定义
sql
primary key(id1, id2)
外键
sql
foreign key (这个表里的字段名) references 关联表 (关联表的字段) [on delete restrict|cascade|set null|no action]
on delete restrict
因为子表中有引用,则父表不能删除on update cascade
更新后,级联更新on update set null
若父表更新,则子表内容变为空on delete no action
不允许有动作,与RESTRICT同义
sql
create table worker(
id int primary key auto_increment,
name varchar(30),
user_id int references work_1,
);
或者:
foreign key (user_id) references work_1 (id) -- 外键约束,我们实际上使用的是上面一行(实际开发用的少)
命名约束
sql
constraint 约束名字 foreign key (这个表里的字段名) references 关联表 (关联表的字段)
删加
sql
alter table 表 add constraint 约束名 (字段名) -- 添加约束
alter table 表 add constraint unique (phone) -- 给phone添加唯一约束
alter table 表 drop index 字段 -- 删除唯一约束
MySQL中约束:
语言 | 名称 | 描述 |
---|---|---|
not null | 非空约束(nk) | 如果使用非空约束,在此字段的内容不允许为null |
unique | 唯一约束(uk) | 此列的内容不允许出现重复 |
primary key | 主键约束(pk) | 表示一个唯一的标识,一般都是自动递增,不能为空 |
主外键约束(fk) | 是在两种表上建立关联约束,加入关联约束后两张表就产生关系 | |
7.视图
视图是从基表中导出的逻辑表,它不像基表一样物理地存储在数据库中,视图没有自己独立的数据实体,它是一个虚拟表。视图作为一种基本的数据库对象,是查询一个表或多个表的另一种方法,通过将预先定义好的查询作为一个视图对象存储在数据库中,然后就可以像使用表一样在查询语句中调用它。
随着数据变化的虚拟表:视图是存储在数据字典里的一条select语句。
特点:
- 虚表,是从一个或几个基本表(或视图)导出的表。
- 只存放视图的定义,不存放视图对应的数据。
- 基表中的数据发生变化,从视图中查询出的数据也随之改变。
- 视图之上可以再定义视图。
视图的优点:
- 集中分散数据 :可以有选择性的选取数据库里的部分
- 简化查询语句:可以把复杂的查询变的简单
- 重用SQL语句:视图不包含数据,可以便捷的重复使用
- 保护数据安全 :只授予用户使用视图的权限
- 共享所需数据:数据具有独立性(存一次),试图可从多个表检索数据
- 更改数据格式:可以重新格式化检索出的数据,输出到其他应用程序之中
创建
sql
CREATE VIEW 视图名称 AS 子查询 [with check option]
CREATE VIEW 视图名称 AS 子查询 with [cascaded|local] check option
- 加上
with check option
可以后续对视图数据进行修改 CASCADED
为默认选型,他会对所有的视图进行检查LOCAL
则使CHECK OPTION 只对定义的视图进行检查
修改
sql
create or replace view 视图名称 as 查询语句 [with check option];
或者
alter view 视图名称 as 查询语句 [with check option];
查看定义
sql
show create view 视图名字;
或者
desc 试图名字;
查看
从用户角度:查询视图与查询基本表相同;更新视图与更新基本表相同;通过视图进行查询没有任何限制,用户可以将注意力集中在其关心的数据上,而非全部数据,这样就大大提高了运行效率与用户满意度。
如果数据来源于多个基本表结构,或者数据不仅来自与基本表结构,还有一部分数据来源于其他视图,并且搜索条件又比较复杂,需要编写的查询语句就会比较烦琐,此时定义视图就可以使数据的查询语句变得简单可行。
定义视图可以将表与表之间的复杂的操作连接和搜索条件对用户不可见,用户只需要简单地对一个视图进行查询即可,所以,视图虽然增加了数据的安全性,但是不能提高查询的效率。
sql
SELECT * FROM VIEW 视图名称;
数据更新
视图看上去非常像数据库的物理表,对它的操作同任何表一样。当通过视图修改时,实际上是在改变表(视图定义中涉及的表)中的数据;相反地,基本数据的改变也会自动反映在由基表产生的视图中。由于逻辑上的原因,有些Oracle视图可以修改对应的基表,有些则不能(仅能查询)。
查询方法&更新方法:
- 实体化视图:有效性检查:检查所查询的视图是否存;执行视图定义,将视图临时实体化,生成临时表;查询视图转换为查询临时表;查询完毕删除被实体化的视图(临时表)。
- 视图消解法:进行有效性检查,检查查询的表、视图等是否存在。如果存在,则从数据字典中取出视图的定义;把视图定义中的子查询与用户的查询结合起来,转换成等价的对基本表的查询;执行修正后的查询。
视图更新有限制,要求定义视图时:
- select子句中的目标列不能包含聚集函数;
- select子句中不能使用distinct关键字;
- 不能包括group by子句;
- 不能包括经算术表达式计算出来的列;
- 不能从两个以上的基本表中导出;
- 视图定义中不能有嵌套查询
一般来说,对于行列子集视图可以更新,其他视图更新有限制或者不能。
-
插入INSERT
-
修改UPDATE
-
删除DELETE
删除
sql
drop view [if exists] 视图名;
IF EXISTS
可以防止因为删除不存在的视图时而出现的问题
8.索引
给字段添加索引是为了提高查询效率,但不是所有的字段都可以添加索引,创建索引有以下特点
创建建索引列的特点:
- 在经常需要搜索的列上,可以加快搜索的速度
- 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构
- 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;
- 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间
sql
alter table 表名 add index 索引名(该表中的某字段); 添加索引
alter table emp add index sal_index(sal);
alter table 表名 drop index 索引名; 删除索引
alter table emp drop index sal_index;
三种索引:唯一索引、主键索引和聚集索引。
普通索引
最基本的索引,而且没有唯一性之类的限制。
创建:create index [indexName] on [TableName] ([column],...)
删除:drop index [tableName].[indexName]
唯一索引
不允许其中任何两行具有相同索引值的索引。当现有数据中存在重复的键值时,大多数数据库不允许将新创建的唯一索引与表一起保存。数据库还防止添加,将在表中创建重复键值的新数据。
例如,如果在 employee 表中职员的姓 (lname) 上创建了唯一索引,则任何两个员工都不能同姓。
创建: create Unique index [indexName] on [TableName] ([column],...)
删除:drop index [TableName].[IndexName]
- 主键索引
数据库表经常有一列或列组合,其值唯一标识表中的每一行。该列称为表的主键。在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。建议建立唯一索引时,直接创建主键索引就好了。
- 聚集索引
该索引中键值的逻辑顺序决定了表中相应行的物理顺序。聚集索引类似于电话簿,按姓氏排列数据。由于聚集索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚集索引。但该索引可以包含多个列(组合索引),就像电话簿按姓氏和名字进行组织一样。
创建:CREATE cluster index [IndexName] ON TableName
聚集索引使用注意事项:
(1) 定义聚集索引键时使用的列越少越好;
(2) 使用下列运算符返回一个范围值的查询:BETWEEN、>、>=、< 和 <=,可以按物理顺序更快的返回一个范围;
(3) 被连续访问的列;
(4) 返回大型结果集的查询;
(5) 经常被使用表联接或 GROUP BY 子句的查询访问的列;一般来说,这些是外键列。对 ORDER BY 或 GROUP BY 子句中指定的列进行索引,可以使 SQL Server 不必对数据进行排序,因为这些行已经排序。这样可以提高查询性能;
(6) OLTP 类型的应用程序,这些程序要求进行非常快速的单行查找(一般通过主键)。应在主键上创建聚集索引;
- 非聚集索引
数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置。非聚集索引中的项目按索引键值的顺序存储 ,而表中的信息按另一种顺序存储(这可以由聚集索引规定)。对于非聚集索引,可以为在表非聚集索引中查找数据时常用的每个列创建一个非聚集索引。有些书籍包含多个索引。例如,一本介绍园艺的书可能会包含一个植物通俗名称索引,和一个植物学名索引,因为这是读者查找信息的两种最常用的方法。
创建CREATE noclustered index [IndexName] ON TableName
9.触发器
触发器是用户定义在基本表上的一类由事件驱动的特殊过程。由服务器自动激活, 能执行更为复杂的检查和操作,具有更精细和更强大的数据控制能力。使用 CREATE TRIGGER 命令建立触发器。
每个表的一个时刻下每一个事件仅有一个触发器
sql
CREATE TRIGGER trigger_name
trigger_time
trigger_event ON tbl_name
FOR EACH ROW
trigger_stmt
trigger_name:标识触发器名称,用户自行指定
trigger_time:标识触发时机,取值为BEFORE 或AFTER
trigger_event:标识触发事件,取值为INSERT、UPDATE 或 DELETE
tbl_name:标识建立触发器的表名,即在哪张表上建立触发器
trigger_stmt:触发器程序体,可以是一句SQL语句,或者用 BEGIN 和 END 包含的多条语句。
列:创建两种表t1,t2两种表中都有id,name字段,新加t1表记录后自动添加t2
sql
CREATE TRIGGER triggen_1
after
insert ON t1
FOR EACH ROW
insert into t2(name) values(new.name);
- NEW是新值,OLD是旧值
INSERT只有NEW
UPDATE有NEW和OLD
DELETE只有OLD
注意:一般情况下,Mysql默认是以;号作为结束执行语句。在创建触发器过程中需要用到;号。为了解决这个问题,可以用到delimiter语句。例如delimiter //
,可以将结束符号变成//,创建完触发器后再执行delimiter ;
将结束符号改回成;
号。
查看
sql
show TRIGGERS
删除
sql
DROP TRIGGER 触发器的名字
备份与恢复
导出一整个数据库:
cmd
C:\WINDOWS\system32> mysqldump -u 用户名 -p 数据库名 > 导出的文件名
C:\WINDOWS\system32> mysqldump -u root -p user > d:\demo.sql
导出一张表:
cmd
C:\WINDOWS\system32> mysqldump -u 用户名 -p 数据库名 表名称 > 导出的文件名
C:\WINDOWS\system32> mysqldump -u root -p user user_1 > d\demo.sql
恢复:
数据的回复必须要先登录,登录成功后新建一个数据库,进入到指定的数据库中执行如下命令
cmd
mysql> Source 脚本目录(绝对路径)
mysql> Source C:\java\demo.sql
Linux防火墙修改
shell
vim /usr/lib/firewalld/services/ssh.xml
<port protocol="tcp" port="3306"/>
systemctl restart firewalld
其他机器连接本地的MySQL
shell
mysql> GRANT ALL PRIVILEGES ON *.* TO root@"%" IDENTIFIED BY "root" with grant option;
.
就是所有
Linux禁止更新(推荐设置)
我们在安装之后,为了能够正常运行,我们会禁止MySQL进行更新。因为在yum更新了MySQL之后,MySQL会自动重启,这对于我们上线部署项目来说是没有必要的,所以我们可以屏蔽更新。
vim /etc/yum.conf
exclude=mysql-community-client,mysql-community-common,mysql-community-libs,mysql-community-server
mysql无法输入中文
mysql数据库"不能插入中文"解决办法 - 付杰博客 (fujieace.com)
报错:
ERROR1366 (HY000): Incorrect string value: '\xD5\xC5\xC8\xFD' for column'username' at row 1
mysql
status; 查看客户端编码字符状态
C:\Program Files\MySQL\MySQL Server 5.7\bin\mysql.exe
Ver 14.14 Distrib 5.7.30, for Win64 (x86_64)
Connection id: 4
Current database:
Current user: root@localhost
SSL: Cipher in use is ECDHE-RSA-AES128-GCM-SHA256
Using delimiter: ;
Server version: 5.7.30-log MySQL Community Server (GPL)
Protocol version: 10
Connection: localhost via TCP/IP
Server characterset: latin1
Db characterset: latin1
Client characterset: gbk
Conn. characterset: gbk
TCP port: 3306
Uptime: 12 min 16 sec
注意:client characterset:gbk;
一定要是gbk,不能是utf8;
mysql
show variables like "%character%"; 查看所有编码字符
+--------------------------+---------------------------------------------------------+
| Variable_name | Value |
+--------------------------+---------------------------------------------------------+
| character_set_client | gbk |
| character_set_connection | gbk |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | gbk |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | C:\Program Files\MySQL\MySQL Server 5.7\share\charsets\ |
+--------------------------+---------------------------------------------------------+
8 rows in set, 1 warning (0.01 sec)
注意两个地方:character_set_client 和 character_set connection ,这两个地方一定要是gbk;
修改为utf8:
cmd
mysql>set character_set_database=utf8;
mysql>set character_set_server=utf8;
-
解决表无法插入中文
经过上面的修改后,以后数据库创建的表默认的编码都是utf8,可以插入中文了,但是在修改编码前已经创建的表编码还是latin1,还是不能插入中文,有两种解决办法:
-
第一种方法:最直接明了,删表重建,但是有些麻烦
-
第二种方法:使用下面语句,tablename换成你的表名,该语句的作用就是把表的编码换成utf8
mysql
alter table `tablename` convert to character set utf8;
关于 gbk,为了各方面的兼容,也有人用 utf8mb4 编码