MySQL:SQL進階

1、數據庫相關理論

一、系統數據庫

information_schema: 虛擬庫,不佔用磁盤空間,存儲的是數據庫啓動後的一些參數,如用戶表信息、列信息、權限信息、字符信息等
performance_schema: MySQL 5.5開始新增一個數據庫:主要用於收集數據庫服務器性能參數,記錄處理查詢請求時發生的各類事件、鎖等現象 
mysql: 受權庫,主要存儲系統用戶的權限信息
test: MySQL數據庫系統自動建立的測試數據庫html

二、建立庫

1 語法(help create database)

CREATE DATABASE 數據庫名 charset utf8;

2 數據庫命名規則:

能夠由字母、數字、下劃線、@、#、$
區分大小寫
惟一性
不能使用關鍵字如 create select
不能單獨使用數字
最長128位

三、庫相關操做

詳細見 SQL(1)mysql

2、表相關理論

表的本質即爲 ‘文件’nginx

一、存儲引擎

文件(表)的類型在MySQL中稱之爲存儲引擎sql

不一樣的類型會對應不一樣的處理機制數據庫

引擎的區別(主要)

#引擎 
# innodb   支持事務,原子性操做
#               支持行鎖
#               支持外鍵
# myisam   查詢速度快 不支持事務
#               支持表鎖
#               不支持外鍵

sql底層流程

'''
sql底層流程原理:
一、一堆接口(Python、Perl、Ruby等等)

二、鏈接池(併發,爲了機器的負載均衡引入池)

三、sql接口(數據庫操做命令,存儲過程,視圖,觸發器等等)

四、解析器(sql語句(有執行優先級之分),查詢\事務)

五、優化查詢(索引技術,最少的IO)

六、緩存\緩衝池(內存空間,存儲經常使用的數據,提高速度)

七、存儲引擎
  myisam    
  innodb   支持事務,行鎖,支持外鍵 
  memory 內存

八、文件系統
'''

 

                                                                                查看存儲引擎 圖vim

 

二、表操做之約束條件

 約束條件與數據類型的寬度同樣,是可選參數windows

做用:用於保證數據的完整性和一致性緩存

# PRIMARY KEY (PK)    標識該字段爲該表的主鍵,能夠惟一的標識記錄
# FOREIGN KEY (FK)    標識該字段爲該表的外鍵
# NOT NULL            標識該字段不能爲空
# UNIQUE KEY (UK)     標識該字段的值是惟一的
# AUTO_INCREMENT      標識該字段的值自動增加(整數類型,並且爲主鍵)
# DEFAULT             爲該字段設置默認值

# UNSIGNED  無符號
# ZEROFILL  使用0填充

 說明:bash

1. 是否容許爲空,默認NULL,可設置NOT NULL,字段不容許爲空,必須賦值
2. 字段是否有默認值,缺省的默認值是NULL,若是插入記錄時不給字段賦值,此字段使用默認值
sex enum('male','female') not null default 'male'
age int unsigned NOT NULL default 20 必須爲正值(無符號) 不容許爲空 默認是20
3. 是不是key
主鍵 primary key
外鍵 foreign key
索引 (index,unique...)

2.1  not null 和 default

是否可空,null表示空,非字符串
not null - 不可空
null - 可空服務器


默認值,建立列時能夠指定默認值,當插入數據時若是未主動設置,則自動添加默認值
create table tb1(
nid int not null defalut 2,
num int not null
)

==================not null====================
mysql> create table t1(id int); #id字段默承認以插入空
mysql> desc t1;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
mysql> insert into t1 values(); #能夠插入空


mysql> create table t2(id int not null); #設置字段id不爲空
mysql> desc t2;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
mysql> insert into t2 values(); #不能插入空
ERROR 1364 (HY000): Field 'id' doesn't have a default value



==================default====================
#設置id字段有默認值後,則不管id字段是null仍是not null,均可以插入空,插入空默認填入default指定的默認值
mysql> create table t3(id int default 1);
mysql> alter table t3 modify id int not null default 1;



==================綜合練習====================
mysql> create table student(
    -> name varchar(20) not null,
    -> age int(3) unsigned not null default 18,
    -> sex enum('male','female') default 'male',
    -> hobby set('play','study','read','music') default 'play,music'
    -> );
mysql> desc student;
+-------+------------------------------------+------+-----+------------+-------+
| Field | Type                               | Null | Key | Default    | Extra |
+-------+------------------------------------+------+-----+------------+-------+
| name  | varchar(20)                        | NO   |     | NULL       |       |
| age   | int(3) unsigned                    | NO   |     | 18         |       |
| sex   | enum('male','female')              | YES  |     | male       |       |
| hobby | set('play','study','read','music') | YES  |     | play,music |       |
+-------+------------------------------------+------+-----+------------+-------+
mysql> insert into student(name) values('mogu');
mysql> select * from student;
+------+-----+------+------------+
| name | age | sex  | hobby      |
+------+-----+------+------------+
| mogu |  18 | male | play,music |
+------+-----+------+------------+
View Code

 2.2 unique key

