MYSQL学习笔记
自己记性实在太差,有些指令三天不用就忘了,于是做个记录免得老去百度
1连接数据库
一般情况本地连接数据库不会出现问题,大部分问题出现在远程连接上,尤其是权限问题很烦人,不过知道咋回事了也就那么回事
注意:用的时候不要把尖括号也带上了,这里只是提醒这是个字段,免得你真写成mysql -u<用户名>......了
1.1连接本地数据库
mysql -u<用户名> -p<密码>
例:mysql -uroot -proot
1.2连接其他地方的数据库
mysql -u<用户名> -p<密码> -h<远程数据库地址> -P<端口号>
测试了一下,远程数据库地址填域名也可以,只不过比较慢,毕竟需要域名解析
如果远程地址连不上,本地地址可以连上,先检查防火墙是不是拦住数据库的TCP端口了,MySQL默认3306,当然一般公司的数据库不会用默认的
然后检查MYSQL用户配置,这个在下面新建用户的时候讲,另外就算不给用户赋权限,用户也是可以登录的,不过只能看见information_schema这一个库
1.3还有一个是指定需要连接的数据库
mysql -u<用户名> -p<密码> -D<数据库名>
这个一般情况用不到,但是如果你新建了个用户,权限限制在某个数据库下
而且你登录的时候没有指定数据库,那么你会发现USE <数据库>是没有权限的
但是操作你赋权限的那个数据库是没有问题的,只不过每次操作都需要带上数据库名
这个时候就需要在连接的时候带上数据库名
重点:连接mysql数据库和当前终端用户有关 本机root用户登录mysql的root用户没问题 但是其他用户无法用root用户登入数据库 必须sudo才可以
而且linux下普通用户用非root用户登录mysql修改root密码无效 尽管显示成功了 但依然无法登录 root用户下用以前root的密码登录数据库依然成功
2用户操作
用户操作是最常用的了,有其实在新开一个数据库的时候需要添加用户并分配一些权限,不建议root用户搞开发,免得一不注意删错库了
2.1新建用户
CREATE USER <用户名>@<远程地址> IDENTIFIED BY <密码> [WITH GRANT OPTION]
例如:CREATE 'USER DBA_BOOK'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION;
用户名和密码建议用引号扩起来,反正密码要是不要引号扩起来是会报错的
远程地址可以用*代替,表示任意地址都可以使用该用户登录,
mysql默认的ROOT用户默认是只能在本机(LOCALHOST)登录
最后的with grant option可选,相当与设置该用户是否为管理员
如果设置了,那么该用户就可以新建别的用户并分配自己拥有的权限
当然下面可以单独设置那些权限运行他分配给别人
2.2添加权限
GRANT <权限> ON <数据库名>.<表名> TO <用户名>@<远程地址> [WITH GRANT OPTION]
例如:GRANT ALL PRIVILEGES ON db_book.* TO 'dba_book'@'%'
权限可以一次写多个,用逗号分来就可以
常用的包括SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER,INDEX
还有些GRANT,REFERENCE,PROCESS什么的,其他的想不起来了
比较蓝的话干脆ALL PRIVILEGES代替所有的权限
数据库名可以不写,那就代表当前数据库,如果当前没有选择数据库,那么执行指令会报错提示No database selected
其他的地方和新建用户的地方一样
当然用户名后面的@如果不写的话就是给所有你写的这个用户名相同的用户赋权限了
例如存在多个用户
'dba_book'@'localhost'
'dba_book'@'192.168.1.12'
'dba_book'@'172.18.49.141'
‘dba_book'@'%'
执行GRANT ALL PRIVILEGES ON 'db_book'.* TO 'dba_book'
于是这四个用户受影响了
另外localhost其实也是域名,不过大部分系统默认将其指向127.0.0.1,如果localhost指向的不是这个地址,那么数据库可能不是本地数据库
另外精确指定远程地址的用户的权限的优先级大于用百分号指定远程用户的权限
就是说如果上面第二个用户指定了一个INSERT权限,给第四个用户指定了SELECT权限,那么第二个用户就只能插入不能查询,其他用户(不包括第一个和第三个)就只能查询而不能插入
2.3回收权限
REVOKE <权限> ON <数据库名>.<表名> FROM <用户名>@<远程地址>
用法和赋权限一样,不再赘述
2.4删除用户
和删除表一样 DROP <用户名>@<远程地址>
之前用delete直接在user表删除用户 发现不管用 用户依然存在 因为再添加同名用户提示错误
3.数据导入(执行SQL脚本)
SOURCE <SQL脚本的绝对路径>
例如:SOURCE /root/backup/20110311_localhost_db_book.sql
嘿嘿,我是单用户系统,你们的大概都不会仍ROOT用户下吧,虽然我用单系统用的挺嗨的,但是还是要说,不喜欢折腾的别用ROOT用户,搞不好就玩脱了准备重装吧
比如你发现系统分区不够用的时候调整了一下分区,中间出了小插曲出错了,然后重启发现不能引导了,然后U盘的LIVE模式启动发现文件都丢了,
额。。。虽然和是不是用ROOT用户没啥关系,不过我还是要说,因为都是泪啊,不过还好不是公司服务器,公司服务器还在用WIN2000呢
额。。。跑题了,这是病,得治,电一下。。。算了,弃疗了
4.数据备份
如果不想学习MYSQL从删库到跑路的话就需要学习如何备份数据库
最简单的方法,复制
MYSQL的数据文件在/var/lib/mysql下,我是debian系的(包括ubuntu系列),红帽系(包括centos)的不知道是不是也在这
直接复制粘贴
cp -a /var/lib/mysql/* /root/backup/20180528_localhost_full/
恢复的时候直接粘回原地方就好了,别忘了粘回去的先把服务停掉,最好把目标位置清空了再粘回去
当然不一定要把数据库备份文件也仍在数据库服务器上,不然你要是一个rm -r * 不也是玩完
我没试过,有兴趣的可以自己试试,在虚拟机上试试就好,要在服务器上试的话先提前计划好逃跑路线
mysql提供了个客户端工具,mysqldump
我是这样用的mysqldump -u<用户名> -p<密码> -h<数据库地址> --databases <数据库名> > <备份文件的完整路径名,包括文件名>
例如:mysqldump -udba_book -p123456 -h192.168.1.144 --databases db_book > /root/backup/20180528_192.168.1.144_db_book.sql
注意那个尖括号不要忘了,这个尖括号不是提示符,是操作系统输出流的符号
一般和echo命令一起使用
例如echo hello > demo.txt
如果不存在demo.txt这个文件,则创建这个文件然后写入hello
如果存在demo.txt这个文件,则清空这个文件后写入hello
还有一个就是>>,这个和前者的区别是如果存在该文件,则在文件末尾追加输入的内容
例如在刚才执行echo hello > demo.txt的基础上再执行一次echo hello2 >> demo.txt
你会看到文件内容变成
hello
hello2
也就是说他会自动加一个换行符再写入新的内容
貌似又扯远了,不过我还是要说,windows和linux都有这两个命令
恢复数据的时候就用第三条数据导入的方法执行SQL文件就好了
5.常规操作
这里只是做个笔记,详细用法不写了,有需要的请去菜鸟教程,W3SCHOOL这些地方查询
5.1 SELECT
SELECT [DISTINCT] <选择列> FROM <数据库名>.<表名> WHERE <查询条件> GROUP BY <分组列名> HAVING <分组筛选条件> ORDER BY <排序列名> [ASC/DESC]
DISTINCT用于去除重复项,
例如tb_test
|- id -|
|------|
| 1 |
| 1 |
| 1 |
|------|
就这样的一张表,手打的,不要纠结好不好看了,反正我觉得不好看
内容仅供测试,应该没人像我这么无聊
SELECT DISTINCT * FROM test;
结果是
|- id -|
|------|
| 1 |
|------|
ORDER序默认升序ASC,降序用DESC
5.2 INSERT
INSERT INTO <数据库名>.<表名> (<列名>) VALUES (<值>)
INSERT INTO <数据库名>.<1表名> (<1列名>) SELECT (<2列名>) FROM <2表名> 。。。。。。这就和SELECT一样了
INSERT INTO <数据库名>.<表名> (<列名>) SELECT (<值>) FROM DUAL WHERE NOT EXISTS (SELECT * FROM <数据库名>.<表名> WHERE <列名>=<值>)
第三个语句可以达到插入不重复数据的目的,但是不太推荐,虽然可以插入不重复的数据,但是明显设置个唯一索引更方便,因为这种方法看上去执行效率都不会高,另外DUAL是一个MYSQL的临时表,在插入数据前他会把数据先扔在这里面再插入到目标表中
5.3 UPDATE
UPDATE <数据库名>.<表名> SET <列名>=<值> WHERE <列名>=<值>
UPDATE <数据库名>.<1表名> <表别名1>,<数据库名>.<2表名> <表别名2> SET <表别名1>.<列名>=<表别名2>.<值> WHERE <表别名1>.<列名>=<表别名2>.<值>
第二个语句这样也可以达到复制表的目的,而且只更新表1和表2里面都有的数据,当然依然存在效率较低的问题,1W条数据我执行了1分40秒,是不是该换电脑了
5.4 DELETE
DELETE FROM <数据库名>.<表名> WHERE <列名>=<值>
这种方法不会重置自动增长列,需要重置自动增长列只能重建表
修改自动增长列可以用ALTER TABLE <数据库名>.<表名> AUTO_INCREMENT = 1;
这种方式的问题是设置的自动增长列的数不能小于等于表中存在的自动增长列的大小
比如
|- id -|- name -|
|---------|------------|
|- 1 -|- a1 -|
|- 2 -|- a2 -|
|- 3 -|- a3 -|
|---------|------------|
假如此时这张表的自动增长列已经达到100了,执行上面那条语句后,自动增长列会变成4,而不是1,就是这个意思
6主外键及索引 想起来再写吧,困了,睡会
20191228
删除表的时候带上连接查询
表A
|---------------- A --------------------|
|- uuid -|- name -|- password -|
|- 1 -|- 1 -|- 123456 -|
|- 2 -|- 2 -|- 123456 -|
|- 3 -|- 3 -|- 123456 -|
|--------- B --------|
|- uuid -|- name -|
|- 1 -|- 张三 -|
|- 2 -|- 李四 -|
|- 3 -|- 王五 -|
表A中的name与表B中的uuid相关联
假如要删除张三的记录
DELETE A FROM A,B WHERE A.name=B.uuid WHERE B.name='张三';
我记得查的资料上说较低版本不支持DELETE A这块用别名
我用的是mariadb10.3.20 可以用别名