[Linux]Day30-20180606【SQL语句】

```
【本节主题:SQL语句】

回顾
1、范式
1NF
一个字段一个值
列的值不能重复
2NF
非主字段必须完全依赖主键
违反范式:复合主键
3NF
非主键不能存在依赖关系
2、ACID
A:原子性
C:一致性
I:隔离性
D:持续性
3、多实例

RDBMS常见组件
数据库

索引
视图
存储过程
存储函数
触发器
事件调度

SQL语言介绍
应用于RDBMS,最早由oracle商用
微软:T-SQL
oracle:PL/SQL

SQL语言规范
不区分大小写,但建议用大写
长语句建议分行书写
语句要以 ; 结尾
关键字不能简写
标准注释
/* 多行注释 */
-- 单行注释,
MySQL支持 # 注释

数据库对象
对象的分类
数据库

索引
视图
用户
存储过程
命名
必须以字母开头
只允许使用字母、数字、下划线
不要使用MySQL保留字
同一个数据库(Schema)不允许同名
实例instance
一套数据库应用软件
多个实例之间相互隔离

SQL语句分类
DDL:数据定义语言(数据对象)
CREATE 增
DROP 删
ALTER 改
DML:数据操作语言(数据库)
INSERT 增
DELETE 删
UPDATE 改
DCL:数据控制语言
GRANT 授权
撤销授权
DQL:数据查询语言
SELECT 查询

SQL语句构成
关键字keyword组成子句clause
多条子句共同组成一条语句

SQL帮助文档
https://dev.mysql.com/doc/refman/5.5/en/

数据库操作
创建数据库
指定数据库名(“如果不存在”避免报错)
CREATE DATABASE [IF NOT EXISTS]
SCHEMA [IF NOT EXISTS]
指定字符集
CHARACTRE SET
指定排序规则
COLLATE
删除数据库
DROP DATABASE
查看帮助
help
查看数据库
SHOW DATABASES;
注意!DATABASES是复数形式!!

-- 查看数据库
show databases;
-- 创建数据库
CREATE DATABASE db1;
-- 删除数据库
DROP DATABASE db1;
-- 查看系统支持的字符集
show CHARACTRE SET;
-- 查看排序规则
show COLLATE;
-- 查看子句的用法帮助
help CREATE DATABASE;


二维关系
设计表需要遵守规范
修饰

扫描二维码关注公众号,回复: 1586196 查看本文章

表操作
查看表
SHOW TABLES
查看所有引擎
SHOW ENGINES
查看表结构
DESC db_name.tb_name
删除表
DROP TABLE [IF EXISTS] tb_name
查看表创建命令
SHOW CREATE TABLE tbl_name
查看表状态
SHOW TABLE STATUS LIKE 'tbl_name'
查看指定数据库中所有表状态
SHOW TABLE STATUS FROM db_name
创建表
CREATE TABLE [IF NOT EXISTS]
create_definition
创建表的定义语句,字段用逗号隔开

-- 查看表
show TABLES;
-- 创建表
/*
tinyint unsigned :正整数,存储数据的宽度可变
not null :非空
primary key :指定为主键
char(10) :存放姓名,数据宽度占用10个字节
char(11) :存放手机号码,数据宽度占用11个字节
char(1) :存放性别属性,数据宽度占用1个字节
*/
CREATE TABLE students ( id tinyint unsigned not null primary key ,  name char(10) not null , phone char(11) , sex char(1) );
-- 查看表基本信息
show tables status like 'students'\G
-- 查看表结构
desc students;
-- 查看指定数据库中所有表的状态
show table status from students;

数据类型
三大原则
使用最小数据类型
简单数据类型的操作可以节省CPU周期
不要出现NULL值,可以添加默认值(NULL值不利于MySQL优化)
整型
TINYINT
0~255
unsigned:正数,要紧跟在数据类型后面,否则会报错
SMALLINT
INT
后面跟的length:显示的位数
字符型
CHAR
每个字符宽度一致
追求性能,查询速度快
VARCHAR
字符宽度可变
节约磁盘存储空间
日期时间类型
timestamp
自动更新的时间戳

创建表的第一种语法

-- 
/*auto_increment:编号自动递增*/
create table emp
( id int unsigned auto_increment primary key , 
name varchar(30) not null , 
sex char(1) default 'm' , 
address varchar(100) ) 
engine=innodb 
default charset=utf8;
-- 
show table status like 'emp'\G
-- 
show create table emp\G
-- 
show create table user\G

创建表的第二种语法

-- 
select user,host,password from mysql.user;
-- 只有表结构,不拷贝数据
create table user2 user,host,password from mysql.user where 1 = 0;
-- 
desc user2;
-- 
select * from user where 1 = 0;

创建表的第三种语法

-- 仿照别的表结构创建新表(不会拷贝数据)
create table user3 like mysql.user;
-- 
desc user3;
-- 
select * from user where 1 = 0;

问题:如何在不修改表结构的情况下,让查询结果中的表头显示为中文?

级联删除CASCADE
删除主键表附带删除与之关联的外键表
枚举ENUM
多个字符中只选一个,(单选)
多选SET
多个字符中选取多个
主键PRIMARY KEY

唯一键UNIQUE KEY
多个
允许为空

-- 
create table t1 
( name char(30) , 
city char(30) , 
sex char(1) , 
primary key(name,city) );

DML语句
INSERT
UPDATE
DELETE

(一)INSERT插入记录

-- 
insert students 
values(1, '10086' , 'm' );
-- 
select * from students;
-- 插入单条记录
insert students(name,id) 
values ('wang' , 70);
-- 
select * from students;
-- 插入多条记录
insert students(id,name,sex) 
values (2 , 'liu' , 'm'),(3 , 'lin' , 'f');
-- 
select * from students;

(二)UPDATE修改记录
一定要加WHERE条件!!!

-- 
update emp 
name='admin',address='beijing' 
where id=1;
-- 只修改前两行记录
update emp 
name='admin',address='beijing' 
where name='root' 
LIMIT 2;

(三)DELECT删除记录
一定要加WHERE条件!!!
生产中用“伪删除”来代替删除

三种等效的写法

# 使用安全模式
mysql --safe-updates
# 
musql -U
# 
mysql --i-am-a-dummy

vim /etc/my.cnf.d/mysql-clients.cnf

[mysql]
safe-updates

SELECT查询
不严谨的语句写法可能会造成服务器宕机

SELECT
as 字段显示使用别名
like 模糊搜索

-- 
select 'number',user,password from user;
-- 精确匹配,等号后面的字符串不能写错
select * from user where host='localhost';
-- 并且
select * from user 
where host='localhost' 
and user='root';
-- 或者
select * from user 
where host='localhost' 
or user='root';
-- 
select * from students 
where sex is null;
-- 
select * from students 
where sex is not null;
-- 
select * from students 
where id >= 2 
and id <= 5;
-- 
select * from students 
where id 
between 2 and 5;

注意:
between A and B 存在顺序,
A是小值,B是大值

-- 
select id 
as 编号 , name as 姓名 
from students as st;
-- 
select * from students where name like 'w%'

百分号:相当于通配符的星号,匹配任意个字符
下划线:相当于通配符的问号,匹配单个字符

-- 在phone列后面插入score列
alter students add score tinyint after phone;
-- 
select from students group by sex;
-- 
select sex , max(score)  as 最好成绩 
from students 
group by sex;
-- 
select sex , avg(score)  as 平均成绩 
from students 
group by sex;

1、用来分组的字段名本身
2、要汇总统计的字段

-- 
alter table students 
add class tinyint default 1
-- 
select class,sex,avg(score) 
from students 
group by class,sex;
-- 分组后过滤
select class,sex,avg(score) 
from students 
group by class,sex 
having avg(score) > 80;

正向排序

-- 
select * from students 
order by score asc;

逆向排序

-- 
select * from students 
order by score desc;

针对NULL特别优化

-- 把NULL排在最后面
select * from students 
order by -score desc;
-- 把NULL排在最前面
select * from students 
order by -score asc;

限制条件

-- 
select * from students order by score limit 3;

使用sql脚本的第一种方法

mysql < hellodb.sql

使用sql脚本的第二种方法

source hellodb.sql

多表查询

内连接:两张表取交集

-- 旧写法
select 
s.name as student_name , t.name as teacher_name 
from 
students as s , teacher as t 
where 
s.teacherid=t.tid;
-- 新写法
select 
s.name as student_name , t.name as teacher_name 
from 
students as s 
inner join 
teachers as t
on 
s.teacherid=t.tid;

左外连接

-- students表在左边(取全部),teachers表在右边(只取交集)
select 
s.name as student_name , t.name as teacher_name 
from 
students as s 
left outer join 
teachers as t 
on 
s.teacherid=t.tid;

右外连接

-- students表在左边(只取交集),teachers表在右边(取全部)
select 
s.name as student_name , t.name as teacher_name 
from 
students as s 
right outer join 
teachers as t 
on 
s.teacherid=t.tid;
-- students表在左边,teachers表在右边
-- 取出students表中不包含两表交集的部分
select 
s.name as student_name , t.name as teacher_name 
from 
students as s 
left outer join 
teachers as t 
on 
s.teacherid=t.tid and t.name=null;

完全外连接??

-- 
select stuid , name 
from students 
union 
select tid,name 
from teachers;

完全外连接

-- 
select 
s.name as student_name , t.name as teacher_name 
from 
students as s
left outer join 
teachers as t 
on
s.teacherid=t.tid 
union 
select 
s.name as student_name , t.name as teacher_name 
from 
students as s 
right outer join 
teachers as t 
on 
s.teacherid=t.tid 
where 
s.teacherid is null 
or 
t.tid is null;

自连接

-- 
select 
s1.name as emp , s2.name as leader 
from 
students as s1 
inner join 
students as s2 
on 
s1.teacherid=s2.stuid;

子查询

SELECT执行流程
找表
过滤条件
分组
挑列
挑行

练习题一

-- 
select 

from 
students 
where 
age > 25 
group by 
gender;

练习题二

-- 
select name from students 
where 
age > (select avg(age) from students);

视图:相当于Shell中的别名
相当于假的表
用“查看表状态”可以看到
COMMENT : VIEW
可以隐藏磁盘上数据的逻辑结构
视图本身不存储数据,可以通过视图间接修改表

-- 创建视图
create view view_students 
as select stuid , name from students;
-- 
select * from view_students;

物化视图
相当于实体表,会占用磁盘空间,
但是:MySQL不支持此技术

删除视图 DROP VIEW_NAME 不会删除表数据,类似于Shell中删除别名操作

函数
函数不能独立运行,必须嵌入SQL语句才能运行

自定义函数UDF
delimiter //

delimiter;

存储过程
系统数据库mysql用来存储设置信息:函数、变量
mysql.proc存放存储过程

调用存储过程
    CALL PROCEDURE_NAME(ARGS)

触发器

MySQL用户与权限管理
用户帐号的符号格式(写法)
'USERNAME'@'HOST'
匿名用户

创建用户
(1)指定用户名
(2)指定主机
(3)默认权限:USAGE,只能连接数据库,不能做其他的操作(增删改查)

-- 创建用户
/*控制用户只能在192.168.30.6上登录*/
create user 'wang'@'192.168.30.6' identified by 'centos'
-- 刷新权限策略
flush privileges;
-- 
select user , host , password from user.mysql;
-- 删除匿名用户
drop user ''@'localhost';
# 添加数据库的root口令
mysqladmin password 'centos'
# 使用新口令登录数据库
mysql -uroot -pcentos

破解数据库的root口令
1、停止服务
2、修改配置文件:/etc/my.cnf
在文件头添加一行:skip-grant-tables
3、启动服务
4、mysql客户端免密码登录
5、改user.mysql表
update user.mysql set password=password('centos') where user='root' and host='localhost';
6、退出登录
7、再次修改配置文件:/etc/my.cnf
删除刚刚添加的这一行:skip-grant-tables
8、重启服务
9、使用新密码登录mysql客户端

```

猜你喜欢

转载自www.cnblogs.com/linyongfeng/p/9179515.html