============設置惟一約束 UNIQUE===============
方法一:
create table department1(
id int,
name varchar(20) unique,
comment varchar(100)
);


方法二:
create table department2(
id int,
name varchar(20),
comment varchar(100),
constraint uk_name unique(name)
);


mysql> insert into department1 values(1,'IT','技術');
Query OK, 1 row affected (0.00 sec)
mysql> insert into department1 values(1,'IT','技術');
ERROR 1062 (23000): Duplicate entry 'IT' for key 'name'
View Code
create table service(
id int primary key auto_increment,
name varchar(20),
host varchar(15) not null,
port int not null,
unique(host,port) #聯合惟一
);

mysql> insert into service values
    -> (1,'nginx','192.168.0.10',80),
    -> (2,'haproxy','192.168.0.20',80),
    -> (3,'mysql','192.168.0.30',3306)
    -> ;
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> insert into service(name,host,port) values('nginx','192.168.0.10',80);
ERROR 1062 (23000): Duplicate entry '192.168.0.10-80' for key 'host'
聯合惟一

2.3  primary key

從約束角度看primary key字段的值不爲空且惟一,那咱們直接使用not null+unique不就能夠了嗎,要它幹什麼?

主鍵primary key是innodb存儲引擎組織數據的依據,innodb稱之爲索引組織表,一張表中必須有且只有一個主鍵

一個表中能夠:

單列作主鍵
多列作主鍵(複合主鍵)

============單列作主鍵===============
#方法一:not null+unique
create table department1(
id int not null unique, #主鍵
name varchar(20) not null unique,
comment varchar(100)
);

mysql> desc department1;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | NO   | UNI | NULL    |       |
| comment | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)

#方法二:在某一個字段後用primary key
create table department2(
id int primary key, #主鍵
name varchar(20),
comment varchar(100)
);

mysql> desc department2;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| comment | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.00 sec)

#方法三:在全部字段後單獨定義primary key
create table department3(
id int,
name varchar(20),
comment varchar(100),
constraint pk_name primary key(id); #建立主鍵併爲其命名pk_name

mysql> desc department3;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| comment | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)
單列主鍵
==================多列作主鍵================
create table service(
ip varchar(15),
port char(5),
service_name varchar(10) not null,
primary key(ip,port)
);


mysql> desc service;
+--------------+-------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| ip           | varchar(15) | NO   | PRI | NULL    |       |
| port         | char(5)     | NO   | PRI | NULL    |       |
| service_name | varchar(10) | NO   |     | NULL    |       |
+--------------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> insert into service values
    -> ('172.16.45.10','3306','mysqld'),
    -> ('172.16.45.11','3306','mariadb')
    -> ;
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into service values ('172.16.45.10','3306','nginx');
ERROR 1062 (23000): Duplicate entry '172.16.45.10-3306' for key 'PRIMARY'
多列主鍵

2.4  auto_increment

 約束字段爲自動增加,被約束的字段必須同時被key約束

#不指定id,則自動增加
create table student(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') default 'male'
);

mysql> desc student;
+-------+-----------------------+------+-----+---------+----------------+
| Field | Type                  | Null | Key | Default | Extra          |
+-------+-----------------------+------+-----+---------+----------------+
| id    | int(11)               | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)           | YES  |     | NULL    |                |
| sex   | enum('male','female') | YES  |     | male    |                |
+-------+-----------------------+------+-----+---------+----------------+
mysql> insert into student(name) values
    -> ('egon'),
    -> ('alex')
    -> ;

mysql> select * from student;
+----+----------+------+
| id | name     | sex  |
+----+----------+------+
|  1 | mogu     | male |
|  2 | xiaoming | male |
+----+----------+------+
2 rows in set (0.00 sec)
#也能夠指定id
mysql> insert into student values (4,'xiaonvhai','female');
Query OK, 1 row affected (0.01 sec)

mysql> insert into student values (7,'xiaohuochai','male');
Query OK, 1 row affected (0.00 sec)

mysql> select * from student;
+----+-------------+--------+
| id | name        | sex    |
+----+-------------+--------+
|  1 | mogu        | male   |
|  2 | xiaoming    | male   |
|  4 | xiaonvhai   | female |
|  7 | xiaohuochai | male   |
+----+-------------+--------+
4 rows in set (0.00 sec)
#對於自增的字段,在用delete刪除後,再插入值,該字段仍按照刪除前的位置繼續增加
mysql> delete from student;
Query OK, 4 rows affected (0.01 sec)

mysql> select * from student;
Empty set (0.00 sec)

mysql> insert into student (name) values ('zhangsan');
Query OK, 1 row affected (0.01 sec)

