笛卡尔乘积
笛卡尔乘积 :
当一个连接条件无效或被遗漏时,其结果是一个笛卡尔乘积 (Cartesian product),其中所有行的组合都被显示。第一个表中的所 有行连接到第二个表中的所有行。一个笛卡尔乘积会产生大量的 行,其结果没有什么用。你应该在 WHERE 子句中始终包含一个有 效的连接条件,除非你有特殊的需求,需要从所有表中组合所有的 行。
多表查询分类
等值连接
为了确定一个雇员的部门名,需要比较 EMPLOYEES 表中的 DEPARTMENT_ID 列与DEPARTMENTS 表中的 DEPARTMENT_ID 列的值。在 EMPLOYEES 和DEPARTMENTS 表之间的关系是一个相 等 (equijoin) 关系,即,两个表 中DEPARTMENT_ID列的值必须相等。
等值连接特点:
注意: 等值连接也被称为简单连接 (simple joins) 或内连接 (inner joins)。
等值连接的使用
SELECT 子句指定要返回的列名:
FROM 子句指定数据库必须访问的两个表:
WHERE 子句指定表怎样被连接:
EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID,因为 DEPARTMENT_ID 列 是两个表的同名列,它必须用表名做前缀以避免混淆。
增加搜索条件
添加查询条件
除连接之外,可能还要求用 WHERE 子句在连接中限制一个或多个表中的行。
限制不明确的列名
使用表别名
表别名定义原则
多表连接
示例一: 查询雇员 King 所在的部门名称。
select d.department_name
from employees e,departments d
where e.dept_id = d.department_id and e.last_name = 'King';
示例二: 显示每个雇员的 last name、departmentname 和 city。
SELECT e.last_name, d.department_name, l.city
FROM employees e, departments d, locations l
WHERE e.department_id = d.department_id AND d.location_id = l.location_id;
非等值连接
一个非等值连接是一种不同于等值操作的连接条件。 EMPLOYEES 表 和JOB_GRADES A 表之间的关系有一个非等值连接例子。在两个 表之间的关系是EMPLOYEES 表中的 SALARY 列必须是 JOB_GRADES 表的 LOWEST_SALARY 和HIGHEST_SALARY 列之间 的值。使用不同于等于 (=) 的操作符获得关系。
示例一: 创建 job_grades 表,包含 lowest_sal ,highest_sal , grade_level。
create table job_grades(
lowest_sal int,
highest_sal int ,
grade_level varchar(30)
);
示例二: 插入数据
1000 2999 A
2000 4999 B
5000 7999 C
8000 12000 D
insert into job_grades values(1000,2999,'A');
insert into job_grades values(2000,4999,'B');
insert into job_grades values(5000,7999,'C');
insert into job_grades values(8000,12000,'D');
示例三: 查询所有雇员的薪水级别。
select e.last_name,j.grade_level
from employees e ,job_grades j
where e.salary between j.lowest_sal and j.highest_sal;
自连接
连接一个表到它自己。有时需要连接一个表到它自己。为了找到每 个雇员的经理的名字,则需要连接EMPLOYEES 表到它自己,或执 行一个自连接。
图片中的例子连接 EMPLOYEES 表到它自己。为了在 FROM 子句中模拟两个表,对于相同的表 EMPLOYEES,用两个别名,分别为 worker 和 manager。在该例中,WHERE 子句包含的连接意味着 “一个工人的经理号匹配该经理的雇员号”。
示例一:
查询每个雇员的经理的名字以及雇员的名字,雇员名字列别名为 W,经理列别名为M。
SELECT
worker.LAST_NAME W,manager.LAST_NAME M
from employees worker,employees manager
where worker.MANAGER_ID = manager.EMPLOYEE_ID;
示例二:
查询Fox的经理是谁?显示他的名字。
SELECT
worker.LAST_NAME,manager.LAST_NAME
from employees worker,employees manager
where worker.MANAGER_ID = manager.EMPLOYEE_ID
AND
worker.LAST_NAME = 'Fox';
MySQL5.7 支持部分的SQL99 标准。
示例: 使用交叉连接查询 employees 表与 departments 表。
select * from employees cross join departments;
自然连接
连接只能发生在两个表中有相同名字和数据类型的列上。如果列有 相同的名字,但数据类型不同,NATURAL JOIN 语法会引起错误。
自然连接查询
在图片例子中,LOCATIONS 表被用 LOCATION_ID 列连接到 DEPARTMENT表,这是在两个表中唯一名字相同的列。如果存在其它的同名同类型的列,自然连接会使用等值连接的方式连接他们, 连接条件的关系为and。 自然连接也可以被写为等值连接:
SELECT d.department_id, d.department_name, d.location_id , l.city
FROM departments d , locations l
WHERE d.location_id = l.location_id;
示例: 使用自然连接查询所有有部门的雇员的名字以及部门名称。
select e.last_name,d.department_name
from employees e
natural join departments d;
语法:
用ON子句指定连接条件
用ON子句指定更多的连接条件
示例: 查询雇员名字为 Fox 的雇员 ID ,薪水与部门名称。
select
e.employee_id,e.salary,d.department_name
from employees e
inner JOIN departments d
on e.department_id = d.department_id
where e.last_name = 'Fox';
孤儿数据(Orphan Data)
孤儿数据是指被连接的列的值为空的数据。
左外连接
左边的表 (EMPLOYEES) 中即使没有与 DEPARTMENTS 表中匹配的 行,该查询也会取回 EMPLOYEES 表中所有的行。
示例: 查询所有雇员的名字以及他们的部门名称,包含那些没有部门的雇员。
select e.last_name,d.department_name
from employees e
LEFT OUTER JOIN departments d
on e.dept_id = d.department_id;
右外连接
右边的表 (DEPARTMENTS ) 中即使没有与 EMPLOYEES 表中匹配的 行,该查询也会取回 DEPARTMENTS 表中所有的行。
示例: 查询所有雇员的名字以及他们的部门名称,包含那些没有雇员的部门。
select e.last_name,d.department_name
from employees e RIGHT OUTER JOIN departments d
on e.DEPARTMENT_ID = d.department_id;
注意: MySQL 中不支持 FULL OUTER JOIN 连接
可以使用 union 实现全完连接。
语法结构
(SELECT 投影列 FROM 表名 LEFT OUTER JOIN 表名 ON 连接条件)
UNION
(SELECT 投影列 FROM 表名 RIGHT OUTER JOIN 表 名 ON 连接条件)
示例: 查询所有雇员的名字以及他们的部门名称,包含那些没有雇员的部 门以及没有部门的雇员。
(select e.last_name,d.department_name
from employees e LEFT OUTER JOIN
departments d on e.department_id = d.department_id)
UNION
(select e1.last_name,d1.department_name
from employees e1 RIGHT OUTER JOIN
departments d1 on d1.department_id = e1.department_id)
自然连接 natural join
select <选择列>
from 表A natural join 表B
将表A和表B进行自然连接:在A和B所有共同属性上做等值连接,然后再投影去掉重复属性。
例如:
select *
from book natural join reader
内连接 inner join
select <选择列>
frome 表A inner join 表B on <连接条件>
<连接条件> A.s θ B.k(s为表A的属性,k为表B的属性)
θ为等号=时,是等值连接;θ不为等号=时,是不等值连接;
将表A和表B进行内连接:当至少有一个满足连接条件时,返回满足条件的行。
例如:
select book_name
from book inner join reader on book.borrower_id=reader.id
外连接 outer join
左外连接 left join
select <选择列>
from 表A left join 表B on <连接条件>
<连接条件>参考上文
将表A和表B进行左外连接:在自然连接的结果上,如果t是A中不满足连接条件的元组,则将t添加到结果中,并且t本身不存在的属性取NULL
右外连接 right join
select <选择列>
from 表A right join 表B on <连接条件>
<连接条件>参考上文
将表A和表B进行右外连接:在自然连接的结果上,如果t是B中不满足连接条件的元组,则将t添加到结果中,并且t本身不存在的属性取NULL
全外连接 full join
select <选择列>
from 表A full join 表B on <连接条件>
<连接条件>参考上文
将表A和表B进行全外连接:在自然连接的结果上,
1)如果t是A中不满足连接条件的元组,则将t添加到结果中,并且t本身不存在的属性取NULL
2)如果s是B中不满足连接条件的元组,则将s添加到结果中,并且s本身不存在的属性取NULL
聚合函数
聚合函数也称之为多行函数,组函数或分组函数。聚合函数不象单行函数,聚合函数对行的分组进行操作,对每组给出一个结果。如果在查询中没有指定分组,那么聚合函数则将查询到的结果集视为一组。
聚合函数类型
聚合函数说明:
函数名 | 描述 | 实例 |
---|---|---|
AVG(expression) | 返回一个表达式的平均 值,expression 是一个 字段 | 返回 Products 表中Price 字段的平均值: SELECT AVG(Price) AS AveragePrice FROM Products; |
COUNT(expression) | 返回查询的记录总数, expression 参数是一个 字段或者 * 号 | 返回 Products 表中 products 字段总共有多少条记 录: SELECT COUNT(ProductID) AS NumberOfProducts FROM Products; |
MAX(expression) | 返回字段 expression 中 的最大值 | 返回数据表 Products 中字段 Price 的最大值: SELECT MAX(Price) AS LargestPrice FROM Products; |
MIN(expression) | 返回字段 expression 中 的最小值 | 返回数据表 Products 中字段 Price 的最小值: SELECT MIN(Price) AS MinPrice FROM Products; |
SUM(expression) | 返回指定字段的总和 | 计算 OrderDetails 表中字段 Quantity 的总和: SELECT SUM(Quantity) AS TotalItemsOrdered FROM OrderDetails; |
聚合函数使用方式
使用聚合函数的原则
AVG(arg)函数
对分组数据做平均值运算。 arg:参数类型只能是数字类型。
SUM(arg)函数
对分组数据求和。 arg:参数类型只能是数字类型。
示例: 计算员工表中工作编号含有REP的工作岗位的平均薪水与薪水总 和。
SELECT AVG(salary),SUM(salary)
FROM employees
WHERE job_id LIKE '%REP%';
MIN(arg)函数
求分组中最小数据。 arg:参数类型可以是字符、数字、 日期。
MAX(arg)函数
求分组中最大数据。 arg:参数类型可以是字符、数字、 日期。
示例: 查询员工表中入职时间最短与最长的员工,并显示他们的入职时 间。
SELECT MIN(hire_date), MAX(hire_date) FROM employees;
返回分组中的总行数。
COUNT 函数有三种格式:
使用 DISTINCT 关键字
示例一: 显示员工表中部门编号是80中有佣金的雇员人数。
SELECT COUNT(commission_pct) FROM employees WHERE department_id = 80;
示例二: 显示员工表中的部门数。
SELECT COUNT(DISTINCT department_id) FROM employees;
组函数和 Null 值
在组函数中使用 IFNULL 函数
SELECT AVG(IFNULL(commission_pct, 0)) FROM employees;
创建数据组
在没有进行数据分组之前,所有聚合函数是将结果集作为一个大的 信息组进行处理。但是,有时,则需要将表的信息划分为较小的 组,可以用 GROUP BY 子句实现。
GROUP BY 子句语法
原则
使用 GROUP BY 子句
GROUP BY 子句
select
聚合函数,
列(要求出现在group by的后面)
from
表
where
筛选条件
group by
分组的列表
order by
子句
注意:除了出现在group by后面的字段,如果要在select后查询其他字段,必须用聚合函数进行聚合
特点:分组查询中的筛选条件分为两类:
分组前筛选: 数据源是原始表,用where,放在group by前面,因为在分组前筛选
分组后筛选:数据源是分组后的结果集 ,用having,放在group by后面,因为在分组后进行筛选。
示例: 计算每个部门的员工总数。
SELECT DEPARTMENT_ID, COUNT(*) FROM employees GROUP BY DEPARTMENT_ID;
在组中分组
可以列出多个 GROUP BY 列返回组和子组的摘要结果。可以用 GROUP BY子句中的列的顺序确定结果的默认排序顺序。下面是图 片中的 SELECT 语句中包含一个 GROUP BY 子句时的求值过程:
SELECT 子句指定被返回的列:
− 部门号在 EMPLOYEES 表中
− Job ID 在 EMPLOYEES 表中
− 在 GROUP BY 子句中指定的组中所有薪水的合计
FROM 子句指定数据库必须访问的表:EMPLOYEES 表。
GROUP BY 子句指定你怎样分组行:
− 首先,用部门号分组行。
− 第二,在部门号的分组中再用 job ID 分组行。
如此 SUM 函数被用于每个部门号分组中的所有 job ID 的 salary 列。
示例: 计算每个部门的不同工作岗位的员工总数。
SELECT e.DEPARTMENT_ID, e.JOB_ID,COUNT(*)
FROM employees e
GROUP BY e.DEPARTMENT_ID,e.JOB_ID;
HAVING 子句
HAVING 子句是对查询出结果集分组后的结果进行过滤。
约束分组结果
用 WHERE 子句约束选择的行,用 HAVING 子句约束组。
为了找到每个部门中的最高薪水,而且只显示最高薪水大于 $10,000 的那些部门,可以象下面这样做:
SELECT department_id, MAX(salary)
FROM employees
GROUP BY department_id
HAVING MAX(salary)>10000 ;
HAVING子句语法
示例:
显示那些合计薪水超过 13,000 的每个工作岗位的合计薪水。排除那 些JOB_ID中含有REP的工作岗位,并且用合计月薪排序列表。
SELECT job_id, SUM(salary) PAYROLL
FROM employees
WHERE job_id NOT LIKE '%REP%'
GROUP BY job_id
HAVING SUM(salary) > 13000
ORDER BY SUM(salary);
用子查询解决问题
假如要写一个查询来找出挣钱比 Abel 的薪水还多的人。为了解决这 个问题,需要两个查询:一个找出 Abel 的收入,第二个查询找出收入高于 Abel 的人。可以用组合两个查询的方法解决这个问题。内查询或子查询返回一个值给外查询或主查询。使用一个子查询相当于执行两个连续查询并且用第一个查询的结果作为第二个查询的搜索 值。
子查询语法
子查询
子查询是一个 SELECT 语句,它是嵌在另一个 SELECT 语句中的子 句。使用子查询可以用简单的语句构建功能强大的语句。
可以将子查询放在许多的 SQL 子句中,包括:
使用子查询
使用子查询的原则
子查询类型
示例: 查询与Fox同一部门的同事,并显示他们的名字与部门ID。
select e.LAST_NAME,e.DEPARTMENT_ID FROM
employees e
where e.DEPARTMENT_ID =
(select e1.DEPARTMENT_ID from employees e1 where e1.last_name = 'Fox');
单行子查询
单行子查询是从内查询返回一行的查询。在该子查询类型中用一个单行操作符。
示例: 查询 Fox的同事,但是不包含他自己。
select empl.last_name
from employees empl
where empl.department_id =
(select e.department_id from employees e where e.last_name = 'Fox')
and empl.last_name <> 'Fox';
多行子查询
子查询返回多行被称为多行子查询。对多行子查询要使用多行运算符而不是单行运算符。
使用ANY运算符
ANY 运算符
ANY 运算符比较一个值与一个子查询返回的每一个值。
使用ALL运算符
ALL 运算符比较一个值与子查询返回的每个值。
NOT 运算符可以与 IN运算符一起使用。
子查询中的空值
内查询返回的值含有空值,并因此整个查询无返回行,原因是用大 于、小于或不等于比较Null值,都返回null。所以,只要空值可能是子查询结果集的一部分,就不能用 NOT IN 运算符。NOT IN 运算符 相当于 <> ALL。
注意,空值作为一个子查询结果集的一部分,如果使用 IN 操作符的话,不是一个问题。IN 操作符相当于 =ANY。
SELECT emp.last_name
FROM employees emp
WHERE emp.employee_id IN (SELECT mgr.manager_id FROM employees mgr);
示例: 查找各部门收入为部门最低的那些雇员。显示他们的名字,薪水以及部门 ID。
select
em.last_name,em.salary,em.department_id
from employees em
where em.salary in
(select min(e.salary) from employees e group by e.department_id);
索引是对数据库表中的一列或多列值进行排序的一种结构,使用索引可以快速访问数据库表中的特定信息。索引是一种特殊的文件, 它们包含着对数据表里所有记录的位置信息。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。MySQL索引的建立对于MySQL 的高效运行是很重要的,索引可以大大提高 MySQL 的检索速度。
索引的作用
索引相当于图书上的目录,可以根索引缺点据目录上的页码快速找到所需的 内容,提高性能(查询速度)。
索引优点:
索引缺点
什么时候需要创建索引
什么时候不需要创建索引
MySQL中的索引类型
是最基本的索引,它没有任何限制。在创建索引时,可以指定索引 长度。length 为可选参数,表示索引的长度,只有字符串类型的字 段才能指定索引长度,如果是 BLOB 和 TEXT 类型,必须指定 length。
创建索引时需要注意: 如果指定单列索引长度,length 必须小于这个字段所允许的最大字符个数。
查询索引
SHOW INDEX FROM table_name;
直接创建索引
CREATE INDEX index_name ON table(column(length));
示例:
为 emp3 表中的 name 创建一个索引,索引名为 emp3_name_index;
create index emp3_name_index ON emp3(name);
修改表添加索引
ALTER TABLE table_name ADD INDEX index_name (column(length));
示例:
修改 emp3 表,为 addrees 列添加索引,索引名为 emp3_address_index;
alter table emp3 add index emp3_address_index(address);
创建表时指定索引列
CREATE TABLE `table` (
COLUMN TYPE ,
PRIMARY KEY (`id`),
INDEX index_name (column(length))
);
示例:
创建 emp4 表,包含 emp_id,name,address 列, 同时为 name 列 创建索引 ,索引名为 emp4_name_index。
create table emp4(
emp_id int primary key auto_increment,
name varchar(30),
address varchar(50),
index emp4_name_index(name)
);
删除索引
DROP INDEX indexname ON tablename;
示例:
删除 mep3 表中索引名为 emp3_address_index 的索引。
drop index emp3_address_index on emp3;
唯一索引与普通索引类似,不同的就是: 索引列的值必须唯一,但允许有空值。
创建唯一索引
CREATE UNIQUE INDEX indexName ON table(column(length));
示例:
为 emp 表中的 name 创建一个唯一索引,索引名为 emp_name_index。
create unique index emp_name_index on emp(name);
修改表添加唯一索引
ALTER TABLE table_name ADD UNIQUE indexName (column(length));
示例:
修改 emp 表,为 salary 列添加唯一索引,索引名为 emp_salary_index。
alter table emp add unique emp_salary_index(salary);
创建表时指定唯一索引
CREATE TABLE `table` (
COLUMN TYPE ,
PRIMARY KEY (`id`),
UNIQUE index_name (column(length))
);
示例:
创建 emp5 表,包含 emp_id,name,address 列,同时为 name 列 创建唯一索引。索引名为 emp5_name_index。
create table emp5(
emp_id int primary key,
name varchar(30),
address varchar(30),
unique emp5_name_index(name)
);
主键索引是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建表的时候同时创建主键索引。
修改表添加主键索引
ALTER TABLE 表名 ADD PRIMARY KEY(列名);
示例:
修改 emp 表为 employee_id 添加主键索引。
1 alter table emp add primary key(employee_id);
创建表时指定主键索引
CREATE TABLE `table` (
COLUMN TYPE ,
PRIMARY KEY(column)
);
示例:
创建 emp6 表,包含 emp_id,name,address 列,同时为 emp_id 列创建主键索引。
create table emp6(
employee_id int primary key auto_increment,
name varchar(20),
address varchar(50)
);
组合索引是指使用多个字段创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用(最左前缀原则)。
最左前缀原则
就是最左优先。
如: 我们使用表中的 name ,address ,salary 创建组合索引,那么想要组合索引生效, 我们只能使用如下组合:
name/address/salary
name/address
name/
如果使用 addrees/salary 或者是 salary 则索引不会生效
添加组合索引
ALTER TABLE table_name ADD INDEX index_name (column(length),column(length));
示例:
修改 emp6 表,为 name ,address 列创建组合索引。
alter table emp6 add index emp6_index_n_a(name,address);
创建表时创建组合索引
CREATE TABLE `table` (
COLUMN TYPE ,
INDEX index_name (column(length),column(length))
);
示例:
创建 emp7 表,包含 emp_id,name,address 列,同时为 name,address 列创建组合索引。
create table emp7(
emp_id int primary key auto_increment ,
name varchar(20),
address varchar(30),
index emp7_index_n_a(name,address)
);
事务是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
事务定义(Transaction)
事务四大特征(ACID)
事务类型
显式事务
需要我们手动的提交或回滚。
DML 语言中的所有操作都是显示事务操作。
隐式事务
数据库自动提交不需要我们做任何处理,同时也不具备回滚性。
DDL、DCL 语言都是隐式事务操作
TCL语句 | 描述 |
---|---|
start transaction | 事务开启 |
commit | 事物提交 |
rollback | 事物回滚 |
示例一:
创建account账户表,包含id、卡号、用户名、余额。
create table account(
id int primary key auto_increment,
cardnum varchar(20) not null,
username varchar(30) not null,
balance double(10,2)
);
示例二:
向account表中插入两条数据。
insert into account(cardnum,username,balance) VALUES('123456789','张三',2000);
insert into account(cardnum,username,balance) VALUES('987654321','李四',2000);
示例三:
在一个事务中完成转账业务。
START TRANSACTION
update account set balance = balance-200 where cardnum = '123456789';
update account set balance = balance+200 where cardnum = '987654321';
select * from account;
-- 当我们关闭数据库重新打开后,张三和李四的账户余额并没发生任何变化。
-- 这是因为当我们使用“START TRANSACTION”开启一个事务后,该事务的提交方式不再是自动的,
-- 而是需要手动提交,而在这里,我们并没有使用事务提交语句COMMIT,
-- 所以对account表中数据的修改并没有永久的保存到数据库中,也就是说我们的转账事务并没有执行成功
-- 提交转账事务
commit;
-- 事务的回滚让数据库恢复到了执行事务操作前的状态。
-- 需要注意的是事务的回滚必须在事务提交之前,因为事务一旦提交就不能再进行回滚操作。
rollback;
脏读(读取未提交数据)
指一个事务读取了另外一个事务未提交的数据。
A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行 回滚操作,那么A事务读取到的数据就是脏数据。
不可重复读(前后多次读取,数据内容不一致)
在一个事务内读取表中的某一行数据,多次读取结果不同。
事务A在执行读取操作,由整个事务A比较大,前后读取同一条数据 需要经历很长的时间 。而在事务A第一次读取数据,比如此时读取 了小明的年龄为20岁,事务B执行更改操作,将小明的年龄更改为 30岁,此时事务A第二次读取到小明的年龄时,发现其年龄是30 岁,和之前的数据不一样了,也就是数据不重复了,系统不可以读取到重复的数据,成为不可重复读。
幻读(前后多次读取,数据总量不一致)
是指在一个事务内读取到了别的事务插入的数据,导致前后读取数量总量不一致。
事务A在执行读取操作,需要两次统计数据的总量,前一次查询数据 总量后,此时事务B执行了新增数据的操作并提交后,这个时候事务 A读取的数据总量和之前统计的不一样,就像产生了幻觉一样,平白 无故的多了几条数据,成为幻读。
事务的隔离级别用于决定如何控制并发用户读写数据的操作。数据 库是允许多用户并发访问的,如果多个用户同时开启事务并对同一 数据进行读写操作的话,有可能会出现脏读、不可重复读和幻读问题,所以MySQL中提供了四种隔离级别来解决上述问题。
事务的隔离级别从低到高依次为:
隔离级别越低,越能支持高并发的数据库操作。
查看MySQL默认事务隔离级别
SELECT @@transaction_isolation;
设置事务隔离级别
对当前session有效。
set session transaction isolation level read uncommitted;
set session transaction isolation level read committed;
set session transaction isolation level repeatable read;
set session transaction isolation level serializable;
MySQL 是一个多用户的数据库系统,按权限,用户可以分为两种: root 用户,超级管理员,和由 root 用户创建的普通用户。
创建用户
CREATE USER username IDENTIFIED BY 'password';
查看用户
SELECT USER,HOST FROM mysql.user;
示例:
创建一个 u_sxt 的用户,并查看创建是否成功。
create user u_sxt IDENTIFIED by 'sxt';
select user,host from mysql.user;
新用户创建完后是无法登陆的,需要分配权限。
GRANT 权限 ON 数据库.表 TO 用户名@登录主机 IDENTIFIED BY “密码”
登陆主机:
字段 | 含义 |
---|---|
% | 匹配所有主机 |
localhost | localhost 不会被解析成 IP 地址,直接通过 UNIXsocket 连接 |
127.0.0.1 | 会通过 TCP/IP 协议连接,并且只能在本机访问 |
:: 1 | ::1 就是兼容支持 ipv6 的,表示同 ipv4 的 127.0.0. 1 |
权限列表
权 限 | 作用范围 | 作 用 |
---|---|---|
all [privileges] | 服务器 | 所有权限 |
select | 表、列 | 选择行 |
insert | 表、列 | 插入行 |
update | 表、列 | 更新行 |
delete | 表 | 删除行 |
create | 数据库、表、索引 | 创建 |
drop | 数据库、表、视图 | 删除 |
reload | 服务器 | 允许使用flush语句 |
shutdown | 服务器 | 关闭服务 |
process | 服务器 | 查看线程信息 |
file | 服务器 | 文件操作 |
grant option | 数据库、表、存储过程 | 授权 |
references | 数据库、表 | 外键约束的父表 |
index | 表 | 创建/删除索引 |
alter | 表 | 修改表结构 |
show databases | 服务器 | 查看数据库名称 |
super | 服务器 | 超级权限 |
create temporary tables | 表 | 创建临时表 |
lock tables | 数据库 | 锁表 |
execute | 存储过程 | 执行 |
replication client | 服务器 | 允许查看主/从/二进制日志状态 |
replication slave | 服务器 | 主从复制 |
create view | 视图 | 创建视图 |
show view | 视图 | 查看视图 |
create routine | 存储过程 | 创建存储过程 |
alter routine | 存储过程 | 修改/删除存储过程 |
create user | 服务器 | 创建用户 |
event | 数据库 | 创建/更改/删除/查看事件 |
trigger | 表 | 触发器 |
create tablespace | 服务器 | 创建/更改/删除表空间/日志文件 |
proxy | 服务器 | 代理成为其它用户 |
usage | 服务器 | 没有权限 |
GRANT ALL PRIVILEGES ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password'
示例:
为 u_sxt 用户分配只能查询 bjsxt 库中的 emp 表,并且只能在本机 登陆的权限。
grant select ON bjsxt.emp to 'u_sxt'@'localhost' IDENTIFIED by 'sxt';
刷新权限
每当调整权限后,通常需要执行以下语句刷新权限。
FLUSH PRIVILEGES;
删除用户
DROP USER username@localhost;
示例:
删除 u_sxt 用户。
drop user 'u_sxt'@'localhost';
创建用户
分配权限
删除用户
导出sql脚本文件
导入sql脚本文件
MySQL 分页查询原则:
LIMIT子句
SELECT 投影列 FROM 表名 WHERE 条件 ORDER BY LIMIT 开始位置,查询数量;
示例:
查询雇员表中所有数据按 id 排序,实现分页查询,每次返回两条结果。
select * from employees order by employees_id limit 0,2;
LIMIT OFFSET子句
SELECT 投影列 FROM 表名 WHERE 条件 ORDER BY LIMIT 查询数量 OFFSET 开始位置;
示例:
查询雇员表中所有数据按 id 排序,使用 LIMIT OFFSET 实现分页查询,每次返回两条结果。
select * from employees order by employees_id limit 2 offset 4;