简述
文档
特点
免费;开源;跨平台;真的好用!
sql的使用
sql的基本概念
什么是sql SQL全称是Structured Query Language:结构化查询语言<br>其实就是定义了操作所有关系型数据库的规则
。
安装
下载
去官网(www.sql.com)→DOWNLOADS→sql Community (GPL) Downloads →sql Installer for Windows
安装: 目录为C:\Program Files\sql\sql Server 8.0
配置: 系统环境变量的PATH编辑添加安装的bin目录
卸载
去C:\ProgramData\sql\sql Server 8.0目录下找到my.ini文件
,并复制datadir=C:/ProgramData/sql/sql Server 8.0\Data
写在sql
删除C:\ProgramData下的sql文件夹
sql相关配置
服务的启动
1、手动。计算机管理→服务
2、cmd→services.msc 打开服务的窗口
3、使用管理员打开cmd
net start sql:启动sql的服务
net stop sql:停止sql的服务
登录与退出
格式:
sql -h主机名 -u用户名 -密码
各参数以及意义:
-h:表示启动服务器程序的计算机的域名或者IP地址,如果服务器程序在本机运行的话,可省略这个参数,也可填写localhost或者127.0.0.1;还可以写为“--host=主机”的形式
-u:表示用户名,超级管理员的用户名是root;也可以是“--user=用户名”的形式
-p:表示密码;也可以是“--password=密码”的形式
退出:quit、exit、\q
连接注意事项:
- 最好不要在一行命令中输入密码;此时输入密码会被任何程序监视到,不安全。
可以先不为 -p参数指定值,如:sql -hlocalhost -uroot -p
单击回车后会提示输入密码,此时输入时安全状态 - 如果非要显式地把密码写出来,则密码值和 -p之间不能有空白字符,其他参数名之间可以有空白字符;
如:sql -h localhost -u root -p123456
- sql地各个参数地摆放顺序没有硬性规定
- 如果服务器和客户端程序安装在同一台计算器,-h参数可省略
- 如果使用的是类UNIX系统,并且省略了-u参数,则会把登录操作系统的用户名当作sql的用户名处理
sql基础
基础语法
通用语法
- SQL语句可以单行或多行书写,以分号结尾。
- 可使用空格和缩进来增强语句的可读性。
- sql数据库的SQL语句不区分大小写,关键字建议使用大写。
- 使用 \c 放弃本次操作
- 字符串的表示:用单引号('内容')或双引号("内容")把字符串内容引起来。
- 三种注释
- 单行注释:
-- 内容
←--和内容之间必须加空格 - 单行注释:
#内容(sql特有)
- 多行注释:
/*内容*/
- 单行注释:
注意事项
- 语句结束符号:(;)(\g)(\G)
- \G 比较特殊,它以垂直的形式将结果中的每个列都展示在单独的一行。
- 语句可以随意地换行,即没有语句结束符,该语句就不会结束。
- 可以一次提交多条语句。
数据类型
整数类型
类型 | 大小 | 无符号取值范围 | 有符号取值范围 |
---|---|---|---|
TINYINT | 1字节 | 0~2⁸-1 | -2⁷~2⁷-1 |
SMALLINT | 2字节 | 0~2¹⁶-1 | -2¹⁵~2¹⁵-1 |
MEDIUMINT | 3字节 | 0~2²⁴-1 | -2²³~2²³-1 |
INT或INTEGER | 4字节 | 0~2³²-1 | -2³¹~2³¹-1 |
BEGINT | 8字节 | 0~2⁶⁴-1 | -2⁶³~2⁶³-1 |
- 在数据类型后加上 UNSIGNED 单词,则表示该类型用于无符号数。
- 在数据类型后加上 SIGNED 单词,或者什么都不加,则表示该类型表示有符号数。
浮点数类型
类型 | 大小 | 取值范围 | 取值范围 | 含义 |
---|---|---|---|---|
FLOAT | 4字节 | 单精度浮点数 | ||
DOUBLE | 8字节 | 双精度浮点数 |
- 使用浮点数表示小数是不够精确的。
- 可用FLOAT(M,D)或DOUBLE(M,D)来限制可以存储到本列的小数范围。(不推荐使用)
- M表示该小数最多包含的有效数字个数
- D表示该小数保留小数点后十进制数字的个数
定点数类型
类型 | 大小 | 取值范围 |
---|---|---|
DECIMAL(M,D) | 取决于M和D | 取决于M和D |
字符串类型
类型 | 最大长度 | 存储空间要求 | 含义 |
---|---|---|---|
CHAR(M) | M个字符 | M*W字节 | 定长字符串 |
VARCHAR(M) | M个字符 | L+1或L+2字节 | 变长字符串 |
TINYTEXT | 2⁸-1字节 | L+1字节 | |
TEXT | 2¹⁶-1字节 | L+2字节 | |
MEDIUMTEXT | 2²⁴-1字节 | L+3字节 | |
LONGTEXT | 2³²-1字节 | L+4字节 |
- M 代表该数据类型最多能存储的字符数量
- W 代表在特定字符集下编码一个字符最多需要的字节数
- L 代表实际想该类型的列中存储的字符串在特定字符集下所占的字节数
CHAR(M)
- CHAR(M)中的M代表该类型最多可以存储的字符数量。
- M 的取值范围是(0~255)
- 若省略则默认为1
- CHAR(0),只能存储空字符串或NULL值
- CHAR(M)在不同的字符集下需要的存储空间也不一样
- 假设某个字符集编码一个字符最对需要W字节,则CHAR(M)占用的存储空间是M*W字节
- ASCII:W=1
- GBK:W=2
- UTF-8:W=3
- 如果实际存储的字符串在特定字符集编码下占用的字节数不足M*W,那么剩余的存储空间用空格字符补齐。
VARCHAR(M)
VARCHAR(M)对应的存储空间由下面两部分组成
真正的字符串内容
- 假设真正的字符串在采用特定字符集编码后占用的字节数为L
占用的字节数
假设VARCHAR(M)类型采用的字符集编码一个字符最多需要W字节,那么
- 当W*M < 256时,所需存储空间为 L+1
- 当W*M >= 256时,所需存储空间为 L+2
VARCHAR(M)的性能低于CHAR(M)
TEXT
表中如果有的属性需要存储特别长的文本,可考虑使用这几个类型
ENUM和SET
- ENUM类型,也就是枚举类型
- 格式:ENUM('str1','str2','str3',...)
- 对于使用ENUM类型的列,该列的值只能在给定的字符串中选取其中一个
- SET类型
- 格式:SET('str1','str2','str3',...)
- 对于使用SET类型的列,该列的值可以在给定的字符串列表中选择一个或多个
二进制类型
类型 | 占用的存储空间(单位:字节) | 含义 |
---|---|---|
BIT(M) | 近似为(M+7)/8 | 存储M个二进制位的值 |
BINARY(M) | 定长 | |
VARBINARY(M) | 变长 | |
TINYBLOB | 2⁸-1 | |
BLOB | 2¹⁶-1 | |
MEDIUMBLOB | 2²⁴-1 | |
LONGBLOB | 2³²-1 |
BIT
- M的取值范围(1~64),且M可省略,默认为1
- 若存储的比特数不足以整个字节,则按一个字节计算
BINARY(M)和VARBINARY(M)
- 与CHAR(M)和VARCHAR(M)类似
BLOB
- 用于存储可变长度的二进制数据,比如图片、音频、压缩文件等。
- 对于比较大的二进制数据,通常不直接存储到数据库管理系统中,而是保存在文件系统中,在数据库中存储文件路径。
日期和时间类型
类型 | 大小 | 范围 | 含义 |
---|---|---|---|
YEAR | 1字节 | 1901至2155 | 年份值 |
DATE | 3字节 | 1000-01-01至9999-12-31 | 日期值 |
TIME | 3字节+小数秒的大小 | -838:59:59[.000000]至838.59.59[.000000] | 时间值 |
DATETIME | 5字节+小数秒的大小 | 1000-01-01 00:00:00[.000000]至9999-12-31 23:59:59[.999999] | 日期加时间值 |
TIMESTAMP | 4字节+小数秒的大小 | 1970-01-01 00:00:01[.000000]至2038-01-19 03:24:07[.999999] | 时间戳 |
让TIME、DATETIME、TIMESTAMP支持小数秒的语法:数据类型(小数秒位数)
保留的小数秒位数 | 额外需要的存储空间 |
---|---|
0 | 0字节 |
1或2 | 1字节 |
3或4 | 2字节 |
5或6 | 3字节 |
YEAR
- 取值范围是1901~2155
- 如果想存储更大范围的年份值,可使用SMALLINT(2字节)或者字符串类型
DATE
- 表示日期,格式是YYYY-MM-DD
TIME
- 表示时间,格式是hh:mm:ss[.uuuuuu] 或者 hhh:mm:ss[.uuuuuu]
- TIME可表示一天中的某个时间,也可表示某一段时间(某两个时间的时间间隔)
- 这导致TIME可能表示的小时数比较大,并且可能为负值。
DATETIME
- 表示日期和时间,格式是YYYY-MM-DD hh:mm:ss[.uuuuuu]
- DATETIME中存储的时间必须是一天内的某个时间(也就是小时数必须小于24)
TIMESTAMP
- TIMESTAMP存储的时间所展示的值随着时区的变化而变化
文档
sql的分类
DDL(Data Definition Lauguage)数据库定义语言
- 用来定义数据库对象:数据库,表,列表,列等。
- 关键字:create,drop,alter等
DML(Data Manipulation Language)数据操作语言
- 用来对数据库中表的数据进行增删改查。
- 关键字:insert,delete,update等
DQL(Data Query Language)数据查询语言
- 用来查询数据库中表的记录(数据)
- 关键字:select,where等
DCL(Data Control Language)数据库控制语言
- 用来定义数据库的访问权限和安全级别,及创建用户。
- 关键字:GRANT,REVOKE等
DDL:操作数据库和表
操作数据库:CRUD
- C(Create):创建
- R(Retrieve):查询
- U(Update):修改
- D(Delete):删除
查询
查询所有数据库:
sqlSHOW DATABASES;
查询当前数据库:
sqlSELECT DATABASE();
创建
创建数据库:
sqlCREATE DATABASE 数据库名; 或者 CTEATE DATABASE [IF NOT EXISTS] 数据库名 [DEFAULT CHARSET 字符集] [COLLATE 排序规则]
IF NOT EXISTS:
sqlCREATE DATABASE IF NOT EXISTS 数据库名;
- 这条语句的意思是,如果指定的数据库不存在就创建,若存在就什么也不做,只提出warning
- 而用第一种方法创建数据库,若已存在,会报错(ERROR)
删除
删除数据库:
sqlDROP DATABASE 数据库名;
IF EXISTS:
sqlDROP DARABASE IF EXISTS 数据库名;
- 这条语言和前面提到的类似,在此就不做赘述。
使用
切换数据库:
sqlUSE 数据库名
- 切换当前使用的数据库,结尾分号可加可不加。
连接时选择数据库:
sqlsql -h localhost -u root -p123456 数据库名
- 这样,当成功连接服务器后,“数据库名”就是当前客户端的默认数据库。
表的基本操作
查询
查询表:
sqlSHOW TABLES [FROM 数据库名];
- 默认查询正在使用的表。
- 若查询的数据库没表,会返回 Empty set(空集)
查询表结构:
sqlDESCRIBE 表名; DESC 表名; EXPLAIN 表名; SHOW FIELDS FROM 表名; SHOW COLUMNS FROM 表名;
以上代码效果一样,都可以查询表结构。
查询指定表的建表语句
sqlSHOW CREATE TABLE 表名\G
此语句的输出是创建表时填写的语句,且自动添加属性。
创建
创建表:
sqlCREATE TABLE 表名( 列名1 数据类型 [列的属性], 列名2 数据类型 [列的属性], ... 列名n 数据类型 [列的属性] )[COMMENT `表的注释信息`];
创建表的语句可在单行,多行只为美观。最后一个语句没有逗号结尾
COMMENT
:为建表语句添加注释
IF NOT EXISTS:
sqlCREATE TABLE IF NOT EXISTS 表名( 各个列的信息 ... );
与数据库的 IF NOT EXISTS 类似,在此不多做赘述。
删除
删除表
sqlDROP TABLE 表1,表2,...,表n; -- 删除指定表,并重新创建该表 TRUNCATE TABLE 表名;
IF ESISTS
sqlDROP TABLE IF ExISTS 表名;
与数据库的 IF EXISTS 类似,在此不多做赘述。
使用
- 直接使用某个数据库中的某个表
- 数据库.表名
修改
修改表名
-- 方式一
ALTER TABLE 旧表名 RENAME TO 新表名;
-- 方式二
RENAME TABLE 旧表名1 TO 新表名1,旧表名2 TO 新表名2,...旧表名n TO 新表名n;
- 如果在修改表名的时候指定了数据库名,还可以将该表转移到对应的数据库下。
增加列
ALTER TABLE 表名 ADD COLUMN 列名 数据类型 [列的属性];
-- 添加到第一列
ALTER TABLE 表名 ADD COLUMN 列名 数据类型 [列的属性] FIRST;
-- 添加到指定列的后面
ALTER TABLE 表名 ADD COLUMN 列名 数据类型 [列的属性] AFTER 指定列名;
修改列信息
-- 修改列的数据类型和属性
-- 方式一
ALTER TABLE 表名 MODIFY 列名 新数据类型 [新属性];
-- 方式二,也可修改列名
ALTER TABLE 表名 CHANGE 旧列名 新列名 新数据类型 [新属性];
-- 将某列设置为表的第一列
ALTER TABLE 表名 MODIFY 列名 列的类型 列的属性 FIRST;
-- 将列放在指定列的后面
ALTER TABLE 表名 MODIFY 列名 列的类型 列的属性 AFTER 指定列名;
-- 若同一表中有多列修改操作,可放在一条语句
ALTER TABLE 表名 操作1,操作2,...,操作n;
删除列
-- 删除表中的列
ALTER TABLE 表名 DROP COLUMN 列名;
列的属性
简单的查询和插入
简单的查询语句
-- 查询某个表中已经存储了哪些数据
SELECT * FROM 表名;
简单的插入语句
- 在sql中插入数据的时候是以行为单位的,一行数据也成为一条记录。
INSERT INTO 表名 VALUES(列1的值,列2的值,...,列n的值);
-- 批量插入
INSERT INTO 表名(列1,列2,...) VALUES(列1的值,列2的值,...),(列1的值,列2的值,...),...;
- 也可以只指定部分的列,没有显式指定的列的值将被设置为NULL。
列的属性
默认值
-- 列的默认值为NULL,若要修改列的默认值,可在定义列的时候给列增加一个DEFAULT属性。
列名 列的类型 DEFAULT 默认值
示例:
CREATE TABLE first_table(
first_column INT,
second_column VARCHAR(100) DEFAULT 'abc'
);
-- 这样之后second_column的默认值就成为了abc
NOT NULL
-- 规定不能存放NULL,可给列添加NOT NULL属性,语法:
列名 列的类型 NOT NULL
示例:
ALTER TABLE first_table MODIFY first_column INT NOT NULL;
此后再在此列插入NULL,将会报错。
主键
- 候选键:有时候在表中可以通过某个列或某些列的列组合来确定一条唯一的记录,我们可以把这个列或者这些列的列组合称为候选键。
- 一个表中可能有多个候选键,可以选择一个候选键作为表的主键
- **主键:**一个表中只能有一个主键,主键的值不能重复,可以通过主键找到唯一的一条记录。
可以通过下面的方式定义主键:
-- 如果主键只是单个列的话,可直接在该列后面声明PRIMARY KEY。
示例:
把student_info表的“学号”列声明为主键
CREATE TABLE student_info(
number INT PRIMARY KEY,
name VARCHAR(5),
...
);
-- 也可以把主键的声明单独提取出来,用下面这样的形式声明:
PRIMARY KEY (列名1,列名2,...)
然后把主键声明放在列定义后
实例:
CREATE TABLE student_info(
number INT,
name VARCHAR(5),
...,
PRIMARY KEY(number)
);
-- 对于多个列的列组合作为主键的情况下,必须使用单独声明形式
示例:
比如student_score表中number和subject的列组合作为主键
CREATE TABLE student_score(
number INT,
subject VARCHAR(30),
score TINYINT,
PRIMARY KEY (number,subject)
);
-- 注意:主键列默认具有NOT NULL属性。
UNIQUE约束
- UNIQUE约束是列约束或表约束,它定义了将列或列组中的值约束为唯一的规则。
- 也就是值是唯一的,不可重复。
与建表语句中声明主键的方式类似,声明UNIQUE约束也有两种
-- 如果想为单个列声明UNIQUE约束,可直接在该列后填写UNIQUE或UNIQUE KEY。
示例:
把student_info表的id_number列添加UNIQUE约束
CREATE TABLE student_info(
number INT PRIMARY KEY,
name VARCHAR(5),
id_number CHAR(18) UNIQUE,
...
);
-- 也可以把UNIQUE约束的声明单独提取出来,用下面这样的形式声明:
UNIQUE [KEY] [约束名称] (列名1,列名2,...)
示例:
对id_number列的UNIQUE约束起名为uk_id_number
CREATE TABLE student_info(
number INT PRIMARY KEY,
name VARCHAR(5),
id_number CHAR(18),
...,
UNIQUE KEY uk_id_number (id_number)
);
-- 对于多个列的列组合添加UNIQUE约束,必须使用单独声明形式
- 对于约束名称:每个约束都有自己的名字。
- 主键约束的名字是PRIMARY,为sql自动添加,用户不可修改
- 而对于UNIQUE约束,可自定义,也可默认。
主键和UNIQUE约束对比:
- 两者都能保证某个列或列组合的唯一性
- 一张表中只能定义一个主键,却可以定义多个UNIQUE约束
- 主键列中不允许存放NULL,而声明了UNIQUE约束的列可以存放NULL,而且NULL可以重复的出现在多条记录中。
- 如果没有给表定义主键,sql会将第一个声明为NOT NULL并且具有UNIQUE约束的列或列组合自动定义为主键。
外键
外键约束是指用于在两个表之间建立关系,需要指定引用主表的哪一列。
CONSTRAINT [外键名称] FOREIGN KEY(列1,列2,...) REFERENCES 父表名(父列1,父列2,...);
- 外键名是可选的,仅作名字使用。
- 如果A表中的某个列或者某些列依赖于B表中的某个列或某些列,那么就称A表为子表,B表为父表。
- 子表和父表使用外键关联起来
示例:
-- 由上举例,student_score表的number列依赖于student_info的number列
-- 所以student_info是父表,student_score是子表,如下定义:
CREATE TABLE student_score(
number INT,
subject VARCHAR(30),
score TINYINT,
PRIMARY KEY (number,subject),
CONSTRAINT FOREIGN KEY(number) REFERENCES student_info(number)
);
这样之后,再向student_score表插入记录的时候,sql都会检查插入的学号是否能在student_info表中找到,找不到则会报错。
在sql中,父表中被子表依赖的列或列组合必须建立索引。
AUTO_INCREMENT
- 自增
- 可以为使用整数类型或浮点数类型的列声明该属性,在之后插入新记录时,可以不显示指定该列的值,sql会自动帮该列生成自动增长的唯一值。
列名 列的类型 AUTO_INCREMENT
示例:
CREATE TABLE first_table(
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
first_column INT,
second_column VARCHAR(100) DEFAULT 'abc'
);
将id添加AUTO_INCREMENT属性
当我们在插入新记录而忽略该列,该列的值会自增1
若显式声明该值,则以显式为准
注意:
- 一个表中最多有一个具有AUTO_INCREMENT属性的列
- 具有AUTO_INCREMENT属性的列必须建立索引。主键和具有UNIQUE属性的列会自动建立索引
- 拥有AUTO_INCREMENT属性的列不能再通过指定DEFAULT属性来指定默认值
- AUTO_INCREMENT一般作为主键的属性,来自动生成唯一标识一条记录的主键值
列的注释
-- 每个列的末尾都可以添加COMMENT语句来为列添加注释。
显示宽度与ZEROFILL
ZEROFILL简介
- 对于无符号整数类型的列,若要在查询结果中让数字左边补0,可给该列加ZEROFILL属性;
- 加入该属性后,列的类型就变为INT(10),其中“10”就是显示宽度。
- 可指定显示宽度。
注意事项
- 在创建表时,若声明了ZEROFILL属性的列没有声明UNSIGNED属性,那么sql会为该列自动生成该属性。
- 不同的整数类型有不同的默认显示宽度。TINYINT默认为4,INT默认为11;若加了UNSIGNED属性,则该类型的显示宽度减1。
- 显示宽度并不会影响列的所需存储空间以及取值范围。
- 只有列的实际值的位数小于显示宽度时,才会补0。
- 只设置显示宽度,而不设置ZEROFILL属性,则队查询结果无影响。
标识符的命名
sql不欢迎的命名方式
- 名称中全部是数字
- 名称中有空白字符
- 名称中使用了sql的保留字
- 倘若非要用,可用反引号(``)把定义的名称引起来,但也不支持空格结尾这种脑残行为
DML:操作表的数据
DML介绍
- DML全称是Data Manipulation Language(数据操作语言),用来对数据库中表的数据记录进行增删改查操作。
- 添加数据(INSERT)
- 修改数据(UPDATE)
- 删除数据(DELETE)
插入数据
- 在关系型数据库中,数据一般都是以记录(行)为单位插入表中的。
INSERT INTO 表名 VALUES(列1的值,列2的值,...,列n的值);
-- VALUES子句中参数的顺序与表中各个列的顺序一一对应
-- 在使用此语法(插入一条完整记录的语法)时,VALUES子句中必须给出表中所有列的值,若无则填NULL(前提是没有声明NOT NULL属性)。
-- 也可以显式指定列的插入顺序
INSERT INTO 表名(列1名,列2名,...,列n名) VALUES(列1的值,列2的值,...,列n的值);
-- 批量添加数据
INSERT INTO 表名(列1名,列2名,...,列n名) VALUES(值1,值2,...),(值1,值2,...),(值1,值2,...),...;
- 可以将某个查询的结果插入到表中。
INSERT IGNORE
- 对于是主键或UNIQUE键的列或列组合来说,若不存在与待插入的值相同的值,则执行,否则不执行(而不是报错)。
-- INSERT IGNORE语法
INSERT IGNORE INTO first_table(first_column,second_column) VALUES(1,'值');
-- 执行结果:Query OK,0 rows affected,1 warning(0.00 sec)
-- 这样在INSERT后加入IGNORE就不会报错,批量同样适用。
INSERT ... ON DUPLICATE KEY UPDATE
- 与INSERT IGNORE类似,但相同后会执行额外语句。如下用法
- 现有一个first_table表的first_column列拥有UNIQUE约束,如果表中不包含与待插入记录的first_column列重复的记录,那么就把这条记录插入,否则将已存在的重复记录的first_column列更新为10,second_column列更新为'雪碧'。
INSERT INTO first_table(first_column,second_column) VALUES(1,'哇哈哈') ON DUPLICATE KEY UPDATE first_column = 10,second_column = '雪碧';
- 对于作为主键或UNIQUE键的列或者列组合来说,如果表中现有的记录在这些列或列组合上与待插入记录有重复的值,则可以使用VALUES(列名)的形式来引用待插入记录中对应列的值
INSERT INTO first_table(first_column,second_column) VALUES(10,'哇哈哈') ON DUPLICATE KEY UPDATE second_column = VALUES(second_column);
删除数据
DELETE FROM 表名 [WHERE 表达式];
-- 可以使用LIMIT子句限制删除的记录数量,使用ORDER BY子句来指定删除顺序,如:
DELETE FROM first_table ORDER BY first_column DESC LIMIT 1;
更新数据
UPDATE 表名 SET 列1=值1,列2=值2,...,列n=值n [WHERE 表达式];
-- 可以使用LIMIT子句限制更新的记录数量,使用ORDER BY子句来指定更新顺序,如:
UPDATE first_table SET second_column='爽歪歪' ORDER BY first_column DESC LIMIT 1;
-- 修改id为1的数据,将name改为李三
UPDATE tb_user SET name='李三' WHERE id=1;
- 判断一个表达式的值是否为空,要用IS NULL,而非=
DQL:查询表的数据
DQL介绍
DQL英文全称是Data Query Language(数据库查询语言),数据查询语言,用来查询数据库中表的记录。
语法:
SELECT -- >字段列表
FROM -- >表名列表
WHERE -- >条件列表
GROUP BY -- >分组字段列表
HAVING -- >分组后条件列表
ORDER BY -- >排序字段列表
LIMIT -- >分页参数
子句编写顺序
- 如果在一个查询语句中出现了多个子句,那么它们之间的顺序是不能乱放的。
-- 顺序如下所示
SELECT [DISTINCT] 查询列表
[FROM 表名]
[WHERE 布尔表达式]
[GROUP BY 分组列表]
[HAVING 分组过滤条件]
[ORDER BY 排序列表]
[LIMIT 偏移量,限制条数]
子句执行顺序
[FROM 表名]
↓↓
[WHERE 布尔表达式]
↓↓
[GROUP BY 分组列表]
↓↓
[HAVING 分组过滤条件]
↓↓
SELECT [DISTINCT] 查询列表
↓↓
[ORDER BY 排序列表]
↓↓
[LIMIT 偏移量,限制条数]
简单查询
查询单列(列的别名)
查询某个表中某一列的数据的通用格式:
SELECT 列名 FROM 表名
- SELECT子句:要查询的列名
- FROM子句:要查询的表名
也可以为结果集中的列重新定义一个别名
SELECT 别名 [AS] 列的别名 FROM 表名;
- AS可有可无
SELECT number AS 学号 FROM student_info;
与下相同
SELECT number 学号 FROM student_info;
注意:别名只是在本次查询到的结果集中展示,并不会改变真实表的列名。
查询多列
查询多列,需在SELECT子句写上多个列名
SELECT 列名1,列名2,...列名n FROM 表名;
-- 带上别名
SELECT 列名1 [AS] 列的别名,列名2 [AS] 列的别名,...列名n [AS] 列的别名 FROM 表名;
查询所有列
SELECT * FROM 表名;
查询结果去重
单列去重
sqlSELECT DISTINCT 列名 FROM 表名;
多列去重
sqlSELECT DISTINCT 列名1,列名2,...列名n FROM 表名;
LIMIT
当结果集过多时,可使用LIMIT子句限制记录条数
LIMIT 限制条数
如:
SELECT number FROM student_info LIMIT 2;
默认从第1条记录开始
若不向从第一条记录开始,可用
LIMIT 偏移量,限制条数
-- 偏移量:第n条记录的偏移量就是n-1
如:
-- 从第3条记录开始,共取2条记录
SELECT number FROM student_info LIMIT 2,2;
-- 若偏移量大于或等于结果集的行数,则查询结果是空集。
分页查询
- 语法
SELECT 字段列表 FROM 表名 LIMIT 起始索引,查询记录数;
- 注意
- 起始索引从0开始,起始索引=(查询页码-1)*每页显式记录数。
- 分页查询是数据库的方言,不同的数据库有不同的实现,sql中是LIMIT。
- 若查询的是第一页的数据,起始索引可省略。
ORDER BY(排序查询)
可用ORDER BY子句显式指定排序规则
-- 单列排序
ORDER BY 列名 [ASC|DESC]
-- 多列排序
ORDER BY 列1 [ASC|DESC],列2 [ASC|DESC] ...
示例:
-- 单列升序
SELECT * FROM student_score ORDER BY score;
SELECT * FROM student_score ORDER BY score ASC;
-- 多列升序
SELECT * FROM student_score ORDER BY subject,score ASC;
-- 结合ORDER BY子句和LIMIT子句
SELECT * FROM student_score ORDER BY score LIMIT 1;
ASC和DESC指的是排序方向
- ASC是按照指定列由小到大,即升序排列。
- DESC是按照制定列由大到小,即降序排列。
- 默认是ASC。
比较字符串的大小就是依次比较每个字符的大小。
查询案例
-- 1、查询年龄为20,21岁的人员信息
SELECT * FROM tb_user WHERE age in(20,21);
-- 2、查询性别为男,且年龄为20岁的姓名为两个字的人员信息
SELECT * FROM tb_user WHERE gender='男' AND age=20 AND name LIKE '__';
-- 3、统计年龄小于20岁的男性员工的人数
SELECT * FROM tb_user WHERE age<20 AND gender='男';
-- 4、查询所有年龄小于等于20岁人员信息,并对查询结果按年龄升序排序,若年龄相同按id升序排序
SELECT * FROM tb_user WHERE age<=20 ORDER BY age ASC,id DESC;
-- 5、查询性别为男,且年龄为20岁的前3个人员信息,并对查询结果按年龄升序排序,若年龄相同按id升序排序
SELECT * FROM tb_user WHERE age=20 ORDER BY age ASC,id ASC LIMIT 3;
条件查询
语法:
SELECT 列名 FROM 表名 WHERE 条件;
运算符简述
- 各种比较运算符
运算符 | 示例 | 描述 |
---|---|---|
= | a = b | a等于b |
<=> | a <=> b | a等于b(<=> 称为NULL值安全等于运算符) |
<>或!= | a <> b | a不等于b |
< | a < b | a小于b |
<= | a <= b | a小于或等于b |
> | a > b | a大于b |
>= | a >= b | a大于或等于b |
BETWEEN | a BETWEEN b AND c | a的值必须满足 b<=a<=c |
NOT BETWEEN | a NOT BETWEEN b AND c | a的值必须不满足b<=a<=c |
- IN运算符
运算符 | 示例 | 描述 |
---|---|---|
IN | a IN (b1,b2,...) | a是b1,b2,...中的某一个 |
NOT IN | a NOT IN (b1,b2,...) | a不是b1,b2,...中的某一个 |
- NULL运算符
运算符 | 示例 | 描述 |
---|---|---|
IS NULL | a IS NULL | a的值是NULL |
IS NOT NULL | a IS NOT NULL | a的值不是NULL |
- 多条件查询
运算符 | 描述 |
---|---|
AND或&& | 符合所有搜索条件 |
OR或|| | 符合某一个搜索条件 |
- 支持模糊查询的运算符
运算符 | 示例 | 描述 |
---|---|---|
LIKE | a LIKE b | a匹配b |
NOT LIKE | a NOT LIKE b | a不匹配b |
- 算数运算符
运算符 | 示例 | 描述 |
---|---|---|
+ | a + b | 加法 |
- | a - b | 减法 |
* | a * b | 乘法 |
/ | a / b | 除法 |
DIV | a DIV b | 除法,取商的整数部分 |
% | a % b | 取余 |
- | -a | 取负值 |
- 逻辑运算符
运算符 | 示例 | 描述 |
---|---|---|
NOT(也可以写作 ! ) | NOT a | 对a取反 |
AND(也可以写作 && ) | a AND b | 全真则真 |
OR(也可以写作 || ) | a OR b | 全假则假 |
XOR | a XOR b | 只有一个为真才为真 |
简单搜索条件
使用方法
- 把搜索条件放在WHERE子句中,再将WHERE子句放在FROM子句的后面
示例:
-- 查询student_info表中名字是“狗哥”的学生的一些信息
SELECT number,name,id_number FROM student_info WHERE name = '狗哥';
-- 查询学好在2~4的学生信息
SELECT number,name,id_number FROM student_info WHERE number BETWEEN 2 AND 4;
匹配列表中元素(IN)
作用:
- 指定某一列的值是否在在个列表中
示例:
-- 查询“软件工程”和“会计”专业的学生信息
SELECT number,name,id_number,major FROM student_info WHERE major IN ('软件工程','会计');
匹配NULL
作用:
- 为某一列填入NULL意味着这一列的值尚未确定
- 判断某一列的值是否为NULL时,不能用=运算符
- 需要使用匹配NULL运算符
示例:
-- 查询student_info表中name列是NULL的学生记录有哪些
SELECT number,name,id_number,major FROM student_info WHERE name IS NULL;
若所有记录的name列的值都不是NULL,则返回Empty set
若有,则返回结果。
<=>:
- <=>运算符被称为NULL值安全等于运算符。
- 当<=>的操作数不含NULL时,其功能和 = 相同;
- 当<=>的一个操作数为NULL,另一个操作数不为NULL时,结果为0(FALSE);
- 当两个操作数都为NULL,结果为1(TRUE)。
多条件查询(AND|OR)
AND运算符
作用:
- 需要某条记录在符合所有搜索条件的时候才将其加入结果集
示例:
-- 从student_score表中找出科目为“语文”并且成绩大于75分的记录
SELECT * FROM student_score WHERE subject = '语文' AND score >75;
OR运算符
作用:
- 需要某条记录只需符合某一个搜索条件就将其加入结果集
示例:
-- 从student_score表中找出成绩大于95或者小于55分的记录
SELECT * FROM student_score WHERE score > 95 OR score < 55;
更复杂的搜索条件的组合
作用:
- 在多条件的组合时,会因为运算符优先级判断失误而导致记录错误
- 故可使用小括号来显式的指定各个搜索条件的检测顺序
示例:
-- 从student_score表中找出课程为“语文”,并且成绩大于95或者小于55分的记录
SELECT * FROM student_score WHERE (score > 95 OR score < 55) AND subject = '语文';
通配符(LIKE)
作用:
- 搜索条件是模糊的,称为模糊查询。
- 可使用通配符来代替模糊的信息。
通配符:
- % : 代表任意数量的字符,0个字符也可以。
示例:
sql-- 查询student_info表中name以“王”开头的记录 SELECT number,name,id_number FROM student_info WHERE name LIKE '王%'; -- 查询student_info表中name里包含一个“三”字 SELECT number,name,id_number FROM student_info WHERE name LIKE '%三%';
- _ :代表任意一个字符
示例:
sql-- 查询student_info表中name中以“王”开头,且只有2个字符的记录 SELECT number,name,id_number FROM student_info WHERE name LIKE '王_'; -- 查询student_info表中name是2个字符的记录 SELECT number,name,id_number FROM student_info WHERE name LIKE '__';
- 通配符不能代表NULL
转移通配符:
若待匹配字符串中包含普通字符串'%'或'_'的话,需要在其前加一个反斜杠()来和通配符区别。
- '%'代表普通字符串'%'
- '\ _'代表普通字符串' _'
分组查询
- 所谓分组,就是针对某个列,将该列的值相同的记录分到一个组中。
创建分组
- GROUP BY子句可完成分组
- 只需把分组列放在GROUP BY子句中,然后在SELECT子句的查询列表中写入想要统计的信息。
-- 语法
SELECT 字段列表 FROM 表名 [WHERE 条件] GROUP BY 分组字段名 [HAVING 分组后过滤条件];
-- WHERE和HAVING的区别
⚪执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组后对结果进行过滤。
⚪判断条件不同:where不能对聚合函数进行判断,而having可以。
-- 根据性别分组,统计男性员工和女性员工的数量
SELECT gender,count(*) FROM student_info GROUP BY gender;
- 查询列表处,不可放置非分组列
带有WHERE的分组查询
- 在划分分组之前将某些记录过滤掉,可使用WHERE子句
-- 把分数低于60分的记录删去再统计平均分
SELECT subject,AVG(score) FROM student_score WHERE score >= 60 GROUP BY subject;
作用于分组的过滤条件
- 对分组后的数据进行过滤,可以使用 HAVING子句
-- 统计平均分大于73分的课程
SELECT subject,AVG(score) FROM student_score GROUP BY subject HAVING AVG(score) > 73;
-- 统计“JAVA语言”这门课程的平均分
SELECT subject,AVG(score) FROM student_score GROUP BY subject HAVING subject = 'JAVA语言';
- HAVING子句中与汇总函数有关的条件是不能出现在WHERE子句中。
- 因为汇总函数组成的表达式不适用于判断单条记录是否符合条件。
分组和排序
- 分组查询的结果是可以进行排序的
-- 按照从大到小的顺序对各个学科的平均分进行排序
SELECT subject,AVG(score) FROM student_score GROUP BY subject ORDER BY AVG(score) DESC;
多个分组列
- 在书写包含嵌套分组的查询语句时,只需要在GROUP BY子句中把各个分组列依次写上,然后用逗号分隔开就好。
-- 示例
SELECT department,major,COUNT(*) FROM student_info GROUP BY department,major;
注意事项
- 如果分组列中有NULL,那么NULL会作为一个独立的分组存在
- GROUP BY子句后可以跟随表达式(但不能是汇总函数)
DCL:控制数据的权限
DCL介绍
DCL英文全称是Data Control Language(数据控制语言),用来管理数据库用户、控制数据库的访问权限。
用户管理
语法
1、查询用户
USER sql;
SELECT * FROM user;
或者
SELECT * FROM sql.user;
2、创建用户
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
3、修改用户密码
ALTER USER '用户名'@'主机名' IDENTIFIED WITH sql_native_password BY '新密码';
或者
ALTER USER '用户名'@'主机名' IDENTIFIED BY '新密码';
4、删除用户
DROP USER '用户名'@'主机名';
创建用户
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
在创建用户时,要指定下面三项内容
- 用户名
- 主机名——指明客户端可以在那些机器上启动(也可以填入IP地址),若省略则默认为'%',表示该用户可以在任意主机上启动客户端。
- 密码——若省略则表示此用户不需要密码。
注意:
刚创建的用户权限很小。
权限管理
授予权限
格式
GRANT 权限名称
ON 应用级别
TO '用户名'@'主机名'
[WITH GRANT OPTION];
权限名称
具体可参考sql :: sql 8.0 参考手册 :: 6.2.2 sql 提供的权限
以下为sql中常用的几种权限
权限名称 | 描述 |
---|---|
ALL [PRIVILEGES] | 代表了除GRANT OPTION、PROXY以外的其他所有权限 |
SELECT | 查询数据 |
INSERT | 插入数据 |
UPDATE | 修改数据 |
DELETE | 删除数据 |
ALTER | 修改表 |
DROP | 删除数据库/表/视图 |
CREATE | 创建数据库/表 |
应用级别
常用级别有以下方式
- *.* :代表全局级别。全局级别的权限作用于任何数据库下的任何对象
- 数据库名.* :代表数据库级别。数据库级别的权限作用于指定数据库下的任意对象
- 数据库名.表名 :代表表级别。表级别的权限作用于表中的任何列
WITH GRANT OPTION
若在使用GREANT语句为某个用户授予权限时添加了WITH GRANT OPTION子句,则表示该用户可以将自己拥有的权限赋予其他人。
查看权限
SHOW GRANTS FOR '用户名'@'主机名';
移除权限
REVOKE 权限名称
ON 应用级别
FROM '用户名'@'主机名';
函数
函数 是指一段可以直接被另一端程序调用的程序或代码。
汇总函数
MAX(表达式)
- 从匹配的结果中返回表达式对应列的最大值。
-- 从student_score表中找出科目为“JAVA语言”的最高成绩
SELECT MAX(score) FROM student_score WHERE subject = 'JAVA语言';
MIN(表达式)
- 从匹配的结果中返回表达式对应列的最小值。
-- 从student_score表中找到科目为“JAVA语言”的最低成绩
SELECT MIN(score) FROM student_score WHERE subject = 'JAVA语言';
SUM(表达式)
- 从匹配的结果中计算表达式对应列的总和。
-- 计算student_score表中科目为“JAVA语言”的成绩的总和
SELECT SUM(score) FROM student_score WHERE subject = 'JAVA语言';
AVG函数
- 从匹配的结果中计算表达式对应列的平均数。
-- 计算student_score表中科目为“JAVA语言”的成绩的平均分
SELECT AVG(score) FROM student_score WHERE subject = 'JAVA语言';
COUNT函数
- 从匹配的结果中统计表达式对应列中非NULL值的数量。
-- 使用COUNT函数统计student表列id中非NULL值的数量
SELECT COUNT(id) FROM student;
-- 查询匹配的结果中总共有多少条记录
SELECT COUNT(*) FROM student;
-- 当然,除了 * ,也可以使用任何值不为NULL的表达式
汇总函数中的DISTINCT
- 可使用DISTINCT函数来过滤重复数据
-- 查看student_info表中存储了多少个专业的学生信息
SELECT COUNT(DISTINCT major) FROM student_info;
使用多个汇总函数
- 多个汇总函数可放在同一个查询列表中。
SELECT COUNT(*) AS 成绩记录总数, MAX(score) AS 最高成绩, MIN(score) AS 最低成绩, AVG(score) AS 平均成绩 FROM student_score;
字符串函数
- 常用函数
名称 | 示例 | 示例结果 | 描述 |
---|---|---|---|
CONCAT | CONCAT('abc','123','xyz') | abc123xyz | 拼接字符串 |
LOWER | LOWER('ABC') | abc | 转小写 |
UPPER | UPPER('abc') | ABC | 转大写 |
LEFT | LEFT('abc123',3) | abc | 从左取指定长度 |
RIGHT | RIGHT('abc123',3) | 123 | 从右取指定长度 |
TRIM | TRIM(' abc ') | abc | 去除两边空格 |
SUBSTRING | SUBSTRING('abc123',2,3) | bc1 | 指定位置截取指定长度 |
LPAD | LPAD(str,n,pad) | 左填充,用pad对str填充至n个长度 |
- 使用方法
SELECT 函数(参数);
数值函数
- 常用函数
名称 | 示例 | 示例结果 | 描述 |
---|---|---|---|
ABS | ABS(-1) | 1 | 取绝对值 |
MOD | MOD(5,2) | 1 | 返回除法的余数 |
RAND | RAND() | 返回一个随机数 | |
CEIL | CEIL(2.3) | 3 | 返回不小于给定值的最小整数 |
FLOOR | FLOOR(2.3) | 2 | 返回不大于给定值的最大整数 |
SQRT | SQRT(9) | 3 | 返回平方根 |
POW | POW(2,2) | 4 | 返回定次幂 |
Pi | Pi() | 返回圆周率 | |
ROUND(x,y) | ROUND(2.344,2) | 2.23 | 求参数四舍五入后的值,保留y位小数 |
日期函数
- 常用函数
名称 | 描述 |
---|---|
NOW() | 返回当前时间和日期 |
CURDATE() | 返回当前日期 |
CURTIME() | 返回当前时间 |
DATE(date) | 提取date的日期 |
DATE_ADD(date,INTERVAL expr type) | 返回date加上expr type后的时间值 |
DATE_SUB(date,INTERVAL expr type) | 返回date减去expr type后的时间值 |
DATEDIFF(date1,date2) | 返回date1减去date2后的天数 |
DATE_FORMAT(date,'格式') | 用给定格式显示日期和时间 |
YEAR(date) | 提取年份 |
MONTH(date) | 提取月份 |
DAY(date) | 提取日 |
HOUR(date) | 提取小时 |
MINUTE(date) | 提取分钟 |
SECOND(date) | 提取秒 |
- 其中DATE_ADD和DATE_SUB所用的type为时间单位
- DATE_FORMAT(NOW(),'%m-%d-%Y');
流程函数
CASE 一
- 语法
CASE WHEN 表达式1 THEN 结果1 [WHEN 表达式2 THEN 结果2 ...] [ELSE 默认结果] END
- 示例
SELECT number,subject,score CASE WHEN score<60 THEN '不及格'
WHEN score<90 THEN '及格'
ELSE '优秀' END AS level
FORM student_score;
- 含义
- 当表达式1为true,返回结果1
- 当表达式2为true,返回结果2
- ...
- 若都不为true,返回ELSE的默认结果
CASE 二
- 语法
CASE 待比较表达式 WHEN 表达式1 THEN 结果1 [WHEN 表达式2 THEN 结果2 ...] [ELSE 默认结果] END
- 示例
- 含义
- 当待比较表达式的值和表达式1的值相同,返回结果1
- 当待比较表达式的值和表达式2的值相同,返回结果2
- ...
- 若都不为true,返回ELSE的默认结果
IF
- 语法
IF(表达式1,表达式2,表达式3)
- 示例
IF(1>2,3,4)
-- 结果为4
- 含义
- 当表达式1为TRUE时,返回值为表达式2,否则为表达式3
IFNULL
- 语法
IFNULL(表达式1,表达式2)
- 示例
SELECT IFNULL(NULL,5);
-- 结果为5
SELECT IFNULL(3,5);
-- 结果为3
- 含义
- 当表达式1为NULL,返回值为表达式2,否则为表达式1
NULLIF
- 语法
NULLIF(表达式1,表达式2)
- 示例
SELECT NULLIF(2,3);
-- 结果为2
SELECT NULLIF(2,2);
-- 结果为NULL
- 含义
- 当表达式1和表达式2的值相同时,返回值为NULL,否则返回表达式1的值
约束
概述
概念
约束是作用于表中字段上的规则,用于限制存储在表中的数据。
目的
保证数据库中数据的正确、有效性和完整性。
分类
约束 | 描述 | 关键字 |
---|---|---|
非空约束 | 限制该字段的数据不能为null | NOT NULL |
唯一约束 | 保证该字段的所有数据都是唯一、不重复的 | UNIQUE |
主键约束 | 主键是一行数据的唯一标识,要求非空且唯一 | PRIMARY KEY |
默认约束 | 保存数据时,如果未指定该字段的值,则采用默认值 | DEFAULT |
检查约束 | 保证字段值满足某个条件 | CHECK |
外键约束 | 用来让两张表的数据之间建立连接,保证数据的一致性和完整性 | FOREIGN KEY |
注意:约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束。
约束的使用
案例:根据需求完成表结构的创建
字段名 | 字段含义 | 字段类型 | 约束条件 | 关键字 |
---|---|---|---|---|
id | ID唯一标识 | int | 主键,自动增长 | PRIMARY KEY,AUTO_INCREMENT |
name | 姓名 | varchar(10) | 不为空,且唯一 | NOT NTLL,UNIQUE |
age | 年龄 | int | 大于0,且小于等于120 | CHECK |
status | 状态 | char(1) | 默认为1 | DEFAULT |
gender | 性别 | char(1) | 无 |
create table user(
id int primary key auto_increment comment '主键',
name varchar(10) not null unique comment '姓名',
age int check (age>0 && age<=120) comment '年龄',
status char(1) default '1' comment '状态',
gender char(1) comment '性别'
) comment '用户表';
外键约束
语法
- 添加外键
一、创建表时,添加外键约束
CREATE TABLE 表名(
字段名 数据类型,
...
[CONSTRAINT] [外键名称] FOREIGN KEY (外键字段名) REFERENCES 主表(主表列名)
);
二、表已创建,更新表时添加外键约束
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名) REFERENCES 主表(主表列名);
- 删除外键
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
删除和更新行为
行为
行为 | 说明 |
---|---|
NO ACTION | 当在父表中删除/更新对应记录时,首先检查记录是否有对应外键,若有则不允许删除/更新。(与RESTRICT一致) |
RESTRICT | 当在父表中删除/更新对应记录时,首先检查记录是否有对应外键,若有则不允许删除/更新。(与NO ACTION一致) |
CASCADE | 当在父表中删除/更新对应记录时,首先检查记录是否有对应外键,若有,则也删除/更新外键在子表中的记录。 |
SET NULL | 当在父表中删除/更新对应记录时,首先检查记录是否有对应外键,若有则设置子表中该外键为null(要求该外键允许null) |
SET DEFAULT | 父表有变更时,子表将外键设置成一个默认的值(lnnodb不支持) |
语法
例如(CASCADE操作):
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段) REFERENCES 主表名(主表字段名) ON UPDATE CASCADE ON DELETE CASCADE;
多表查询
概述
- 多表查询指从多张表中查询数据
- 笛卡尔积:指在数学中,两个集合 集合A和集合B的所有组合情况。(在多表查询时,需要显出无效的笛卡尔积)
如:
select * from emp,dept;
上为多表查询
将所有结果都展现,结果不符合预期
可写成:
select * from emp,dept where emp.dept_id = dept.id;
- 多表查询分类
- 连接查询
- 内连接:相当于查询集合A、集合B交集部分数据
- 外连接:
- 左外连接:查询左表所有数据,以及两张表交集部分数据
- 右外连接:查询右表所有数据,以及两张表交集部分数据
- 自连接:当前表与自身的连接查询,自连接必须使用表别名
- 子查询
- 连接查询
内、外、自连接
概念
- 对于内连接的两个表,若驱动表中的记录在被驱动表中找不到匹配的记录,则该记录不会加入到最后的结果集中。
- 对于外连接的两个表,即使驱动表中的记录在被驱动表中没有被匹配的记录,也仍然需要加入到结果集中。
- 对于自连接的两个表,由于驱动表和被驱动表是一个表,故称为自连接。
ON子句
在WHERE子句之外,又引入了ON子句
WHERE子句中的过滤条件
不论是内连接还是外连接,凡是不符合WHERE子句中过滤条件的记录都不会被加入最后的结果集。
ON子句中的过滤条件
对于外连接的驱动表的记录来说,若无法在被驱动表中找到匹配ON子句中过滤条件的记录,那么该驱动表记录仍然会被加入到结果集中,对应的被驱动表记录的各个字段使用NULL值填充。
**注意:**ON子句的特殊性只有在外连接查询中才会体现。
内连接
内连接查询的就是两张表交集的部分
语法:
- 隐式内连接
SELECT 字段列表 FROM 表1,表2 [WHERE 条件...];
-- 查询每一个员工的姓名,及关联的部门的名称
select emp.name,dept.name from emp,dept where emp.dept_id = dept.id;
|| 下为起别名后的用法
select e.name,d.name from emp e,dept d where e.dept_id = d.id;
- 显示内连接
SELECT 字段列表 FROM 表1 [INNER|CROSS] JOIN 表2 [ON 条件...] [WHERE 条件...];
-- 推荐使用INNER
-- 查询每一个员工的姓名,及关联的部门的名称
select emp.name,dept.name from emp inner join dept on emp.dept_id = dept.in;
select e.name,d.name from emp e inner join dept d on e.dept_id = d.id;
外连接
语法:
- 左(外)连接
SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 ON 过滤条件 [WHERE 过滤条件];
-- 其中表1为外表或驱动表,表2为内表或被驱动表
其中LEFT [OUTER] JOIN左侧的表称为外表或驱动表,右侧的表称为内表或被驱动表
相当于查询表1(左表)的所有数据,包含表1和表2交集部分的数据
示例:
-- 查询emp表的所有数据,和对应的部门信息(左外连接)
select e.*,d.name from emp e left outer join dept d on e.dept_id = d.id;
- 右(外)连接
SELECT 字段列表 FROM 表1 RIGHT [OUTER] JOIN 表2 ON 过滤条件 [WHERE 过滤条件];
-- 其中表2为外表或驱动表,表1为内表或被驱动表
其中LEFT [OUTER] JOIN右侧的表称为外表或驱动表,左侧的表称为内表或被驱动表
相当于查询表2(右表)的所有数据,包含表1和表2交集部分的数据
示例:
-- 查询dept表的所有数据,和对应的部门信息(右外连接)
select d.*,e.* from emp e right outer join dept d on e.dept_id = d.id;
自连接
语法:
SELECT 字段列表 FROM 表A 别名A [INNER] JOIN 表A 别名B ON 条件...;
-- 因为FROM子句中不能出现相同的表名,故需要对表定义别名
-- 例如
SELECT * FROM t1 AS table1 ,t1 AS table2;
自连接查询,可以是内连接查询,也可以是外连接查询。
联合查询
- 对于联合查询,就是把多次查询的结果合并起来,形成一个新的查询结果集。
UNION
- UNION可以将两个查询结果连在一起
SELECT 字段列表 FROM 表A ... UNION SELECT 字段列表 FROM 表B ...;
例如:
-- 将下两个查询语句联合起来
SELECT m1 FROM t1 WHERE m1<2;
SELECT m1 FROM t1 WHERE m1>2;
SELECT m1 FROM t1 WHERE m1<2 UNION SELECT m1 FROM t1 WHERE m1<2;
UNION ALL
- UNION会默认过滤结果集中重复的记录
- UNION ALL 会在连接多个查询的同时保留重复记录
SELECT 字段列表 FROM 表A ... UNION ALL SELECT 字段列表 FROM 表B ...;
子查询
- 概念
子查询:在SQL语句中嵌套SELECT语句,称为嵌套查询,又称为内层查询。
外层查询:使用子查询的结果作为搜索条件的查询称为外层查询。
根据子查询结果不同,分为:
- 标量子查询(子查询结果为单个值)
- 列子查询(子查询结果为一列)
- 列子查询(子查询结果为一行)
- 表子查询(子查询结果为多行多列)
根据子查询位置不同,分为:WHERE之后、FROM之后、SELECT之后。
在执行查询语句时,将按照从内到外的顺序依次执行。
标量子查询
- 概念
子查询返回的结果只有单个值(数字、字符串、日期等),这种子查询称为标量子查询。
例如:
-- 查询“销售部”的所有员工信息
方法一:
a、先查询“销售部”部门ID
select id from dept where name='销售部';
b、根据销售部部门ID,查询员工信息
select * from emp where dept_id=4;
方法二:
select * from emp where dept_id=(select id from dept where name='销售部');
注:因为标量子查询单纯的代表一个值,故可作为表达式的操作数来进行运算。
列子查询
- 概念
子查询返回是一列(可能是多行),这种子查询称为列子查询。
常用的操作符:IN、NOT IN、ANY、SOME、ALL
操作符 | 描述 |
---|---|
IN | 在指定的集合范围之内,多选一 |
NOT IN | 不在指定的集合范围内 |
ANY | 子查询返回列表中,有任意一个满足即可 |
SOME | 与ANY等同,使用SOME的地方都可以使用ANY |
ALL | 子查询返回列表的所有制都必须满足 |
案例:
-- 查询“销售部”和“市场部”的所有员工信息
方法一:
a、先查询“销售部”和“市场部”的部门ID
select id from dept where name = '销售部' or name = '市场部';
b、再根据部门ID,查询员工信息
select * from emp where dept_id in (2,4);
方法二:
select * from emp where dept_id in (select id from dept where name = '销售部' or name = '市场部');
行子查询
- 概念
子查询返回的结果是一行(可以是多列),这种子查询称为行子查询。
常用的操作符:=、<>、IN、NOT IN
案例:
-- 查询与“张无忌”的薪资及直属领导相同的员工信息
方法一:
a、先查询“张无忌”的薪资和直属领导
select salary,managerid from emp where name = '张无忌';
b、再查询与“张无忌”的薪资及直属领导相同的员工信息
select * from emp where salary = 12500 and managerid = 1;
select * from emp where (salary,managerid) = (12500,1);
方法二:
select * from emp where (salary,managerid) = (select salary,managerid from emp where name = '张无忌');
表子查询
- 概念
子查询返回的结果是多行多列,这种子查询称为表子查询。
常用的操作符:IN
案例:
-- 查询与“鹿仗客”,“宋远桥”的职位和薪资相同的员工信息
a、查询“鹿仗客”,“宋远桥”的职位和薪资
select jod,salary from emp where name = '鹿仗客' or name = '宋远桥';
b、查询与“鹿仗客”,“宋远桥”的职位和薪资相同的员工信息
select * from emp where (job,salary) in (select jod,salary from emp where name = '鹿仗客' or name = '宋远桥');
EXISTS子查询
- 判断子查询的结果集是不是为空集
运算符 | 示例 | 描述 |
---|---|---|
EXISTS | EXISTS (SELECT ...) | 当子查询结果集不是空集时表达式为真 |
NOT EXISTS | NOT EXISTS (SELECT ...) | 当子查询结果集是空集时表达式为真 |
相关子查询
不相关子查询:
子查询可以独立运行并产生结果,之后再拿结果作为外层查询的条件去执行外层查询,这种子查询称为不相关子查询。
select * from student_score where number = (select number from student_info where name = '狗哥');
相关子查询:
需要在子查询的语句中引入外层查询的列,此时子查询就不能当作一个独立的语句去执行,这种子查询称为相关子查询。
select number,name,id_number,major from student_info where exists (select * from student_score where student_score.number = student_info.number);
视图
视图(View)是一种虚拟存在的表,同真实表一样,视图也由列和行构成,但视图并不实际存在于数据库中。
可以把视图看作是一个查询语句的别名,即将一个查询语句用一个名字代替。
创建视图
CREATE VIEW 视图名 AS 查询语句
案例:
create view male_student_view as select s1.number,s1.name,s1.major,s2.subject,s2.score from student_info as s1 inner join student_score as s2 where s1.number = s2.number and s1.sex = '男';
number | name | major | subject | score |
---|---|---|---|---|
20210101 | 狗哥 | 计算机科学与工程 | sql是怎样运行的 | 88 |
20210101 | 狗哥 | 计算机科学与工程 | 计算机是怎样运行的 | 78 |
20210102 | 猫爷 | 计算机科学与工程 | sql是怎样运行的 | 98 |
20210102 | 猫爷 | 计算机科学与工程 | 计算机是怎样运行的 | 100 |
20210104 | 亚索 | 软件工程 | sql是怎样运行的 | 46 |
20210104 | 亚索 | 软件工程 | 计算机是怎样运行的 | 55 |
使用视图
视图也可以称为虚拟表,原因是我们可以像表那样对视图进行一些增删改查操作。
- 查询视图
- 平时怎样从表中查询信息,就可以怎么从视图中查询信息
- 对视图进行查询时,sql服务器会把对视图的查询语句转换为底层表的查询语句,再执行。
select * from male_student_view;
再次强调,视图相当于某个查询语句的别名。
利用视图来创建新视图
create view male_student_view2 as select number,name,score from male_student_view;
number | name | score |
---|---|---|
... | ... | ... |
创建视图时自定义列名
在创建视图的时候为其虚拟列自定义列名,这些自定义列名需要用小括号括起来,写在视图名后面,并使用逗号将各个虚拟列的自定义列名分开。
-- 创建一个自定义列名的视图
create view student_info_view(no,n,m) as select number,name,major from student_info;
有了自定义列名后,之后对视图的查询都要基于自定义的列名
select no,n,m from student_info_view;
操作视图
查看视图
- 查看现有视图
视图会在默认数据库下
-- 名字不能冲突
SHOW TABLES;
- 查看视图的定义
SHOW CREATE VIEW 视图名\G
更新视图
对视图进行增删改操作,其实就是对该视图对应的底层表中的数据进行增、删、改操作。
删除视图
DROP VIEW 视图名;
存储程序
- 存储程序可以封装一些语句,然后用户可以用简单的语句来调用这个存储函数。
- 根据调用方式的不同,可以把存储程序分为:
- 存储例程
- 存储函数
- 存储过程
- 触发器
- 事件
- 存储例程
用户自定义变量
- 通过SET语句来自定义变量
SET @a = 1;
注意:必须在自定义变量前添加 @ 符号
- 查看变量的值
SELECT @a;
- 同一个变量可以存储不同类型的值
- 可以将某个查询的结果赋值给一个变量
SET @a = (SELECT m1 FROM t1 LIMIT 1);
前提是查询结果集最多包含一行一列(若为空集,则变量值为null)
- 可以用INTO子句代替SET语句来为变量赋值
SELECT n1 FROM t1 LIMIT 1 INTO @b;
此语句与下效果相同
SET @a = (SELECT m1 FROM t1 LIMIT 1);
- 当结果集的记录中包含多个列时,只能用INTO
SELECT m1,m2 FROM t1 LIMIT 1 INTO @a,@b;
存储函数
- 存储程序类似于方法
- 存储函数有返回值
创建存储函数
- 语法:
CREATE FUNCTION 存储函数名称([参数列表])
RETURN 返回值类型
BEGIN
函数体内容
END
若不需要参数,参数列表可省略
函数体内容中的每条语句都要用分号(;)结尾
- 示例:
DELIMITER $ # 将sql客户端语句分割符替换为$
CREATE FUNCTION avg_score (s VARCHAR(100))
RETURN DOUBLE
BEGIN
RETURN (SELECT AVG(score) FROM student_score WHERE subject = s);
END $
DELIMITER ; # 将sql客户端语句分割符替换为;
其中DELIMITER $ 意味着将sql客户端的语句的分隔符从 ; 替换为 $
存储函数的调用
自定义函数与系统内置函数的使用方法相同
函数名后加小括号()来调用
-- 调用上定义的avg_score函数
SELECT avg_score('sql是怎样运行的');
查看和删除存储函数
- 查看现有存储函数以及各个存储函数的属性
SHOW FUNCTION STATUS [LIKE 需要匹配的函数名]
- 查看某个函数是怎样定义的
SHOW CREATE FUNCTION 函数名
-- 如:
SHOW CREATE FUNCTION avg_score\G
- 删除存储函数
DROP FUNCTION 函数名
函数体的定义
在函数体中定义局部变量
若想在存储函数的函数体中使用变量,必须提前使用DECLARE语句声明该变量
在函数体内声明的变量值在该函数体内有效
声明语法
DECLARE 变量1,变量2,... 数据类型 [DEFAULT 默认值];
函数体中的局部变量名不允许加@前缀(除非使用反引号将变量名引起来)
示例:
DELIMITER $
CREATE FUNCTION var_demo()
RETURN INT
BEGIN
DECLARE c INT;
SET c = 5;
RETURN c;
END $
DELIMITER ;
-- 也可以直接通过DEFAULT子句来显示的指定局部变量的默认值
DECLARE c INT DEFAULT 5;
在函数体中使用用户自定义变量
除了局部变量外,也可以直接在函数体中使用用户自定义变量
示例:
DELIMITER $
CREATE FUNCTION user_defined_var_demo()
RETURN INT
BEGIN
SET @abc = 10;
RETURN @abc;
END $
DELIMITER ;
-- 调用此函数
SELECT @abc;----NULL
=> 此时用户自定义变量abc的值为NULL
SELECT user_defined_var_demo();
SELECT @abc;----10
=> 在调用了user_defined_var_demo()存储函数之后,abc的值就变为了10
=> 即使存储函数执行完毕,该存储函数修改过的用户自定义变量的值依然生效
注意:此处与在函数体中使用DECLARE声明的局部变量有明显区别。
存储函数的参数
在定义存储函数时,可以指定多个参数,且每个参数都要制定对应的数据类型
就像这样:
参数名 数据类型
示例:
CREATE FUNCTION avg_score (s VARCHAR(100))
RETURN DOUBLE
BEGIN
RETURN (SELECT AVG(score) FROM student_score WHERE subject = s);
END
-- 此处为数据类型为VARCHAR(100)的参数s
注意:函数参数不能制定默认值。
判断语句的编写
语法:
IF 表达式 THEN
语句列表
[ELSEIF 表达式 THEN
语句列表]
... # 此处可有多个ELSEIF语句
[ELSE
语句列表]
END IF;
其中,语句列表中可以包含多条语句。
示例:
DELIMITER $
CREATE FUNCTION condition_demo(i INT) # 此函数接受一个INT类型的参数
BEGIN
DECLARE result VARCHAR(10);
IF i = 1 THEN
SET result = '结果是1'; # 当参数为1,result就被赋值为“结果是1”
ELSEIF i = 2 THEN
SET result = '结果是2'; # 当参数为2,result就被赋值为“结果是2”
ELSEIF i = 3 THEN
SET result = '结果是3'; # 当参数为3,result就被赋值为“结果是3”
ELSE
SET result = '非法参数'; # 否则result就被赋值为“非法参数”
END IF;
REturn result;
END $
DELIMITER ;
循环语句的编写
sql支持三种循环语句的编写,分别为WHILE、REPEAT、LOOP。、
- WHILE循环语句
WHILE 表达式 DO
语句列表
END WHILE;
-- 含义
如果表达式为真,则执行语句列表中的语句,否则退出循环
- REPEAT循环语句
REPEAT
语句列表
UNTIL 表达式 END REPEAT;
-- 含义
先执行语句列表的语句,再判断表达式是否为真,为真则退出循环,否则继续执行
- LOOP循环语句
LOOP
语句列表
END LOOP;
-- 含义
一直循环
-- 注意
此循环没有循环终止的条件!
需要把循环终止的条件写在语句列表中,然后使用RETURN语句结束此函数
若只是结束循环,可用LEAVE语句在LOOP语句前放置标记,来进行结束
-- 示例
flag:LOOP
IF i>n THEN
LEAVE flag;
END IF;
...
END LOOP flag;
存储过程
- 存储过程没有返回值
创建存储过程
语法:
CREATE PROCEDURE 存储过程名称([参数列表])
BEGIN
需要执行的语句
END
示例:
DELIMITER $
CREATE PROCEDURE t1_operation(m1_value INT,n1_value CHAR(1))
BEGIN
SELECT * FROM t1;
INSERT INTO t1(m1,n1) VALUES(m1_value,n1_value);
SELECT * FROM t1;
END $
DELIMITER ;
存储过程的调用
- 存储过程没有返回值,需要显示的使用CALL语句来调用存储过程
语法:
CALL 存储过程([参数列表]);
-- 调用t1_operation存储过程
CALL t1_operation(4,'d');
查看和删除存储过程
- 查看目前服务器已经创建了那些存储过程
SHOW PROCEDURE STATUS [LIKE 需要匹配的存储过程名称]
- 查看某存储过程的定义语句
SHOW CREATE PROCEDURE 存储过程名称
- 删除存储过程
DROP PROCEDURE 存储过程名称
存储过程的参数前缀
存储过程在定义参数的时候可以选择添加一些前缀
语法:
[IN | OUT | INOUT] 参数名 数据类型
前缀 | 实际参数是否必须有变量 | 描述 |
---|---|---|
IN | 否 | 用于调用者向存储过程传递参数,若IN参数在存储过程中被修改,则调用者不可见 |
OUT | 是 | 用于把存储过程运行过程中产生的数据赋值给OUT参数,存储过程执行结束后,调用者可以访问OUT参数 |
INOUT | 是 | 综合IN和OUT的特点,既可以用于调用者向存储过程传递参数,也可以用于存放存储过程中产生的数据以供调用者使用 |
游标简介
游标是一个存储在sql服务器上的数据库查询,它不是一条select语句,而是被该语句所检索出来的结果集。
创建游标
- 在创建游标的时候,需要指定与游标关联的查询语句
DECLARE 游标名称 CURSOR FOR 查询语句;
示例:
-- 定义一个存储过程
CREATE PROCEDURE cursor_demo()
BEGIN
DECLARE t1_record_cursor CURSOR FOR SELECT m1,n1 FROM t1;
END
-- 这样名为t1_record_cursor的游标就创建完成了
注意:
若在存储过程中也有声明局部变量的语句,则创建游标的语句一定要放在局部变量声明的后面。
打开和关闭游标
- 需要手动打开和关闭游标
OPEN 游标名称;
CLOSE 游标名称;
打开游标
- 意味着执行查询语句,使之前声明的游标与查询语句的结果集关联起来。
关闭游标
- 意味着释放与该游标相关的资源,所以一旦使用完了游标,就要将其关闭。
- 若不用CLOSE,则在存储过程的END语句执行完之后会自动关闭游标。
通过游标获取记录
获取记录的语法:
FETCH 游标名 INTO 变量1,变量2,...,变量n;
此句的意思是
把当前游标对应记录的各列的值依次赋值给INTO后的各个变量
注意: 此语句每次只获取一条记录,要获取多条记录需要加循环
案例:
CREATE PROCEDURE cursor_demo()
BEGIN
DECLARE m_value INT;
DECLARE n_value CHAR(1);
DECLARE t1_record_cursor CURSOR FOR SELECT m1,n1 FROM t1;
OPEN t1_record_cursor;
FETCH t1_record_cursor INTO m_value,n_value;
SELECT m_value,n_value;
CLOSE t1_record_cursor;
END $
错误时的执行策略
在FETCH语句获取不到记录的时候默认会停止存储函数或存储过程的执行,并报错
但有时候我们不希望程序停止运行
则可以在存储函数或存储过程中事先声明一种针对某种错误的处理方式,这样在服务器执行期间,若遇到了错误,不会停止并报错,而是采用事先声明的错误处理方式取处理。
在遇到FETCH语句获取不到记录的情况时,可使用:
DECLARE CONTINUE HANDLER FOR NOT FOUND 处理语句;
触发器
sql触发器是与表关联的数据库存储程序,用于响应关联表中发生的事件(例如插入,更新或删除)而自动调用。
创建触发器
语法:
CREATE TRIGGER 触发器名
{BEFORE|AFTER}
{INSERT|DELETE|UPDATE}
ON 表名
FOR EACH ROW
BEGIN
触发器内容
END
名称 | 描述 |
---|---|
BEFORE | 表示在具体的语句执行之前就开始执行触发器的内容 |
AFTER | 表示在具体的语句执行之后才开始执行触发器的内容 |
因为sql服务器会对某条语句影响的所有记录依次调用用户自定义的触发器内容,所以针对每一条受影响的记录,我们需要一种方式来访问该纪录中的内容。
sql提供了NEW和OLD这两词来分别代表新纪录和旧记录。
NEW和OLD在各语句中的含义:
- 对于INSERT语句设置的触发器,NEW代表准备插入的记录,OLD无效。
- 对于DELETE语句...,OLD代表删除前的记录,NEW无效。
- 对于UPDATE语句...,NEW代表修改后的记录,OLD代表修改前的记录。
案例:
DELIMITER $
CREATE TRIGGER bi_t1
BEFORE INSERT ON t1
BEGIN
IF NEW.m1 < 1 THEN
SET NEW.m1 = 1;
ELSEIF NEW.m1 > 10 THEN
SET NEW.m1 = 10;
END IF;
END $
DELIMITER ;
-- 上方代码的解释
对t1表定义了一个名为bi_t1的触发器,意思时在对t1表插入新纪录之前,对准备插入的每一条记录都会执行BEGIN...END之间的语句,“NEW.列名”表示当前待插入记录指定列的值。
查看和删除触发器
- 查看当前数据库中定义的所有触发器
SHOW TRIGGERS;
- 查看某个触发器的定义语句
SHOW CREATE TRIGGER 触发器名
- 删除触发器
DROP TRIGGER 触发器名
注意事项
- 触发器内容中不能有输出结果集的语句。
- 触发器内容中NEW代表记录的列的值可以被更改,OLD代表记录的列的值无法更改。
- 在BEFORE触发器中,使用“SET NEW.列名 = 某个值”的形式来更改待插入记录或者待更新记录的某个值的列,但是这种操作不能再AFTER触发器中使用,因为再执行AFTER触发器的内容时记录已经被插入完成或者更新完成了。
事件
sql中的事件 (event)是用于执行定时或周期性的任务,事件由一个特定的线程来管理的,也就是所谓的事件调度器,但是事件不能直接调用。
创建事件
语法:
CREATE EVENT 事件名
ON SCHEDULE
{
AT 某个确定的时间点|
EVERY 期望的时间间隔 [STARTS 开始日期和时间][END 结束日期和时间]
}
DO
BEGIN
具体的语句
END
事件支持两种类型的自动执行方式:
①在某个确定的时间点执行
②每隔一段时间执行一次
===>>>在某个确定的时间执行
案例:
CREATE EVENT insert_t1_event
ON SCHEDULE
AT '2022-2-2 12:12:12'
DO
BEGIN
INSERT INTO t1(m1,n1) VALUES(6,'f');
END
-- 表示在2022-2-2 12:12:12执行
CREATE EVENT insert_t1_event
ON SCHEDULE
AT DATE_ADD(NOW(),INTERVAL 2 DAY)
DO
BEGIN
INSERT INTO t1(m1,n1) VALUES(6,'f');
END
-- 表示在当前时间的两天后执行
===>>>每隔一段时间执行一次
案例:
CREATE EVENT insert_t1_event
ON SCHEDULE
EVERY 1 HOUR
DO
BEGIN
INSERT INTO t1(m1,n1) VALUES(6,'f');
END
-- 表示每隔一个小时执行一次
CREATE EVENT insert_t1_event
ON SCHEDULE
EVERY 1 HOUR STARTS '2022-2-2 12:12:12' ENDS '2023-2-2 12:12:12'
DO
BEGIN
INSERT INTO t1(m1,n1) VALUES(6,'f');
END
-- 表示自2022-2-2 12:12:12开始到2023-2-2 12:12:12为止的时间段,每隔一个小时执行一次
注意:
定时执行事件的功能需要开启后才能正常使用,如
SET GLOBAL event_scheduler = ON;
查看和删除事件
- 查看当前数据库中定义的所有事件
SHOW EVENTS;
- 查看某事件的定义语句
SHOW CREATE EVENT 事件名;
- 删除事件
DROP EVENT 事件名;
备份与恢复
sqldump
备份数据
在bin目录下,有一个名为sqldump的可执行文件是用来备份数据的。
⚪备份指定数据库的指定表
命令如下:
sqldump [其他选项] 数据库名 [表1名,表2名,表3名,...]
案例:
sqldump -uroot -hlocalhost -p xiaohaizi student_score > student_score.sql
Enter password:******
解释:
sqldump本身时一个客户端程序,在进行备份时需要与服务器进行通信,故在此执行-u(用户名)、-h(主机)和-p(密码)参数
由于sqldump的输出内容较多,建议把输出内容重定向到某个文件中,而> student_score.sql表示把命令的执行结果重定向到一个名为student_score.sql的文件中(此处为相对路径)
此后若student_score表被误删,或想建一个相同的表,可以执行这个student_score.sql文件中的语句。
⚪备份指定数据库中的所有表
命令如下:
sqldump [其他选项] --databases 数据库1名,数据库2名,数据库3名,...
案例:
-- 备份xiaohaizi、dahaizi这两个数据库下的所有表
sqldump -uroot -hlocalhost -p --databases xiaohaizi dahaizi
⚪备份所有数据库下的所有表
命令如下:
sqldump [其他选项] --all-databases
案例:
sqldump -uroot -hlocalhost -p --all-databases
恢复数据
可以通过SOURCE语句来执行备份文件中的语句
方法:只需要将备份文件的路径放在SOURCE单词后,即可执行
案例:
-- 先删除
DROP TABLE student_score;
-- 检查是否被删除
SELECT * FROM student_score;
-- 恢复
SOURCE C:\Users\xiaohaizi\student_score.sql;
以文本形式导出或导入
导出数据
语法:
SELECT ... INTO OUTFILE '文件路径' [导出选项]
常用的导出选项如下
FILEDS TERMINATED BY
- 表示列分隔符,也就是各列的值之间使用什么符号进行分隔,默认以'\t'分隔。
- 如:FILEDS TREMINATED BY ',' 表示以逗号分隔。
FILEDS [OPTIONALLY] ENCLOSED BY
- 表示列引用符,也就是每个列的值被什么符号包裹起来,默认是空字符串''。 若加上OPTIONALLY则只会作用于字符串类型的列。
- 如:FILEDS ENCLOSED BY ' " ' 表示每个列的值都将被双引号引起来。
LINES STARTING BY
- 表示行开始符,也就是每一行以什么符号开始,默认是空字符串''。
- 如:LINES STARTING BY '%%' 表示每行都以两个百分号开头。
LINES TERMINATED BY
- 表示行结束符,也就是每一行以什么符号结尾,默认是换行符'\n'。
- 如:LINES TERMINATED BY '$$' 表示每行都以两个美元符号结尾。
案例:
SELECT * FROM student_score INTO OUTFILE 'C/ProgramData/sql/sql Server 8.0/Uploads/student_score1.txt' FIELDS OPTIONALLY ENCLOSED BY '"' LINES STARTING BY '>_>';
解释:
将student_score表导出目录为‘...’的文件名为‘student_score1.txt’
且导出文件的每行以‘>_>’开头
且subject列的值被双引号引起来(因为subject列时字符串类型)
注意:使用SELECT ... INTO OUTFILE语句导出的数据会被存储到运行服务器程序的主机上。
导入数据
语法:
LOAD DATA [LOCAL] INFILE '文件路径' INTO TABLE 表名 [导入选项]
- 若填入LOCAL,则表名要导入的数据文件在运行客户端的主机中,否则就在运行服务器的主机中。
- 常用的导入选项和SELECT ... INTO OUTFILE语句中的导出选项类似。
案例:
-- 先把student_score表中的记录删除
DELETE FROM student_score;
-- 再导入数据
LOAD DATA INFILE 'C/ProgramData/sql/sql Server 8.0/Uploads/student_score1.txt' INTO TABLE student_score;
事务
简介
事务:是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
事务主要用于处理操作量大,复杂度高的数据。
事务的操作
- 查看/设置事务的提交方式
-- 查看事务的提交方式,1为自动提交,0为手动提交,默认为1
SELECT @@autocommit;
-- 设置事务的提交方式
SET @@autocommit = 0;
除上一种方法控制事务,也可用下方法显式开启事务
- 开启事务
START TRANSACTION 或 BEGIN;
- 提交事务
COMMIT;
若事务的提交方式为手动提交,则语句执行完毕后需要执行COMMIT语句提交事务。
- 回滚事务
ROLLBACK;
若语句出错或有不满意的结果,可执行回滚事务撤回本次操作。
事务的四大特性
- 原子性(Atomicity)
- 事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
- 一致性(Consistency)
- 事务完成时,必须使所有的数据都保持一致状态。
- 隔离性(Isolation)
- 数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
- 持久性(Durability)
- 事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
并发事务问题
问题 | 描述 |
---|---|
脏读 | 一个事务读到另一个事务还没有提交的数据 |
不可重复读 | 一个事务先后读取同一条记录,但两次读取的数据不同 |
幻读 | 一个事务按照条件查询数据时,没有对应的数据行,但在插入数据时,又发现这行数据已经存在 |
事务隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable Read(默认) | × | × | √ |
Serializable | × | × | × |
注:越往下级别越高,但性能越差。
默认仅代表sql
相关语法:
-- 查看事务隔离级别
SELECT @@TRANSACTION_ISOLATION;
-- 设置事务隔离级别
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE}
注:SESSION对当前窗口有效,GLOBAL对全局窗口有效