mysql> select * from student;
+----+----------+------+
| id | name     | sex  |
+----+----------+------+
|  8 | zhangsan | male |
+----+----------+------+
1 row in set (0.00 sec)
#應該用truncate清空表,比起delete一條一條地刪除記錄,truncate是直接清空表,在刪除大表時用它
mysql> truncate student;
Query OK, 0 rows affected (0.03 sec)

mysql> insert into student (name) values ('lisi');
Query OK, 1 row affected (0.01 sec)

mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  1 | lisi | male |
+----+------+------+
1 row in set (0.00 sec)
View Code
#在建立完表後,修改自增字段的起始值
mysql> create table student(
    -> id int primary key auto_increment,
    -> name varchar(20),
    -> sex enum('male','female') default 'male'
    -> );

mysql> alter table student auto_increment=4;#修改起始值

mysql> show create table student;
.......
ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

mysql> insert into student (name)values('xiaomogu');
Query OK, 1 row affected (0.01 sec)

mysql> select * from student;
+----+----------+------+
| id | name     | sex  |
+----+----------+------+
|  4 | xiaomogu | male |
+----+----------+------+
1 row in set (0.00 sec)

mysql> show create table student;
.......
ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
#也能夠建立表時指定auto_increment的初始值,注意初始值的設置爲表選項,應該放到括號外
create table student(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') default 'male'
)auto_increment=3;
瞭解自增

2.5  foreign key 外鍵

1、 快速理解foreign key

員工信息表有三個字段:工號  姓名  部門

公司有3個部門,可是有1個億的員工,那意味着部門這個字段須要重複存儲,部門名字越長,越浪費

解決方法:

咱們徹底能夠定義一個部門表

而後讓員工信息表關聯該表,如何關聯,即foreign key

#表類型必須是innodb存儲引擎,且被關聯的字段,即references指定的另一個表的字段,必須保證惟一
create table department(
id int primary key,
name varchar(20) not null
)engine=innodb;

#dpt_id外鍵,關聯父表(department主鍵id),同步更新,同步刪除
create table employee(
id int primary key,
name varchar(20) not null,
dpt_id int,
constraint fk_name foreign key(dpt_id)
references department(id)
on delete cascade
on update cascade 
)engine=innodb;


#先往父表department中插入記錄
insert into department values
(1,'歐德博愛技術有限事業部'),
(2,'艾利克斯人力資源部'),
(3,'銷售部');


#再往子表employee中插入記錄
insert into employee values
(1,'egon',1),
(2,'alex1',2),
(3,'alex2',2),
(4,'alex3',2),
(5,'李坦克',3),
(6,'劉飛機',3),
(7,'張火箭',3),
(8,'林子彈',3),
(9,'加特林',3)
;


#刪父表department,子表employee中對應的記錄跟着刪
mysql> delete from department where id=3;
mysql> select * from employee;
+----+-------+--------+
| id | name  | dpt_id |
+----+-------+--------+
|  1 | egon  |      1 |
|  2 | alex1 |      2 |
|  3 | alex2 |      2 |
|  4 | alex3 |      2 |
+----+-------+--------+


#更新父表department,子表employee中對應的記錄跟着改
mysql> update department set id=22222 where id=2;
mysql> select * from employee;
+----+-------+--------+
| id | name  | dpt_id |
+----+-------+--------+
|  1 | egon  |      1 |
|  3 | alex2 |  22222 |
|  4 | alex3 |  22222 |
|  5 | alex1 |  22222 |
+----+-------+--------+
示例

二 、如何找出兩張表之間的關係 

分析步驟:
#一、先站在左表的角度去找
是否左表的多條記錄能夠對應右表的一條記錄,若是是,則證實左表的一個字段foreign key 右表一個字段(一般是id)

#二、再站在右表的角度去找
是否右表的多條記錄能夠對應左表的一條記錄,若是是,則證實右表的一個字段foreign key 左表一個字段(一般是id)

#三、總結:
#多對一:
若是隻有步驟1成立,則是左表多對一右表
若是隻有步驟2成立,則是右表多對一左表

#多對多
若是步驟1和2同時成立,則證實這兩張表時一個雙向的多對一,即多對多,須要定義一個這兩張表的關係表來專門存放兩者的關係

#一對一:
若是1和2都不成立,而是左表的一條記錄惟一對應右表的一條記錄,反之亦然。這種狀況很簡單,就是在左表foreign key右表的基礎上,將左表的外鍵字段設置成unique便可

3、 創建表之間的關係

#一對多或稱爲多對一
三張表:出版社,做者信息,書

一對多(或多對一):一個出版社能夠出版多本書

關聯方式:foreign key
=====================多對一=====================
create table press(
id int primary key auto_increment,
name varchar(20)
);

create table book(
id int primary key auto_increment,
name varchar(20),
press_id int not null,
foreign key(press_id) references press(id)
on delete cascade
on update cascade
);


