/*
索引(包含约束,不写索引名,那么索引名就是对应字段名,主键不显示索引名)概念
我们可以通过对数据表中的字段创建索引 来提高查询速度
常见的索引的分类
主键索引 (primary key) 主键是一个唯一性的索引 每个表中只能有一个主键
唯一索引 (unique) 索引列的所有数据只能出现一次,必须是唯一
普通索引 (index) 最常见的索引 作用就是提高对数据的访问速度
表对应的索引被保存在一个索引文件中, 如果对数据进行增删改操作,那么mysql就需要对索引进行更新(这个时候需要考虑索引的性能了,索引多,那么增删改可能会久一点,所以索引的好处基本只是针对查询,而不是增删改(对他们是坏处))
//为什么会这样呢,这就不得不说明一下索引的原理了,通常索引的创建是指对该添加索引的字段进行一个优化,比如使用树(一般搜索的都是B+树),这种树,通常平衡,且是一定范围,在查询时,是可以根据这个树来查询的,他比全部扫描或者说类似的数组扫描是要快的,还有,该树最后会有一个链表连接的类似数组,其实就是链表(连接叶子节点),他的作用在于范围查询(虽然很多人认为他是索引的真正情况,这也并非没有道理,并且可能也会认为查询也是(因为他有顺序(前提如果也存在对应的数组的话),但是对比这样的树来说,通常还是类似的,所以说他是真正情况也不为过,所以大多数是使用树,可能有设置使用链表的(一般是有序链表,可能生成有序数组,具体看代码,那么在这种情况可以认为他是索引的真正情况),或者有其有序数组的))
*/
/*
主键索引的创建
1.创建表的时候 直接添加主键
2.创建表之后 添加索引 使用 DDL
*/
CREATE TABLE demo01(
did INT,
dname VARCHAR(20),
hobby VARCHAR(30)
);
-- 为demo01表添加 主键索引
ALTER TABLE demo01 ADD PRIMARY KEY (did);
/*
唯一索引的创建
create unique index 索引名 on 表名(列名(长度))
*/
-- 为demo01表的 hobby字段添加唯一索引
CREATE UNIQUE INDEX ind_hobby ON demo01(hobby);
-- 添加唯一索引的列,列的所有值都只能出现一次
INSERT INTO demo01 VALUES(1,'tom','篮球');
-- Duplicate entry '篮球' for key 'ind_hobby'
-- 唯一索引保证了数据的唯一性, 同时也提升了查询效率
INSERT INTO demo01 VALUES(2,'jack','篮球');
/*
普通索引的创建
1.create index 索引名 on 表名(列名[长度])
2.ALTER TABLE 表名 ADD INDEX 索引名 (列名)
*/
-- 为 demo01表中的 dname字段添加普通索引
ALTER TABLE demo01 ADD INDEX ind_dname(dname);
/*
删除索引
ALTER TABLE 表名 DROP INDEX 索引名;
*/
-- 删除dname字段上的索引
ALTER TABLE demo01 DROP INDEX ind_dname;
-- 导入测试索引.sql 文件
-- 地址:
/*
链接:https://pan.baidu.com/s/15wVEFP0Dkvft4oMwUgDGFg
提取码:alsk
*/
-- test_index 表中有 500万条数据
SELECT COUNT(*) FROM test_index;
-- 通过id查询一条数据
SELECT * FROM test_index WHERE id = 100001;
-- 通过 dname字段查询 耗时2秒左右
SELECT * FROM test_index WHERE dname = 'name5200';
-- 执行分组查询 dname没有添加索引 36秒
SELECT * FROM test_index GROUP BY dname;
-- dname字段添加索引
ALTER TABLE test_index ADD INDEX dname_indx(dname);
SELECT * FROM test_index GROUP BY dname;
/*
索引的总结
创建索引的原则
优先选择为 经常出现在 查询条件或者排序 分组后面的字段 创建索引.
索引的优点
1.可以大大的提高查询速度
2.减少查询中分组和排序的时间
3.通过创建唯一索引保证数据的唯一性
索引缺点
1.创建和维护索引需要时间,数据量越大 时间越长.
2.表中的数据进行增删改操作时,索引也需要进行维护,降低了维护的速度
3.索引文件需要占据磁盘空间
*/
-- 注意:对于之前所说的约束,其实是一种作用,我们在创建那些约束时,实际上是创建索引
-- 而这些索引帮我们实现了对数据的约束,从而我们也叫约束
-- 就如not null约束,这个不是索引,但他对数据进行了一种作用,让他不为空
-- 唯一索引
-- 对表字段添加unique约束的方式
-- 在创建表时,自占一行的写上 unique key 索引名 (字段名(长度)),key和索引名和长度可以省略
-- 若写上长度,该列必须为字符串的类型,否则报错
-- 也可在字段后面加上unique,后面可以加多个unique不影响,即不报错
-- 因为多次声明,最后的结果还是一个结果,那就是唯一,与主键不同,因为主键只能有一个,而unique可以有多个
-- create unique index 索引名字 on 表(列(长度)),这个长度,若要写上,该列必须为字符串的类型,否则报错
-- 可以理解为创建唯一索引在表的列上
-- alter table 表名 add unique(列名)
-- alter table 表名 add unique key (列名)
-- alter table 表名 add unique key 索引名 (列名)
-- 其中key和索引名,可以不写,若索引名不写的话,则索引名就是对应字段名,主键不显示索引名
-- 由于字段后面可以加unique,那么就可以用修改操作,来实现添加unique等
-- alter table 表名 modify id int unique
-- alter table 表名 change id cid int unique
-- 注意:必须要可以在字段后面加的修饰才可用修改操作来加,否则加不了
-- 因为修改操作,本就是对创建表的一种修补,创建表时,可以加,那么就可以加
-- 而且无论是什么索引,在修改字段名时,对应的索引括号里面的字段名都会变成修改后的字段名
-- 如原来表primary key(id),然后alter table 表名 change id cid int
-- 那么primary key(id),就会变成primary key(cid)
-- index 英文意思:索引
-- 普通索引
-- 在创建表时,自占一行的写上 index(key) 索引名 (字段名(长度)),索引名和长度可以省略
-- 若写上长度,该列必须为字符串的类型,否则报错
-- create index 索引名字 on 表(列(长度))
-- alter table 表名 add index (列名(长度)),或者alter table 表名 add index 索引名 (列名(长度))
-- alter table 表名 add key (列名(长度)),或者alter table 表名 add key 索引名 (列名(长度))
-- 索引名和长度可以省略,若写上长度,该列必须为字符串的类型,否则报错
-- 注意:在创建表时,添加主键的primary key可以直接写key,即省略primary来创建主键
-- key 英文意思:钥匙
-- 删除索引,只要有索引名的,都可以这样删除
-- alter table 表名 drop index(key) 索引名,这样删除有索引名的
-- 因为创建unique索引时,有索引名,那么就可以这样删除
-- 对于mysql的value和values
-- 插入单行的时候使用values,在插入多行的时候使用value
-- 因为在插入单行时values速度快一些,插入多行时value快一些
-- 单行(values快):
-- insert into 表名 (id) values(1);
-- insert into 表名 (id) values(2);
-- 多行(value快):
-- insert into 表名 (id) value(1),(2);
-- 插入几行数据看不出来,但可以插入大量数据看出来
-- 实验数据地址:https://blog.csdn.net/qq_44813090/article/details/105307720
-- 由于在一些很多数据时,相关操作尽可能的提高速度,于是索引出现了,当有大量数据时
-- 你要查询对应的字段值的那一条数据,他会根据你的表找过去,若你这个字段是有索引的
-- 那么查询的速度就会快很多(具体参考B+树,数据结构可以参考99章博客(可能还要后面几篇)),否则没有索引的话,就会慢很多,特别是分组,会消耗大量的使间,这就是索引的好处
-- 在限制你的其他操作的同时(约束),也加快了查询速度
-- 其实无论是修饰(包括索引)还是其他的,都是作用于所有数据
-- 所以当你要操作(如修改,增加,删除)这些修饰或者其他的东西时,会操作所有数据
-- 即最好是在创建完表后,将需要的东西给操作(如修改,增加,删除)完
-- 这样当数据够多时,就不用中途操作(如修改,增加,删除)了
-- 当然,在操作(如修改,增加,删除)单条数据时,会将那些修饰(包括索引)或者其他东西,都会作用到操作后的数据
/*
什么是视图
视图是由查询结果形成的一张虚拟的表.
视图的作用
如果某个查询的结果出现的十分频繁,并且查询语法比较复杂.
那么这个时候,就可以根据这条查询语句构建一张视图 方便查询
视图的语法
create view 视图名[字段列表] as select 查询语句;
view 表示视图
字段列表 一般跟后面的查询语句 相同
as select 查询语句 表示给视图提供数据的 查询语句
*/
-- 创建视图
-- 对应的表在上一章博客
-- 1.查询所有商品和商品对应分类的信息
SELECT * FROM products p LEFT JOIN category c ON p.`category_id` = c.`cid`;
-- 2.根据上面的查询语句 构建一张视图
CREATE VIEW products_category_view AS
SELECT * FROM products p LEFT JOIN category c ON p.`category_id` = c.`cid`;
-- 操作视图 就相当于操作一张 只读表
SELECT * FROM products_category_view;
-- 使用视图进行查询操作
-- 查询各个分类下的商品平均价格
/*
1.查询哪些表 分类表 商品表
2.查询条件是什么 分组操作
3.要查询的字段 平均价格,分类名
4.多表的连接条件 category_id = cid
*/
-- 使用多表方式查询
SELECT
c.`cname`,
AVG(p.`price`)
FROM products p LEFT JOIN category c ON p.`category_id` = c.`cid`
GROUP BY c.`cname`;
-- 通过视图查询
SELECT
pc.`cname`,
AVG(pc.`price`)
FROM products_category_view pc GROUP BY pc.`cname`;
-- 查询鞋服分类下最贵的商品的全部信息
-- 多表查询
-- 1.查询鞋服分类中 最高的商品价格
SELECT
MAX(p.`price`)
FROM products p LEFT JOIN category c ON p.`category_id` = c.`cid`
WHERE c.`cname` = '鞋服';
-- 2.进行子查询 将上面的查询结果作为条件
SELECT
*
FROM products p LEFT JOIN category c
ON p.`category_id` = c.`cid`
WHERE c.`cname` = '鞋服' AND p.`price` =
(
SELECT
MAX(p.`price`)
FROM products p LEFT JOIN category c ON p.`category_id` = c.`cid`
WHERE c.`cname` = '鞋服'
);
-- 通过视图查询
SELECT
*
FROM products_category_view pc
WHERE pc.`cname` = '鞋服' AND pc.`price` =
(
-- 子查询 求出鞋服分类下的最高价格
SELECT MAX(pc.`price`) FROM products_category_view pc
WHERE pc.`cname` = '鞋服' );
/*
视图与表的区别
1.视图是建立在表的基础之上
2.通过视图 不要进行增删改操作,视图主要就是用来简化查询
3.删除视图 表不受影响,删除表 视图就不在起作用了.
*/
-- 在有些数据库的名称中会出现下划线"_",可以看作是连接的意思,假设有两张表,如表1,表2
-- 那么创建的视图可以是"表1_表2_view",这样就可以知道该视图由什么组成,所以通常情况下,下划线"_"
-- 是算连接表的,但这只是一种规范而已,并没有对数据库进行一些操作,即没有实际作用
-- 视图就是将查询的表,进行存储起来
-- 如create view 视图名 as 查询语句,对于查询表字段名时,as是用来设置查询结果字段的
-- 而不是查询表字段名时,而对于表来说,as是设置别名的,操作时都要用这个别名,而创建视图时的as
-- 是将查询语句给该视图,使得查看视图时,是操作这个语句,可以看出,这三个as表示结果不同
-- 即不可完全参照英文意思,因为这是编程,不是英文,意思可能会改变的,即可能不会一模一样
-- 如char在java里表示字符,而英文意思表示烧焦
-- character在java里表示字符包装类,而英文意思表示字符
-- 但也有些相同的
-- 如private在java里表示私有的,在英文意思里也表示私有的
-- 那么以后操作这个视图时,虽然可以用视图名来表示一个表了,但是最终结果是该语句的结果
-- 若该语句所对应表有损坏,且影响了该语句的查询,则会出现不同结果或者报错,若没有影响,就不会
-- 且该视图只能查询,即只能读,因为是一个语句,那么就不可以进行其他操作(如增加,修改,删除)
/*
触发器
当我们执行一条sql语句的时候,这条sql语句的执行会自动去触发执行其他的sql语句。
触发器创建的四个要素
1. 监视地点(table)
2. 监视事件(insert/update/delete)
3. 触发时间(before/after)
4. 触发事件(insert/update/delete)
创建触发器
语法结构
delimiter $ -- 自定义结束符号
create trigger 触发器名
after/before(insert/update/delete) -- 触发的时机 和监视的事件
on tableName -- 触发器所在表
for each row -- 固定写法 表示行触发器
begin
-- 被触发的事件
end $
*/
-- 向商品表中插入数据
INSERT INTO goods VALUES(4,'book',40);
-- 需求: 在下订单的时候,对应的商品的库存量要相应的减少,卖出商品之后减少库存量
/*
监视的表 orders
监视的事件 insert
触发的时间 after
触发的事件 update
*/
-- 1.修改结束符号
DELIMITER $
-- 2.创建触发器
CREATE TRIGGER t1
-- 3.设置触发的时间 以及监视的事件 监视的表
AFTER INSERT ON orders
-- 4.行触发器
FOR EACH ROW
-- 5.触发后要执行的操作
BEGIN
-- 执行修改库存的操作 订单+1 库存-1
UPDATE goods SET num = num - 1 WHERE gid = 4;
END $
-- 向orders表插入一个订单
INSERT INTO orders VALUES(1,4,25);
-- 注意:对于一些可视化界面,是可以不用设置结束符号的
-- 他们规定在触发器和存储过程里面的或者其他代码不参与结束的操作
-- 即分号不参加了,但也可以设置,但有些必须设置结束符号
-- 除非本来就是分号结尾了,当然也可以设置分号为结束符号,只不过没必要,因为没有这样的规定
-- 最主要的是有些工具默认结束符号为分号,那么在没有设置结束符号时,有些代码会报错
-- 因为代码不完整了,如触发器中没设置结束符号时,begin结束的不是end了,被分号拦截了
-- 且设置结束符的话可以让代码更加的整洁
-- 也更加的可以确定在哪里结束
-- 触发器的创建方式
-- delimiter $ -- 自定义结束符号
-- create trigger 触发器名
-- after/before 触发的时机
-- 区别:before的insert和update可以在begin和end之间使用new,new就是你要操作的数据,如原来表的id为4
-- 你增加一个id为5的数据或者修改id为4的数据变为5时,那么new.id就是这个5
-- 即new就是用来存放你对当前表的操作变化的数据
-- 可以看成是你输入的数据,即你准备要改变表的那个数据,但是不可以用old,即不可以操作原来表的数据
-- 而delete则没有操作的数据,所以不可以用new,但需要获得原来表的内容,那么就用old.id
-- old存放着当前表的所有数据,这样就获得表的id数据
-- 即为4,其中update也可以用old
-- 即before的new使用者是insert,old的使用者是delete,而update可以都使用
-- 注意:若要修改new.对应字段,那么必须使用set new.对应字段,因为set代表着设置,否则识别不了你的操作
-- 这个与java不一样,因为不是同一种语言,且只有insert和update可以修改,delete修改不了
-- 因为delete不可以用new,且old是不可以修改的,因为触发器不可对当前表操作
-- 就如不可以对当前表进行增删改操作一样
-- 对于after的insert只可以使用new,但不可修改,update可以使用new和old,但都不能修改
-- delete只可以使用old,且也不能修改
-- 因为new是使用操作变化的数据,而after则是操作表数据之后的操作,所以没有new,因为你先对表操作完了
-- 而old是不可对当前表进行操作,所以也不可以用
-- 即after则new和old都不可修改
-- 总结:
-- before
-- insert可使用new,修改new,不可使用old,不可修改old
-- update可使用new,修改new,可使用old,不可修改old
-- delete不可使用new,不可修改new,可使用old,不可修改old
-- after
-- insert可使用new,不可修改new,不可使用old,不可修改old
-- update可使用new,不可修改new,可使用old,不可修改old
-- delete不可使用new,不可修改new,可使用old,不可修改old
-- 由于after是先完成数据的增删改,再触发,触发的语句晚于监视的增删改操作,且不可修改你输入的数据
-- 那么就无法影响前面的增删改动作
-- 也就是说先插入订单记录(我要20个),再更新商品的数量(只有10个),这时数量可能会出现错误结果,如负数(-10)
-- 而before是先完成触发,再增删改,触发的语句先于监视的增删改,我们就有机会判断(修改输入的数据)
-- 修改即将发生的操作,由于先后的顺序
-- 使得before和after对输入的数据是否有操作的时候,即在前的可以操作,在后的操作不到了
-- 即可以理解为before是对当前表的约束(可以修改),也可以对其他表进行操作
-- 而after只能对其他表进行操作(不可修改,但可以用new)
-- insert/update/delete 监视的事件
-- on tableName -- 触发器所在表
-- for each row -- 固定写法 表示行触发器
-- begin
-- 被触发的事件,sql语句,可以使用if和end if操作(只要是begin和end的都可以使用)
-- 使用方式 if 条件语句 then 中间的操作 end if;,这里也是分号结尾的,mysql规定if操作这样写
-- then 英文意思:然后,当if判断为真,就执行then后面的代码,否则不执行,且then后面的代码必须有操作
-- 即增加操作,修改操作,删除操作,或者变量之间的操作等等,查询操作不可以
-- 否则没有操作的话,创建触发器就会报错
-- 注意:虽然增加操作,修改操作,和删除操作不会有错误,但是运行的时候,不可操作本表,因为怕你有可能会嵌套
-- 所以规定,在表的触发器里,不可对本表进行增删改操作,防止嵌套产生
-- 之所以创建触发器不报错,是因为表名可以随便写
-- 因为sql不关键代码错误不会报错(不关键代码:不是关键字的代码,如表名)
-- 注意:当你设置一个变量,如set @a = 10;,那么再次使用@a时,不可直接@a = 11,否则报错
-- 必须重新set @a = 11,因为在数据库里,第一次的set是定义变量再设置值,之后的set就是单纯的设置值了
-- 若没有set的话,是识别不了你要干什么的,而有set,就知道你要设置值了,这是mysql的规定,对任意变量都是如此
-- 这里给出一个提示功能,如signal SQLSTATE 'HY000' SET mysql_errno = 22, message_text = 'aa';
-- aa表示提示的信息,当执行到这里时,无论是before还是after都会终止前面的操作,即类似于回滚,让表回到原样
-- 只所以是这样的,是因为before和after都不算完全执行完,虽然after是执行增删改操作后触发的,
-- 但是只有当你完全执行完后,当前表和其他表的操作才执行完毕
-- 理解:通常我们在进行增删改操作时,数据到表会经过一系列底层,然后在最后确定,然后表数据(文件)改变
-- 而before和after类似于,对数据的约束,每当一行(for each row,每一行)数据要到表去时
-- 先进行before,然后到一个中转站
-- 最后通过after,在最后确定,然后表数据改变
-- 就如你开门(before),进去(增删改),还要关门(after),才算完全进入,类似于事务一样的操作
-- end $
-- signal 英文意思:信号
-- sqlstale 没英文意思,但可以理解为"错误的sql",而后面的'HY000',是固定的
-- 可以写'HY000'-'HY009'之间,包括两边
-- mysql_errno 没英文意思,但可以理解为"错误的编号",即22错误号,基本可以写很大
-- 但太大了(或者没有找到对应错误号,如'a')的话则默认为1231
-- message_text 没英文意思,但可以理解为"错误的信息",即'aa'就是错误信息,给你看的错误信息
-- 如'学号过大',那么发生错误时(执行到这里就会提示),就显示学号过大
-- 在这里不难发现,整型可以转化为字符串类型,而数字字符串(只有数字,如'1')可以转化整型
-- 但字母字符串(有字母的都算,如'01a')不可以
-- 注意:字符串'1.1'变为整型为1,变为字符串不会,整型1.1变为整型也是1
-- trigger 英文意思:触发
-- after 英文意思:在...后
-- brfore 英文意思:在…以前
-- for each 英文意思:每个
-- row 英文意思:一行
-- 注意:设置结束符时如delimiter ##,那么就会作用于整个窗口,除非你选中执行(使用的是sqlyog工具)
-- 若用光标执行,则执行##之间的代码(delimiter ##不执行也可以,但必须有,会自动识别)
-- set 变量名 = concat(变量1,变量2);,用在begin和end里
-- 可以将变量1和变量2合并起来(形成字符串),并赋值给该变量名
-- 注意:mysql的变量的类型与他的值有关,即可以随便赋值
/*
DCL 创建用户
语法结构
create user '用户名'@'主机名' identified by '密码';
*/
-- 创建 admin1 用户,只能在 localhost 这个服务器登录 mysql 服务器,密码为 123456
CREATE USER 'admin1'@'localhost' IDENTIFIED BY '123456';
-- user 英文意思:用户
-- identified by 英文意思:密码
-- 创建 admin2 用户可以在任何电脑上登录 mysql 服务器,密码为 123456
CREATE USER 'admin2'@'%' IDENTIFIED BY '123456'; -- %表示在任意电脑都可以登录
/*
用户的授权
语法格式
grant 权限1,权限2 ... on 数据库名.表 to '用户名'@'主机名'
*/
-- 需要权限才会存在对应的数据库展示,自行测试就知道了
-- 给 admin1 用户分配对 db4 数据库中 products 表的 操作权限:查询
GRANT SELECT ON db4.`products` TO 'admin1'@'localhost';
-- 也可以修改用户密码
-- 比如GRANT SELECT ON db4.`products` TO 'admin1'@'localhost' IDENTIFIED BY '1234567';
-- 这样也就变成了1234567这个密码了,也就只能使用1234567登录了,而不是123456
-- 当然,他也可以理解为添加用户,即内涵了CREATE USER这个操作以及修改操作
-- 所以如果没有该admin1用户,他也会操作添加该用户
-- 除此之外,通常来说,可以理解为授予权限对哪个地方,并给哪个用户
-- grant 英文意思:授予
-- 给 admin2 用户分配所有权限,对所有数据库的所有表
GRANT ALL ON *.* TO 'admin2'@'%'
-- all:所有权限,*.*:任何数据库的任何表
-- 查询 商品表
SELECT * FROM products;
-- 插入商品数据
-- INSERT command denied to user 'admin1'@'localhost' for table 'products'
-- admin1用户只有查询权限
INSERT INTO products VALUES('p010','小鸟伏特加',3000,1,NULL);
/*
查看用户权限
语法格式
show grants for '用户名'@'主机名';
*/
-- 查看root用户的权限
SHOW GRANTS FOR 'root'@'localhost';
-- 查看 admin1 用户的权限
SHOW GRANTS FOR 'admin1'@'localhost';
-- 删除用户
DROP USER 'admin1'@'localhost';
-- 查询用户
SELECT * FROM USER;
-- 创建用户
-- CREATE USER 'admin1'@'localhost' IDENTIFIED BY '123456';
-- user 英文意思:用户
-- identified by 英文意思:密码
-- 在数据库名称为mysql的数据库里,有个user表,存放的就是你的用户,你创建用户后,这里就有你创建的用户数据了
-- 其中localhost代表着只能在localhost这个服务器登录mysql服务器
-- 可以改成%,则可以在任何电脑上登录mysql服务器
-- 授予权限方式,grant 权限1,权限2 ... on 数据库名.表 to '用户名'@'主机名'
-- grant 英文意思:授予
-- 权限可以为增删改查等等,如select,若为all,则代表所有权限
-- 而"数据库名.表"是对应位置,若为*.*则是所有数据库的所有表
-- 当你指定对应的数据库名.表时,那么新建连接使用这个用户时,就会有你指定的数据库和对应的表
-- 注意通常情况下,需要指定到表,否则报错,若权限为all,那么指定任何位置都不会报错,因为显示mysql数据库
-- 只要你指定到表,那么无论权限如何(无权限除外),新建该连接时
-- 就会有对应的数据库和表(除非你删了,那么下次进入该连接时,就没了)
-- 查看权限方式
-- show grants for '用户名'@'主机名';
-- 展示用户名创建时的sql语句
-- show 英文意思:展示
-- for 英文意思:对于
-- grants 英文意思:允许
-- 注意:所有数据库是由用户共享的,即其中一个用户删除数据库的数据时(如表),那么其他用户也就没有该数据了
-- 因为都指向文件,当没有权限时,如usage,当无权限时,无论你指定什么表,也不会在你连接后,有该表(而且没有也怎么指定呢)
-- 因为只有连接数据库和查询information_schema的权限了,这是底线,不可再低
-- 删除用户
-- deop user '用户名'@'主机名';
-- 查询用户
-- select * from user;
-- 注意:'用户名'@'主机名',之间的@的两边不可有空格,即他们是一体的