insert into press(name) values
('北京工業地雷出版社'),
('人民音樂很差聽出版社'),
('知識產權沒有用出版社')
;

insert into book(name,press_id) values
('九陽神功',1),
('九陰真經',2),
('九陰白骨爪',2),
('獨孤九劍',3),
('降龍十巴掌',2),
('葵花寶典',3)
;
View Code
#多對多
三張表:出版社,做者信息,書

多對多:一個做者能夠寫多本書,一本書也能夠有多個做者,雙向的一對多,即多對多
  
關聯方式:foreign key+一張新的表
=====================多對多=====================
create table author(
id int primary key auto_increment,
name varchar(20)
)engine=innodb default charset=utf8;

create table book(
id int primary key auto_increment,
name varchar(10),
type varchar(10) not null default ''
)engine=innodb default charset=utf8;

#這張表就存放做者表與書表的關係,即查詢兩者的關係查這表就能夠了
create table author2book(
id int not null unique auto_increment,
author_id int not null,
book_id int not null,
constraint fk_author foreign key(author_id) references author(id)
on delete cascade
on update cascade,
constraint fk_book foreign key(book_id) references book(id)
on delete cascade
on update cascade,
primary key(author_id,book_id)
);


#插入四個做者,id依次排開
insert into author(name) values('mogu'),('zhangsan'),('lisi'),('wangwu');

#每一個做者與本身的表明做以下
1 mogu: 
      1 一千零一晚上
      2 安徒生童話
      3 葫蘆娃
      4 變形金剛
      5 七個小矮人
      6 白雪公主


2 zhangsan: 
      1 一千零一晚上
      6 白雪公主

3 lisi:
      4 變形金剛
      5 七個小矮人
      6 白雪公主

4 wangwu:
      3 葫蘆娃


insert into author2book(author_id,book_id) values
(1,1),
(1,2),
(1,3),
(1,4),
(1,5),
(1,6),
(2,1),
(2,6),
(3,4),
(3,5),
(3,6),
(4,3)
;
View Code

 

#一對一
兩張表:學生表和客戶表

一對一:一個學生是一個客戶,一個客戶有可能變成一個學校,即一對一的關係

關聯方式:foreign key+unique
#必定是student來foreign key表customer,這樣就保證了:
#1 學生必定是一個客戶,
#2 客戶不必定是學生,但有可能成爲一個學生


create table customer(
id int primary key auto_increment,
name varchar(20) not null,
qq varchar(10) not null,
phone char(11) not null
);


create table student(
id int primary key auto_increment,
class_name varchar(20) not null,
customer_id int unique, #該字段必定要是惟一的
foreign key(customer_id) references customer(id) #外鍵的字段必定要保證unique
on delete cascade
on update cascade
);


#增長客戶
insert into customer(name,qq,phone) values
('小沫沫','31811231',13811341220),
('王三炮','123123123',15213146809),
('王山炮','283818181',1867141331),
('趙銀宕','283818181',1851143312),
('王巴彈','888818181',1861243314),
('李大龍','112312312',18811431230)
;


#增長學生
insert into student(class_name,customer_id) values
('全棧開發班',3),
('系統架構班',4),
('軟件分析班',5)
;
View Code

3、單表查詢

一、單表查詢的語法

SELECT 字段1,字段2... FROM 表名
                     WHERE 條件
                     GROUP BY field
                     HAVING 篩選
                     ORDER BY field
                     LIMIT 限制條數

二、關鍵字的執行優先級(重點)

重點中的重點:關鍵字的執行優先級
from
where
group by
having
select
distinct
order by
limit

1.找到表:from

2.拿着where指定的約束條件,去文件/表中取出一條條記錄

3.將取出的一條條記錄進行分組group by,若是沒有group by,則總體做爲一組

4.將分組的結果進行having過濾

5.執行select

6.去重

7.將結果按條件排序:order by

8.限制結果的顯示條數

三、簡單查詢

company.employee
    員工id      id                  int             
    姓名        emp_name            varchar
    性別        sex                 enum
    年齡        age                 int
    入職日期     hire_date           date
    崗位        post                varchar
    職位描述     post_comment        varchar
    薪水        salary              double
    辦公室       office              int
    部門編號     depart_id           int



#建立表
create table employee(
id int not null unique auto_increment,
name varchar(20) not null,
sex enum('male','female') not null default 'male', #大部分是男的
age int(3) unsigned not null default 28,
hire_date date not null,
post varchar(50),
post_comment varchar(100),
salary double(15,2),
office int, #一個部門一個屋子
depart_id int
);


#查看錶結構
mysql> desc employee;
+--------------+-----------------------+------+-----+---------+----------------+
| Field        | Type                  | Null | Key | Default | Extra          |
+--------------+-----------------------+------+-----+---------+----------------+
| id           | int(11)               | NO   | PRI | NULL    | auto_increment |
| name         | varchar(20)           | NO   |     | NULL    |                |
| sex          | enum('male','female') | NO   |     | male    |                |
| age          | int(3) unsigned       | NO   |     | 28      |                |
| hire_date    | date                  | NO   |     | NULL    |                |
| post         | varchar(50)           | YES  |     | NULL    |                |
| post_comment | varchar(100)          | YES  |     | NULL    |                |
| salary       | double(15,2)          | YES  |     | NULL    |                |
| office       | int(11)               | YES  |     | NULL    |                |
| depart_id    | int(11)               | YES  |     | NULL    |                |
+--------------+-----------------------+------+-----+---------+----------------+

#插入記錄
#三個部門:教學,銷售,運營
insert into employee(name,sex,age,hire_date,post,salary,office,depart_id) values
('egon','male',18,'20170301','老男孩駐沙河辦事處外交大使',7300.33,401,1), #如下是教學部
('alex','male',78,'20150302','teacher',1000000.31,401,1),
('wupeiqi','male',81,'20130305','teacher',8300,401,1),
('yuanhao','male',73,'20140701','teacher',3500,401,1),
('liwenzhou','male',28,'20121101','teacher',2100,401,1),
('jingliyang','female',18,'20110211','teacher',9000,401,1),
('jinxin','male',18,'19000301','teacher',30000,401,1),
('成龍','male',48,'20101111','teacher',10000,401,1),

('歪歪','female',48,'20150311','sale',3000.13,402,2),#如下是銷售部門
('丫丫','female',38,'20101101','sale',2000.35,402,2),
('丁丁','female',18,'20110312','sale',1000.37,402,2),
('星星','female',18,'20160513','sale',3000.29,402,2),
('格格','female',28,'20170127','sale',4000.33,402,2),

('張野','male',28,'20160311','operation',10000.13,403,3), #如下是運營部門
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬銀','female',18,'20130311','operation',19000,403,3),
('程咬銅','male',18,'20150411','operation',18000,403,3),
('程咬鐵','female',18,'20140512','operation',17000,403,3)
;

#ps:若是在windows系統中,插入中文字符,select的結果爲空白,能夠將全部字符編碼統一設置成gbk
建立表和記錄
#簡單查詢
    SELECT id,name,sex,age,hire_date,post,post_comment,salary,office,depart_id 
    FROM employee;

    SELECT * FROM employee;

    SELECT name,salary FROM employee;

#避免重複DISTINCT  !!!
    SELECT DISTINCT post FROM employee;    

#經過四則運算查詢
    SELECT name, salary*12 FROM employee;
    SELECT name, salary*12 AS Annual_salary FROM employee;
    SELECT name, salary*12 Annual_salary FROM employee;

#定義顯示格式
   CONCAT() 函數用於鏈接字符串
   SELECT CONCAT('姓名: ',name,'  年薪: ', salary*12)  AS Annual_salary 
   FROM employee;
   
   CONCAT_WS() 第一個參數爲分隔符
   SELECT CONCAT_WS(':',name,salary*12)  AS Annual_salary 
   FROM employee;

   結合CASE語句:
   SELECT
       (
           CASE
           WHEN NAME = 'egon' THEN
               NAME
           WHEN NAME = 'alex' THEN
               CONCAT(name,'_BIGSB')
           ELSE
               concat(NAME, 'SB')
           END
       ) as new_name
   FROM
       emp;

四、where 約束

where字句中可使用:

1. 比較運算符:> < >= <= <> !=
2. between 80 and 100 值在10到20之間
3. in(80,90,100) 值是10或20或30
4. like 'egon%'
    pattern能夠是%或_,
    %表示任意多字符
    _表示一個字符 
5. 邏輯運算符:在多個條件直接可使用邏輯運算符 and or not

#1:單條件查詢
    SELECT name FROM employee
        WHERE post='sale';
        
#2:多條件查詢
    SELECT name,salary FROM employee
        WHERE post='teacher' AND salary>10000;

#3:關鍵字BETWEEN AND
    SELECT name,salary FROM employee 
        WHERE salary BETWEEN 10000 AND 20000;

    SELECT name,salary FROM employee 
        WHERE salary NOT BETWEEN 10000 AND 20000;
    
#4:關鍵字IS NULL(判斷某個字段是否爲NULL不能用等號,須要用IS)
    SELECT name,post_comment FROM employee 
        WHERE post_comment IS NULL;

    SELECT name,post_comment FROM employee 
        WHERE post_comment IS NOT NULL;
        
    SELECT name,post_comment FROM employee 
        WHERE post_comment=''; 注意''是空字符串,不是null
    ps:
        執行
        update employee set post_comment='' where id=2;
        再用上條查看,就會有結果了

#5:關鍵字IN集合查詢
    SELECT name,salary FROM employee 
        WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ;
    
    SELECT name,salary FROM employee 
        WHERE salary IN (3000,3500,4000,9000) ;

    SELECT name,salary FROM employee 
        WHERE salary NOT IN (3000,3500,4000,9000) ;

#6:關鍵字LIKE模糊查詢
    通配符’%’
    SELECT * FROM employee 
            WHERE name LIKE 'eg%';

    通配符’_’
    SELECT * FROM employee 
            WHERE name LIKE 'al__';

五、分組查詢:group by

#一、首先明確一點:分組發生在where以後,即分組是基於where以後獲得的記錄而進行的

#二、分組指的是:將全部記錄按照某個相同字段進行歸類,好比針對員工信息表的職位分組,或者按照性別進行分組等

#三、爲什麼要分組呢?
    取每一個部門的最高工資
    取每一個部門的員工數
    取男人數和女人數

小竅門:‘每’這個字後面的字段,就是咱們分組的依據


#四、大前提:
    能夠按照任意字段分組,可是分組完畢後,好比group by post,只能查看post字段,若是想查看組內信息,須要藉助於聚合函數
mysql> select @@global.sql_mode;
+-------------------+
| @@global.sql_mode |
+-------------------+
|                   |
+-------------------+
1 row in set (0.00 sec)

mysql> select * from emp group by post; 
+----+------+--------+-----+------------+----------------------------+--------------+------------+--------+-----------+
| id | name | sex    | age | hire_date  | post                       | post_comment | salary     | office | depart_id |
+----+------+--------+-----+------------+----------------------------+--------------+------------+--------+-----------+
| 14 | 張野 | male   |  28 | 2016-03-11 | operation                  | NULL         |   10000.13 |    403 |         3 |
|  9 | 歪歪 | female |  48 | 2015-03-11 | sale                       | NULL         |    3000.13 |    402 |         2 |
|  2 | alex | male   |  78 | 2015-03-02 | teacher                    | NULL         | 1000000.31 |    401 |         1 |
|  1 | egon | male   |  18 | 2017-03-01 | 老男孩駐沙河辦事處外交大使 | NULL         |    7300.33 |    401 |         1 |
+----+------+--------+-----+------------+----------------------------+--------------+------------+--------+-----------+
4 rows in set (0.00 sec)


#因爲沒有設置ONLY_FULL_GROUP_BY,因而也能夠有結果,默認都是組內的第一條記錄,但其實這是沒有意義的

mysql> set global sql_mode='ONLY_FULL_GROUP_BY';
Query OK, 0 rows affected (0.00 sec)

mysql> quit #設置成功後,必定要退出,而後從新登陸方可生效
Bye

mysql> use db1;
Database changed
mysql> select * from emp group by post; #報錯
ERROR 1055 (42000): 'db1.emp.id' isn't in GROUP BY
mysql> select post,count(id) from emp group by post; #只能查看分組依據和使用聚合函數
+----------------------------+-----------+
| post                       | count(id) |
+----------------------------+-----------+
| operation                  |         5 |
| sale                       |         5 |
| teacher                    |         7 |
| 老男孩駐沙河辦事處外交大使 |         1 |
+----------------------------+-----------+
4 rows in set (0.00 sec)
View Code
單獨使用GROUP BY關鍵字分組
    SELECT post FROM employee GROUP BY post;
    注意:咱們按照post字段分組,那麼select查詢的字段只能是post,想要獲取組內的其餘相關信息,須要藉助函數

GROUP BY關鍵字和GROUP_CONCAT()函數一塊兒使用
    SELECT post,GROUP_CONCAT(name) FROM employee GROUP BY post;#按照崗位分組,並查看組內成員名
    SELECT post,GROUP_CONCAT(name) as emp_members FROM employee GROUP BY post;

GROUP BY與聚合函數一塊兒使用
    select post,count(id) as count from employee group by post;#按照崗位分組,並查看每一個組有多少人
group by 注意點

ps:

若是咱們用unique的字段做爲分組的依據,則每一條記錄自成一組,這種分組沒有意義
多條記錄之間的某個字段值相同,該字段一般用來做爲分組的依據

聚合函數

#強調:聚合函數聚合的是組的內容,如果沒有分組,則默認一組

示例:
    SELECT COUNT(*) FROM employee;
    SELECT COUNT(*) FROM employee WHERE depart_id=1;
    SELECT MAX(salary) FROM employee;
    SELECT MIN(salary) FROM employee;
    SELECT AVG(salary) FROM employee;
    SELECT SUM(salary) FROM employee;
    SELECT SUM(salary) FROM employee WHERE depart_id=3;

#主要爲5個: count、max、min、avg、sum

六、having 過濾

#!  執行優先級從高到低:where > group by > having 
#1. Where 發生在分組group by以前,於是Where中能夠有任意字段,可是絕對不能使用聚合函數。 #2. Having發生在分組group by以後,於是Having中可使用分組的字段,沒法直接取到其餘字段,可使用聚合函數
mysql> select @@sql_mode;
+--------------------+
| @@sql_mode         |
+--------------------+
| ONLY_FULL_GROUP_BY |
+--------------------+
1 row in set (0.00 sec)

mysql> select * from emp where salary > 100000;
+----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
| id | name | sex  | age | hire_date  | post    | post_comment | salary     | office | depart_id |
+----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
|  2 | alex | male |  78 | 2015-03-02 | teacher | NULL         | 1000000.31 |    401 |         1 |
+----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
1 row in set (0.00 sec)

mysql> select * from emp having salary > 100000;
ERROR 1463 (42000): Non-grouping field 'salary' is used in HAVING clause

mysql> select post,group_concat(name) from emp group by post having salary > 10000;#錯誤,分組後沒法直接取到salary字段
ERROR 1054 (42S22): Unknown column 'salary' in 'having clause'
mysql> select post,group_concat(name) from emp group by post having avg(salary) > 10000;
+-----------+-------------------------------------------------------+
| post | group_concat(name) |
+-----------+-------------------------------------------------------+
| operation | 程咬鐵,程咬銅,程咬銀,程咬金,張野 |
| teacher | 成龍,jinxin,jingliyang,liwenzhou,yuanhao,wupeiqi,alex |
+-----------+-------------------------------------------------------+
2 rows in set (0.00 sec)
示例

七、order by 查詢排序

#  where > group by > having > distinct > order by
按單列排序
    SELECT * FROM employee ORDER BY salary;
    SELECT * FROM employee ORDER BY salary ASC;
    SELECT * FROM employee ORDER BY salary DESC;

按多列排序:先按照age排序,若是年紀相同,則按照薪資排序
    SELECT * from employee
        ORDER BY age,
        salary DESC;

八、LIMIT 限制查詢數

示例:
    SELECT * FROM employee ORDER BY salary DESC 
        LIMIT 3;                    #默認初始位置爲0 
    
    SELECT * FROM employee ORDER BY salary DESC
        LIMIT 0,5; #從第0開始,即先查詢出第一條,而後包含這一條在內日後查5條

    SELECT * FROM employee ORDER BY salary DESC
        LIMIT 5,5; #從第5開始,即先查詢出第6條,而後包含這一條在內日後查5條

九、使用正則匹配

SELECT * FROM employee WHERE name REGEXP '^ale';

SELECT * FROM employee WHERE name REGEXP 'on$';

SELECT * FROM employee WHERE name REGEXP 'm{2}';
^ 以什麼開頭
$ 以什麼結尾
小結:對字符串匹配的方式
WHERE name = 'mogu';
WHERE name LIKE 'yua%';
WHERE name REGEXP 'on$';
select * from employee where name regexp '^jin.*[gn]$';
查看全部員工中名字是jin開頭,n或者g結果的員工信息

 

4、多表查詢

#建表
create table department(
id int,
name varchar(20) 
);

create table employee(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') not null default 'male',
age int,
dep_id int
);

#插入數據
insert into department values
(200,'技術'),
(201,'人力資源'),
(202,'銷售'),
(203,'運營');

insert into employee(name,sex,age,dep_id) values
('egon','male',18,200),
('alex','female',48,201),
('wupeiqi','male',38,201),
('yuanhao','female',28,202),
('liwenzhou','male',18,200),
('jingliyang','female',18,204)
;
準備表

一、多表連接語法

#重點:外連接語法

SELECT 字段列表
    FROM 表1 INNER|LEFT|RIGHT JOIN 表2
    ON 表1.字段 = 表2.字段;

 交叉鏈接

不適用任何匹配條件。生成笛卡爾積

mysql> select * from employee,department;

 內鏈接

只鏈接匹配的行

找兩張表共有的部分,至關於利用條件從笛卡爾積結果中篩選出了正確的結果
department沒有204這個部門,於是employee表中關於204這條員工信息沒有匹配出來
mysql> select employee.id,employee.name,employee.age,employee.sex,department.name from employee inner join department on employee.dep_id=department.id; 


#上述sql等同於
mysql> select employee.id,employee.name,employee.age,employee.sex,department.name from employee,department where employee.dep_id=department.id;

重點

    1inner join:只取兩張表有對應關係的部分
    select * from emp inner join dep
        on emp.dep_id = dep.id
        ;


    2left join:在inner join的基礎上保留左表中的記錄
    select * from emp left join dep
        on emp.dep_id = dep.id
        ;

    3right join:在inner join的基礎上保留右表中的記錄
    select * from emp right join dep
        on emp.dep_id = dep.id
        ;

    4full join:在內鏈接的基礎上左右兩邊的記錄都保留(在mysql中無‘full join’)
    select * from emp left join dep on emp.dep_id = dep.id
    union
    select * from emp right join dep on emp.dep_id = dep.id
        ;

二、符合條件連接查詢

#示例1:之內鏈接的方式查詢employee和department表,而且employee表中的age字段值必須大於25,即找出年齡大於25歲的員工以及員工所在的部門
select employee.name,department.name from employee inner join department
    on employee.dep_id = department.id
    where age > 25;

#示例2:之內鏈接的方式查詢employee和department表,而且以age字段的升序方式顯示
select employee.id,employee.name,employee.age,department.name from employee,department
    where employee.dep_id = department.id
    and age > 25
    order by age asc;

 

三、子查詢

#1:子查詢是將一個查詢語句嵌套在另外一個查詢語句中。

#2:內層查詢語句的查詢結果,能夠爲外層查詢語句提供查詢條件。

#3:子查詢中能夠包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等關鍵字

#4:還能夠包含比較運算符:= 、 !=、> 、<等

 帶 in 關鍵字的子查詢

#查詢平均年齡在25歲以上的部門名
select id,name from department
    where id in 
        (select dep_id from employee group by dep_id having avg(age) > 25);

#查看技術部員工姓名
select name from employee
    where dep_id in 
        (select id from department where name='技術');

#查看不足1人的部門名(子查詢獲得的是有人的部門id)
select name from department where id not in (select distinct dep_id from employee);

帶比較運算符的子查詢

#比較運算符:=、!=、>、>=、<、<=、<>
#查詢大於全部人平均年齡的員工名與年齡
mysql> select name,age from emp where age > (select avg(age) from emp);
+---------+------+
| name | age |
+---------+------+
| alex | 48 |
| wupeiqi | 38 |
+---------+------+
2 rows in set (0.00 sec)


#查詢大於部門內平均年齡的員工名、年齡
select t1.name,t1.age from emp t1
inner join 
(select dep_id,avg(age) avg_age from emp group by dep_id) t2
on t1.dep_id = t2.dep_id
where t1.age > t2.avg_age; 

帶 exists 關鍵字的子查詢

EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。
而是返回一個真假值。True或False
當返回True時,外層查詢語句將進行查詢;當返回值爲False時,外層查詢語句不進行查詢

#department表中存在dept_id=203,Ture
mysql> select * from employee
    ->     where exists
    ->         (select id from department where id=200);

#department表中存在dept_id=205,False
mysql> select * from employee
    ->     where exists
    ->         (select id from department where id=204);
Empty set (0.00 sec)

 

5、MySQL數據備份

1. 物理備份: 直接複製數據庫文件,適用於大型數據庫環境。但不能恢復到異構系統中如Windows。

2. 邏輯備份: 備份的是建表、建庫、插入等操做所執行SQL語句,適用於中小型數據庫,效率相對較低。

3. 導出表: 將表導入到文本文件中。

一、mysqldump邏輯備份

#語法:
# mysqldump -h 服務器 -u用戶名 -p密碼 數據庫名 > 備份文件.sql

#示例:
#單庫備份
mysqldump -uroot -p123 db1 > db1.sql
mysqldump -uroot -p123 db1 table1 table2 > db1-table1-table2.sql

#多庫備份
mysqldump -uroot -p123 --databases db1 db2 mysql db3 > db1_db2_mysql_db3.sql

#備份全部庫
mysqldump -uroot -p123 --all-databases > all.sql 

二、恢復邏輯備份

#方法一:
# mysql -uroot -p123 < /backup/all.sql

#方法二:
#mysql> use db1;
#mysql> SET SQL_LOG_BIN=0;
#mysql> source /root/db1.sql

三、實現自動化備份

備份計劃:
1. 什麼時間 2:00
2. 對哪些數據庫備份
3. 備份文件放的位置

備份腳本:
[root@localhost ~]# vim /mysql_back.sql
#!/bin/bash
back_dir=/backup
back_file=`date +%F`_all.sql
user=root
pass=123

if [ ! -d /backup ];then
mkdir -p /backup
fi

# 備份並截斷日誌
mysqldump -u${user} -p${pass} --events --all-databases > ${back_dir}/${back_file}
mysql -u${user} -p${pass} -e 'flush logs'

# 只保留最近一週的備份
cd $back_dir
find . -mtime +7 -exec rm -rf {} \;

手動測試:
[root@localhost ~]# chmod a+x /mysql_back.sql 
[root@localhost ~]# chattr +i /mysql_back.sql
[root@localhost ~]# /mysql_back.sql

配置cron:
[root@localhost ~]# crontab -l
2 * * * /mysql_back.sql
View Code

 

6、索引原理與sql 邏輯查詢語句執行順序

#索引的目的在於提升查詢效率,與咱們查閱圖書所用的目錄是一個道理:先定位到章,而後定位到該章下的一個小節,而後找到頁數。類似的例子還有:查字典,查火車車次,飛機航班等

索引原理與慢查詢優化 

http://www.cnblogs.com/linhaifeng/articles/7274563.html
View Code

SQL邏輯查詢語句執行順序

http://www.cnblogs.com/linhaifeng/articles/7372774.html
View Code
相關文章
相關標籤/搜索