MySql的相關資操做 01-MySql的前戲 02-數據庫概述 03-MySql安裝和基本管理 04-基本的mysql語句 05-庫的操做 06-表的操做 07-數據類型 08-數據類型(2) 09

01-MySql的前戲

 

MySql的前戲

在學習Mysql以前,咱們先來想一下一開始作的登陸註冊案例,當時咱們把用戶的信息保存到一個文件中:css

#用戶名 |密碼
root|123321 alex|123123

上面文件內容的規則是我本身定義的,你要想用我這個程序,必須按照個人規則去執行,但凡不是這個規則,就沒有交流的餘地。html

在一開始的時候文件格式的規定是沒有規範的,後面學到模塊的時候逐漸知道了目錄規則,咱們會把文件放到db目錄下。node

相似下面目錄結構:python

 

對於上面db目錄中,是能夠存放多個文件的,而且文件中能夠有多行數據。mysql

 

那麼問你們一個問題,若是說上面那個軟件是我寫好的,在一臺服務器或者一臺機器上安裝了我寫好的軟件。redis

如今有張三和李四兩我的都安裝了我這個軟件,張三註冊了一個用戶,李四也註冊了一個用戶,那麼本身註冊的用戶應該是本身用的。那麼這兩個用戶是不共享的,算法

因此這個軟件證實我寫的不太好,它不能共享,這種相似單機的軟件是很差的。sql

而後呢,我如今將我寫的這個軟件中目錄修改一下,將db目錄移除。如今將單機程序(本身的DB)改變成也是單機程序(公用DB)。mongodb

 

那麼以前給你們介紹過,凡是交互操做,是離不開scoket的,那麼如今我這邊有個公用DB和一個scoket服務端,而後在張三和李四那邊有scoket客戶端。張三和李四此時輸入用戶名和密碼,如今我這邊scoket服務端某個目錄接收用戶輸入的用戶名和密碼,看一下該用戶名存在不存在,若是存在返回true,若是不存在返回false。也就是說重點的內容咱們把db目錄放到某臺服務器上。數據庫

那麼上面這個例子呢,其實就給你們慢慢的引出來mysql了,mysql呢其實就一個軟件,這個軟件安裝到某臺電腦上或者某臺服務器上,那麼如今只要我告訴它建立一個文件目錄或者建立文件,那麼mysql就自動幫咱們建立了,好比說咱們再在文件中添加一條數據,那麼它也幫咱們完成。

 

總結一句話:其實mysql就是用於管理咱們的文件的一個軟件。

 

那麼對於mysql這個軟件來講有兩個軟件

複製代碼
---服務器軟件
     - socket服務端
     - 本地文件操做
   - 解析指令(mysql語句) ---客戶端軟件 - socket客戶端 - 發送指令
   - 解析指令(mysql語句)
複製代碼

解釋:

對於服務器軟件中的socket服務器是一直開着,客戶端得須要鏈接,而且還有建立文件、刪除文件等等的操做

對於客戶端軟件中的scoket客戶端,咱們得須要發送指令去命令scoket服務端對文件進行操做。

 

你們應該知道ftp的項目,上傳項目和下載項目的命令是不同的。那麼對於mysql中的客戶端和服務端也會有些指令的操做,那麼在這兩個端中應該是有解析指令的過程,這個指令只有mysql這個軟件知道,這種指令就是mysql語句。

再想一想咱們寫的html、css、js.這些比如就是咱們客戶端寫好的語法,而後瀏覽器充當了服務端的角色去解析咱們的的語法,最後來渲染出來結果。

 

接下來咱們要學習這些技能:

- 安裝 服務端和客戶端
- 鏈接
- 學習SOL語句規則:命令服務端作任何的操做


  

02-數據庫概述

 

什麼是數據(Data)

複製代碼
描述事物的符號記錄稱爲數據,描述事物的符號既能夠是數字,也能夠是文字、圖片,圖像、聲音、語言等,數據由多種表現形式,它們均可以通過數字化後存入計算機

在計算機中描述一個事物,就須要抽取這一事物的典型特徵,組成一條記錄,就至關於文件裏的一行內容,如:

1 xiaomage,male,18,1999,山東,計算機系,2017,oldboy
複製代碼

 

單純的一條記錄並無任何意義,若是咱們按逗號做爲分隔,依次定義各個字段的意思,至關於定義表的標題

這樣經過表格咱們很清楚的知道了某人的詳細信息。

 

什麼是數據庫(DataBase,簡稱DB)

數據庫即存放數據的倉庫,只不過這個倉庫是在計算機存儲設備上,並且數據是按必定的格式存放的

過去人們將數據存放在文件櫃裏,如今數據量龐大,已經再也不適用

數據庫是長期存放在計算機內、有組織、可共享的數據便可。

數據庫中的數據按必定的數據模型組織、描述和儲存,具備較小的冗餘度、較高的數據獨立性和易擴展性,並可爲各類 用戶共享

 

什麼是數據庫管理系統(DataBase Management System)

在瞭解了Data與DB的概念後,如何科學地組織和存儲數據,如何高效獲取和維護數據成了關鍵

這就用到了一個系統軟件---數據庫管理系統

如MySQL、Oracle、SQLite、Access、MS SQL Server

mysql主要用於大型門戶,例如搜狗、新浪等,它主要的優點就是開放源代碼,由於開放源代碼這個數據庫是免費的,他如今是甲骨文公司的產品。
oracle主要用於銀行、鐵路、飛機場等。該數據庫功能強大,軟件費用高。也是甲骨文公司的產品。
sql server是微軟公司的產品,主要應用於大中型企業,如聯想、方正等。

數據庫服務器、數據管理系統、數據庫、表與記錄的關係(重點理解!!!)

記錄:1 xxx 324245234 22(多個字段的信息組成一條記錄,即文件中的一行內容)

表:student,scholl,class_list(即文件)

數據庫:oldboy_stu(即文件夾)

數據庫管理系統:如mysql(是一個軟件)

數據庫服務器:一臺計算機(對內存要求比較高)

 

總結:

數據庫服務器-:運行數據庫管理軟件

數據庫管理軟件:管理-數據庫

數據庫:即文件夾,用來組織文件/表

表:即文件,用來存放多行內容/多條記錄

 

03-MySql安裝和基本管理

 

本節掌握內容:

  • MySQL的介紹安裝、啓動

  • windows上製做服務
  • MySQL破解密碼

  • MySQL中統一字符編碼

 

MySQL是一個關係型數據庫管理系統,由瑞典MySQL AB 公司開發,目前屬於 Oracle 旗下公司。MySQL 最流行的關係型數據庫管理系統,在 WEB 應用方面MySQL是最好的 RDBMS (Relational Database Management System,關係數據庫管理系統) 應用軟件之一。

MySQL是一種關係數據庫管理系統,關係數據庫將數據保存在不一樣的表中,而不是將全部數據放在一個大倉庫內,這樣就增長了速度並提升了靈活性。

  • Mysql是開源的,因此你不須要支付額外的費用。

  • Mysql支持大型的數據庫。能夠處理擁有上千萬條記錄的大型數據庫。

  • MySQL使用標準的SQL數據語言形式。

  • Mysql能夠容許於多個系統上,而且支持多種語言。這些編程語言包括C、C++、Python、Java、Perl、PHP、Eiffel、Ruby和Tcl等。

  • Mysql對PHP有很好的支持,PHP是目前最流行的Web開發語言。

  • MySQL支持大型數據庫,支持5000萬條記錄的數據倉庫,32位系統表文件最大可支持4GB,64位系統支持最大的表文件爲8TB。

  • Mysql是能夠定製的,採用了GPL協議,你能夠修改源碼來開發本身的Mysql系統。

因爲其社區版的性能卓越,搭配Apache和PHP以及python 可組成良好的開發環境。

 

應用環境

與其餘的大型數據庫例如 OracleDB2SQL Server等相比,MySQL [1]  自有它的不足之處,可是這絲毫也沒有減小它受歡迎的程度。對於通常的我的使用者和中小型企業來講,MySQL提供的功能已經綽綽有餘,並且因爲 MySQL是開放源碼軟件,所以能夠大大下降整體擁有成本。

Linux做爲 操做系統Apache 或 Nginx做爲  Web 服務器,MySQL 做爲 數據庫,PHP/Perl/ Python做爲服務器端 腳本 解釋器。因爲這四個軟件都是免費或 開放源碼軟件( FLOSS),所以使用這種方式不用花一分錢(除開人工成本)就能夠創建起一個穩定、免費的 網站系統,被業界稱爲「 LAMP「或「 LNMP」組合。

mysql是什麼?

總結:mysql就是一個基於socket編寫的C/S架構的軟件

數據庫管理軟件分類

複製代碼
分兩大類:
  關係型:如sqllite,db2,oracle,access,sql server,MySQL,注意:sql語句通用
  非關係型:mongodb,redis,memcache

總結兩句話:
    關係型數據庫須要有表結構
    非關係型數據庫是key-value存儲的,沒有表結構

因此,如今咱們使用關係型數據庫管理系統(RDBMS)來存儲和管理的大數據量。所謂的關係型數據庫,是創建在關係模型基礎上的數據庫,藉助於集合代數等數學概念和方法來處理數據庫中的數據。

RDBMS即關係數據庫管理系統(Relational Database Management System)的特色:

  • 1.數據以表格的形式出現

  • 2.每行爲各類記錄名稱

  • 3.每列爲記錄名稱所對應的數據域

  • 4.許多的行和列組成一張表單

  • 5.若干的表單組成database

RDBMS 術語

在咱們開始學習MySQL 數據庫前,讓咱們先了解下RDBMS的一些術語:

  • 數據庫: 數據庫是一些關聯表的集合。.

  • 數據表: 表是數據的矩陣。在一個數據庫中的表看起來像一個簡單的電子表格。

  • 列: 一列(數據元素) 包含了相同的數據, 例如郵政編碼的數據。

  • 行:一行(=元組,或記錄)是一組相關的數據,例如一條用戶訂閱的數據。

  • 冗餘:存儲兩倍數據,冗餘下降了性能,但提升了數據的安全性。

  • 主鍵:主鍵是惟一的。一個數據表中只能包含一個主鍵。你能夠使用主鍵來查詢數據。

  • 外鍵:外鍵用於關聯兩個表。

  • 複合鍵:複合鍵(組合鍵)將多個列做爲一個索引鍵,通常用於複合索引。

  • 索引:使用索引可快速訪問數據庫表中的特定信息。索引是對數據庫表中一列或多列的值進行排序的一種結構。相似於書籍的目錄。

  • 參照完整性: 參照的完整性要求關係中不容許引用不存在的實體。與實體完整性是關係模型必須知足的完整性約束條件,目的是保證數據的一致性。

複製代碼

 

mysql的下載安裝

想要使用MySQL來存儲並保存數據,則須要作幾件事情:

  a. 安裝MySQL服務端
  b. 安裝MySQL客戶端
  b. 【客戶端】鏈接【服務端】
  c. 【客戶端】發送命令給【服務端MySQL】服務的接受命令並執行相應操做(增刪改查等)

下載地址:

 

window版本

一、官網去下載

 

二、針對操做系統的不一樣下載不一樣的版本

 

 

3.解壓

若是想要讓MySQL安裝在指定目錄,那麼就將解壓後的文件夾移動到指定目錄,如:C:\mysql-5.6.40-winx64

4.添加環境變量 

5.初始化

1
mysqld  - - initialize - insecure

 

 6.啓動mysql服務

mysqld #啓動MySQL服務

 

7.啓動mysql客戶端並鏈接mysql服務端(新開一個cmd窗口)

mysql -u root -p # 鏈接MySQL服務器

 

上一步解決了一些問題,但不夠完全,由於在執行【mysqd】啓動MySQL服務器時,當前終端會被hang住,那麼作一下設置便可解決此問題,即將MySQL服務製做成windows服務

複製代碼
注意:--install前,必須用mysql啓動命令的絕對路徑
# 製做MySQL的Windows服務,在終端執行此命令:
"c:\mysql-5.6.40-winx64\bin\mysqld" --install

# 移除MySQL的Windows服務,在終端執行此命令:
"c:\mysql-5.6.40-winx64\bin\mysqld" --remove


註冊成服務以後,之後再啓動和關閉MySQL服務時,僅需執行以下命令:
# 啓動MySQL服務
net start mysql

# 關閉MySQL服務
net stop mysql
複製代碼

 

windows下登陸設置密碼

 

打開終端,輸入mysql

輸入mysql提供的函數:select user(); # 查看當前登陸的帳號

當前登陸的默認帳號爲ODBC@localhost

 

 

若是想切到root帳號登陸

執行命令:

mysql -uroot -p

再查看當前用戶:

select user();

管理員爲root(擁有最高權限,管理員帳號),密碼爲空,以無密碼的方式登陸了管理員帳號,是很是危險的一件事情,因此要爲管理員帳號設置密碼

設置管理員root帳號密碼爲123

C:\Users\mjj>mysqladmin -uroot -p password "123"  #設置初始密碼 因爲原密碼爲空,所以-p能夠不用 Mysql版本的不一樣,可能執行這句指令不起做用,請使用update mysql.user set authentication_string =password('') where User='root'; 

ps:⚠️不用管它。翻譯爲:在命令行界面使用密碼不安全,暴露在終端當中。

 

而後再登陸帳號,不輸入密碼則會出現以下結果:

 再次執行以下操做:

 

再查看一下當前登陸的帳號:

 

若是想將原始密碼123,設置新密碼爲456

C:\Users\mjj>mysqladmin -uroot -p"123" password "456"  #修改mysql密碼,由於已經有密碼了,因此必須輸入原密碼才能設置新密碼

 依次執行以下操做:

mysql -uroot -p456

select user();

 

密碼忘記——破解密碼

 

跳過受權方式,直接登陸!!

0.以管理員身份打開cmd

 

2.停掉mysql服務端

C:\WINDOWS\system32>net stop mysql
MySQL 服務正在中止.
MySQL 服務已成功中止。

3.執行以下命令跳過受權表

#跳過受權表
C:\WINDOWS\system32>mysqld --skip-grant-tables
2018-06-09 17:12:38 0 [Warning] Insecure configuration for --secure-file-priv: Current value does not restrict location of generated files. Consider setting it to a valid, non-empty path.
2018-06-09 17:12:38 0 [Note] mysqld (mysqld 5.6.40) starting as process 6052 ...4.

 4.再次查看

5. 如今能夠任意的更改密碼,執行以下命令

 update mysql.user set authentication_string =password('') where User='root'; 

 

6.刷新權限,執行命令

flush privileges;

7.退出mysql。執行命令:exit,

 

8.讓用戶去加載權限,以管理員身份進入cmd,查看當前mysql進程

1
tasklist |findstr mysql   #查看當前mysql的進程

 

9.殺死當前的進程,執行以下命令

taskkill /F /PID 6052  # 殺死當前的進程pid

10.再次執行以下操做,還原

 

統一字符編碼

進入mysql客戶端,執行\s

 

 

爲了統一字符編碼,請執行以下操做:

(1)my.ini文件是mysql的配置文件,

在C:\mysql-5.6.40-winx64文件下建立my.ini文件

(2)將以下代碼拷貝保存。

複製代碼

[mysqld]
# 設置mysql的安裝目錄 **後面的路徑必定是安裝sql的目錄(本身電腦的)**
basedir=C:\mysql-5.7.22-winx64\mysql-5.7.22-winx64
# 設置mysql數據庫的數據的存放目錄,必須是data
datadir=C:\mysql-5.7.22-winx64\mysql-5.7.22-winx64\data
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

# mysql端口
port=3306
# 字符集
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8

複製代碼

 

(3)以管理員身份重啓服務,執行以下命令 

複製代碼
C:\Windows\system32>net stop MySQL
MySQL 服務正在中止..
MySQL 服務已成功中止。

C:\Windows\system32>net start MySQL
MySQL 服務正在啓動 .
MySQL 服務已經啓動成功。
複製代碼

(4)在cmd中輸入mysql進入mysql環境,執行\s,顯示以下信息,表示成功

 

04-基本的mysql語句

 

本節課先對mysql的基本語法初體驗。

操做文件夾(庫)

create database db1 charset utf8;

# 查看當前建立的數據庫
show create database db1;
# 查看全部的數據庫
show databases;

alter database db1 charset gbk;

drop database db1;

 

 

 

操做文件(表)

use db1; #切換文件夾

select database(); #查看當前所在文件夾

create table t1(id int,name char);

查 

複製代碼
#查看當前的這張t1表
show create table t1;

# 查看全部的表
show tables;

# 查看錶的詳細信息
desc t1;
複製代碼

# modify修改的意思
alter table t1 modify name char(6);
# 改變name爲大寫的NAME
alter table t1 change name NAMA char(7);

# 刪除表
drop table t1;

 

 

操做文件內容(記錄)

 增

# 插入一條數據,規定id,name數據leilei
insert t1(id,name) values(1,"mjj01"),(2,"mjj02"),(3,"mjj03");

 查

select id from db1.t1;
select id,name from db1.t1;
select * from db1.t1; 

update db1.t1 set name='zhangsan';
update db1.t1 set name='alex' where id=2;

 刪

delete from t1;
delete from t1 where id=2;

 

05-庫的操做

 

本節重點:

  • 掌握庫的增刪改查

 

1、系統數據庫

執行以下命令,查看系統庫

show databases;

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

2、建立數據庫

一、求救語法:

help create database;

二、建立數據庫語法

CREATE DATABASE 數據庫名 charset utf8;

三、數據庫命名規則:

複製代碼
能夠由字母、數字、下劃線、@、#、$
區分大小寫
惟一性
不能使用關鍵字如 create select
不能單獨使用數字
最長128位
# 基本上跟python或者js的命名規則同樣
複製代碼

3、數據庫相關操做

複製代碼
#查看數據庫
show databases;
#查看當前庫
show create database db1;
#查看所在的庫
select database();

#選擇數據庫
use 數據庫名

#刪除數據庫
DROP DATABASE 數據庫名;
# 修改數據庫
alter database db1 charset utf8;
複製代碼

 

4、瞭解內容

SQL語言主要用於存取數據、查詢數據、更新數據和管理關係數據庫系統,SQL語言由IBM開發。SQL語言分爲3種類型:
一、DDL語句    數據庫定義語言: 數據庫、表、視圖、索引、存儲過程,例如CREATE DROP ALTER

二、DML語句    數據庫操縱語言: 插入數據INSERT、刪除數據DELETE、更新數據UPDATE、查詢數據SELECT

三、DCL語句    數據庫控制語言: 例如控制用戶的訪問權限GRANT、REVOKE
複製代碼
SQL語言主要用於存取數據、查詢數據、更新數據和管理關係數據庫系統,SQL語言由IBM開發。SQL語言分爲3種類型:
一、DDL語句    數據庫定義語言: 數據庫、表、視圖、索引、存儲過程,例如CREATE DROP ALTER

二、DML語句    數據庫操縱語言: 插入數據INSERT、刪除數據DELETE、更新數據UPDATE、查詢數據SELECT

三、DCL語句    數據庫控制語言: 例如控制用戶的訪問權限GRANT、REVOKE

 

06-表的操做

 

本節掌握

  • 存儲引擎介紹(瞭解)
  • 表的增刪改查

1、存儲引擎(瞭解)

前幾節咱們知道mysql中創建的庫===》文件夾,庫中的表====》文件

現實生活中咱們用來存儲數據的文件有不一樣的類型,每種文件類型對應各自不一樣的處理機制:好比處理文本用txt類型,處理表格用excel,處理圖片用png等

數據庫中的表也應該有不一樣的類型,表的類型不一樣,會對應mysql不一樣的存取機制,表類型又稱爲存儲引擎。

ps: 存儲引擎說白了就是如何存儲數據、如何爲存儲的數據創建索引和如何更新、查詢數據等技術的實現方法。由於在關係數據庫中數據的存儲是以表的形式存儲的,因此存儲引擎也能夠稱爲表類型(即存儲和操做此表的類型)

在Oracle 和SQL Server等數據庫中只有一種存儲引擎,全部數據存儲管理機制都是同樣的。而MySql
數據庫提供了多種存儲引擎。用戶能夠根據不一樣的需求爲數據表選擇不一樣的存儲引擎,用戶也能夠根據
本身的須要編寫本身的存儲引擎

SQL 解析器、SQL 優化器、緩衝池、存儲引擎等組件在每一個數據庫中都存在,但不是每 個數據庫都有這麼多存儲引擎。MySQL 的插件式存儲引擎可讓存儲引擎層的開發人員設 計他們但願的存儲層,例如,有的應用須要知足事務的要求,有的應用則不須要對事務有這 麼強的要求 ;有的但願數據能持久存儲,有的只但願放在內存中,臨時並快速地提供對數據 的查詢。

 

2、mysql支持的存儲引擎

mysql> show engines\G;# 查看全部支持的引擎
mysql> show variables like 'storage_engine%'; # 查看正在使用的存儲引擎

 

一、InnoDB 存儲引擎

支持事務,其設計目標主要面向聯機事務處理(OLTP)的應用。其

特色是行鎖設計、支持外鍵,並支持相似 Oracle 的非鎖定讀,即默認讀取操做不會產生鎖。 從 MySQL 5.5.8 版本開始是默認的存儲引擎。

InnoDB 存儲引擎將數據放在一個邏輯的表空間中,這個表空間就像黑盒同樣由 InnoDB 存儲引擎自身來管理。從 MySQL 4.1(包括 4.1)版本開始,能夠將每一個 InnoDB 存儲引擎的 表單獨存放到一個獨立的 ibd 文件中。此外,InnoDB 存儲引擎支持將裸設備(row disk)用 於創建其表空間。

InnoDB 經過使用多版本併發控制(MVCC)來得到高併發性,而且實現了 SQL 標準 的 4 種隔離級別,默認爲 REPEATABLE 級別,同時使用一種稱爲 netx-key locking 的策略來 避免幻讀(phantom)現象的產生。除此以外,InnoDB 存儲引擎還提供了插入緩衝(insert buffer)、二次寫(double write)、自適應哈希索引(adaptive hash index)、預讀(read ahead) 等高性能和高可用的功能。

對於表中數據的存儲,InnoDB 存儲引擎採用了彙集(clustered)的方式,每張表都是按 主鍵的順序進行存儲的,若是沒有顯式地在表定義時指定主鍵,InnoDB 存儲引擎會爲每一 行生成一個 6 字節的 ROWID,並以此做爲主鍵。

InnoDB 存儲引擎是 MySQL 數據庫最爲經常使用的一種引擎,Facebook、Google、Yahoo 等 公司的成功應用已經證實了 InnoDB 存儲引擎具有高可用性、高性能以及高可擴展性。對其 底層實現的掌握和理解也須要時間和技術的積累。若是想深刻了解 InnoDB 存儲引擎的工做 原理、實現和應用,能夠參考《MySQL 技術內幕:InnoDB 存儲引擎》一書。

二、MyISAM 存儲引擎

不支持事務、表鎖設計、支持全文索引,主要面向一些 OLAP 數 據庫應用,在 MySQL 5.5.8 版本以前是默認的存儲引擎(除 Windows 版本外)。數據庫系統 與文件系統一個很大的不一樣在於對事務的支持,MyISAM 存儲引擎是不支持事務的。究其根 本,這也並不難理解。用戶在全部的應用中是否都須要事務呢?在數據倉庫中,若是沒有 ETL 這些操做,只是簡單地經過報表查詢還須要事務的支持嗎?此外,MyISAM 存儲引擎的 另外一個不同凡響的地方是,它的緩衝池只緩存(cache)索引文件,而不緩存數據文件,這與 大多數的數據庫都不相同。

三、NDB 存儲引擎

年,MySQL AB 公司從 Sony Ericsson 公司收購了 NDB 存儲引擎。 NDB 存儲引擎是一個集羣存儲引擎,相似於 Oracle 的 RAC 集羣,不過與 Oracle RAC 的 share everything 結構不一樣的是,其結構是 share nothing 的集羣架構,所以能提供更高級別的 高可用性。NDB 存儲引擎的特色是數據所有放在內存中(從 5.1 版本開始,能夠將非索引數 據放在磁盤上),所以主鍵查找(primary key lookups)的速度極快,而且可以在線添加 NDB 數據存儲節點(data node)以便線性地提升數據庫性能。因而可知,NDB 存儲引擎是高可用、 高性能、高可擴展性的數據庫集羣系統,其面向的也是 OLTP 的數據庫應用類型。

四、Memory 存儲引擎

正如其名,Memory 存儲引擎中的數據都存放在內存中,數據庫重 啓或發生崩潰,表中的數據都將消失。它很是適合於存儲 OLTP 數據庫應用中臨時數據的臨時表,也能夠做爲 OLAP 數據庫應用中數據倉庫的維度表。Memory 存儲引擎默認使用哈希 索引,而不是一般熟悉的 B+ 樹索引。

五、Infobright 存儲引擎

第三方的存儲引擎。其特色是存儲是按照列而非行的,所以很是 適合 OLAP 的數據庫應用。其官方網站是 http://www.infobright.org/,上面有很多成功的數據 倉庫案例可供分析。

六、NTSE 存儲引擎

網易公司開發的面向其內部使用的存儲引擎。目前的版本不支持事務, 但提供壓縮、行級緩存等特性,不久的未來會實現面向內存的事務支持。

七、BLACKHOLE

黑洞存儲引擎,能夠應用於主備複製中的分發主庫。

MySQL 數據庫還有不少其餘存儲引擎,上述只是列舉了最爲經常使用的一些引擎。若是 你喜歡,徹底能夠編寫專屬於本身的引擎,這就是開源賦予咱們的能力,也是開源的魅 力所在。

 

指定表類型/存儲引擎

create table t1(id int)engine=innodb;# 默認不寫就是innodb

 

小練習:

建立四張表,分別使用innodb,myisam,memory,blackhole存儲引擎,進行插入數據測試 

create table t1(id int)engine=innodb;
create table t2(id int)engine=myisam;
create table t3(id int)engine=memory;
create table t4(id int)engine=blackhole;

查看data文件下db1數據庫中的文件:

複製代碼
#.frm是存儲數據表的框架結構

# .ibd是mysql數據文件 

#.MYD是MyISAM表的數據文件的擴展名

#.MYI是MyISAM表的索引的擴展名

#發現後兩種存儲引擎只有表結構,無數據

#memory,在重啓mysql或者重啓機器後,表內數據清空
#blackhole,往表內插入任何數據,都至關於丟入黑洞,表內永遠不存記錄
複製代碼

 

3、表介紹

表至關於文件,表中的一條記錄就至關於文件的一行內容,不一樣的是,表中的一條記錄有對應的標題,稱爲表的字段

id,name,sex,age,birth稱爲字段,其他的,一行內容稱爲一條記錄

 

4、建立表

語法:

複製代碼
create table 表名(
字段名1 類型[(寬度) 約束條件],
字段名2 類型[(寬度) 約束條件],
字段名3 類型[(寬度) 約束條件]
);

#注意:
1. 在同一張表中,字段名是不能相同
2. 寬度和約束條件可選
3. 字段名和類型是必須的
複製代碼


1.建立數據庫

create database db2 charset utf8;


2.使用數據庫

use db2;


3.建立a1表

create table a1(
  id int,
  name varchar(50),
  age int(3)
);

4.插入表的記錄

insert into a1 values
(1,'mjj',18),
(2,'wusir',28);

ps:以;做爲mysql的結束語

5.查詢表的數據和結構

(1)查詢a1表中的存儲數據

複製代碼

mysql> select * from a1;
+------+-------+------+
| id | name | age |
+------+-------+------+
| 1 | mjj   | 18  |
| 2 | wusir | 28  |
+------+-------+------+
2 rows in set (0.02 sec)

mysql>

複製代碼

 

(2)查看a1表的結構

複製代碼
mysql> desc a1;
+-------+-------------+------+-----+---------+-------+
| Field     | Type           | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id        | int(11)        | YES  |      | NULL    |       |
| name      | varchar(50)    | YES  |      | NULL    |       |
| age       | int(3)         | YES  |      | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.16 sec)
複製代碼

(3)查看錶的詳細結構

複製代碼
mysql> show create table a1\G;
*************************** 1. row ***************************
       Table: a1
Create Table: CREATE TABLE `a1` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(50) DEFAULT NULL,
  `age` int(3) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
複製代碼

6.複製表

(1)新建立一個數據庫db3

mysql> create database db3 charset utf8;
Query OK, 1 row affected (0.00 sec)

(2)使用db3

mysql> use db3;
Database changed
複製代碼
#這是上個建立的db2數據庫中的a1表
mysql> select * from db2.a1;
+------+-------+------+
| id   | name  | age  |
+------+-------+------+
|    1 | mjj   |   18 |
|    2 | wusir |   28 |
+------+-------+------+
複製代碼

(3)複製db2.a1的表結構和記錄

# 這就是複製表的操做(既複製了表結構,又複製了記錄)
mysql> create table b1 select * from db2.a1;
Query OK, 2 rows affected (0.03 sec)

(4)查看db3.b1中的數據和表結構

複製代碼
#再去查看db3文件夾下的b1表發現 跟db2文件下的a1表數據同樣
mysql> select * from db3.b1;
+------+-------+------+
| id   | name  | age  |
+------+-------+------+
|    1 | mjj   |   18 |
|    2 | wusir |   28 |
+------+-------+------+
2 rows in set (0.00 sec)
複製代碼

 

ps1:若是隻要表結構,不要記錄

#在db2數據庫下新建立一個b2表,給一個where條件,條件要求不成立,條件爲false,只拷貝表結構
mysql> create table b2 select * from db2.a1 where 1>5;
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

查看錶結構:

複製代碼
# 查看錶結構
mysql> desc b2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(50) | YES  |     | NULL    |       |
| age   | int(3)      | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.02 sec)

#查看錶結構中的數據,發現是空數據
mysql> select * from b2;
Empty set (0.00 sec)
複製代碼

 

ps2:還有一種作法,使用like(只拷貝表結構,不拷貝記錄)

複製代碼
mysql> create table b3 like db2.a1;
Query OK, 0 rows affected (0.01 sec)

mysql> desc b3;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(50) | YES  |     | NULL    |       |
| age   | int(3)      | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.02 sec)

mysql> select * from db3.b3;
Empty set (0.00 sec)
複製代碼

 

7.刪除表:

drop table 表名;

07-數據類型

 

介紹

存儲引擎決定了表的類型,而表內存放的數據也要有不一樣的類型,每種數據類型都有本身的寬度,但寬度是可選的

詳細參考連接:http://www.runoob.com/mysql/mysql-data-types.html

mysql經常使用數據類型歸納:

複製代碼
#1. 數字:
    整型:tinyint  int  bigint
    小數:
        float :在位數比較短的狀況下不精準
        double :在位數比較長的狀況下不精準
            0.000001230123123123
            存成:0.000001230000

        decimal:(若是用小數,則用推薦使用decimal)
            精準
            內部原理是以字符串形式去存

#2. 字符串:
    char(10):簡單粗暴,浪費空間,存取速度快
            root存成root000000
    varchar:精準,節省空間,存取速度慢

    sql優化:建立表時,定長的類型往前放,變長的日後放
                    好比性別           好比地址或描述信息

    >255個字符,超了就把文件路徑存放到數據庫中。
            好比圖片,視頻等找一個文件服務器,數據庫中只存路徑或url。


#3. 時間類型:
    最經常使用:datetime


#4. 枚舉類型與集合類型
   enum 和set
複製代碼

 

1、數值類型

整數類型:TINYINT SMALLINT MEDIUMINT INT BIGINT

做用:存儲年齡,等級,id,各類號碼等

複製代碼
========================================
        tinyint[(m)] [unsigned] [zerofill]

            小整數,數據類型用於保存一些範圍的整數數值範圍:
            有符號:
                -128 ~ 127
            無符號:
                0 ~ 255

            PS: MySQL中無布爾值,使用tinyint(1)構造。



========================================
        int[(m)][unsigned][zerofill]

            整數,數據類型用於保存一些範圍的整數數值範圍:
            有符號:
                    -2147483648 ~ 2147483647
            無符號:
                    0 ~ 4294967295



========================================
        bigint[(m)][unsigned][zerofill]
            大整數,數據類型用於保存一些範圍的整數數值範圍:
            有符號:
                    -9223372036854775808 ~ 9223372036854775807
            無符號:
                    0  ~  18446744073709551615
複製代碼

 

驗證1:有符號和無符號tinyint

複製代碼
============有符號tinyint==============
# 建立數據庫db4
create database db4 charset utf8;

# 切換到當前db4數據庫
mysql> use db4;

# 建立t1 規定x字段爲tinyint數據類型(默認是有符號的)
mysql> create table t1(x tinyint);

# 驗證,插入-1這個數
mysql>   insert into t1 values(-1);

# 查詢 表記錄,查詢成功(證實默認是有符號類型)
mysql> select * from t1;
+------+
| x    |
+------+
| -1 |
+------+

#執行以下操做,會發現報錯。由於有符號範圍在(-128,127)
mysql>   insert into t1 values(-129),(128);
ERROR 1264 (22003): Out of range value for column 'x' at row 1


============無符號tinyint==============
# 建立表時定義記錄的字符爲無符號類型(0,255) ,使用unsigned
mysql> create table t2(x tinyint unsigned);

# 報錯,超出範圍
mysql>   insert into t2 values(-129);
ERROR 1264 (22003): Out of range value for column 'x' at row 1

# 插入成功
mysql>   insert into t2 values(255);
Query OK, 1 row affected (0.00 sec)
複製代碼

 

驗證2:int類型後面的存儲是顯示寬度,而不是存儲寬度

複製代碼
mysql> create table t3(id int(1) unsigned);

#插入255555記錄也是能夠的
mysql> insert into t3 values(255555);

mysql> select * from t3;
+--------+
| id     |
+--------+
| 255555 |
+--------+
ps:以上操做還不可以驗證,再來一張表驗證用zerofill 用0填充

# zerofill 用0填充
mysql> create table t4(id int(5) unsigned zerofill);


mysql> insert into t4 value(1);
Query OK, 1 row affected (0.00 sec)

#插入的記錄是1,可是顯示的寬度是00001
mysql> select * from t4;
+-------+
| id    |
+-------+
| 00001 |
+-------+
1 row in set (0.00 sec)
複製代碼

 

注意:爲該類型指定寬度時,僅僅只是指定查詢結果的顯示寬度,與存儲範圍無關,存儲範圍以下

其實咱們徹底不必爲整數類型指定顯示寬度,使用默認的就能夠了

默認的顯示寬度,都是在最大值的基礎上加1

int的存儲寬度是4個Bytes,即32個bit,即2**32

無符號最大值爲:4294967296-1

有符號最大值:2147483648-1

有符號和無符號的最大數字須要的顯示寬度均爲10,而針對有符號的最小值則須要11位才能顯示徹底,因此int類型默認的顯示寬度爲11是很是合理的

最後:整形類型,其實沒有必要指定顯示寬度,使用默認的就ok

 

2、浮點型

定點數類型: DEC等同於DECIMAL

浮點類型:FLOAT DOUBLE

做用:存儲薪資、身高、體重、體質參數等

語法:

複製代碼
-------------------------FLOAT-------------------
FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
#參數解釋:單精度浮點數(非準確小數值),M是全長,D是小數點後個數。M最大值爲255,D最大值爲30

#有符號:
           -3.402823466E+38 to -1.175494351E-38,
           1.175494351E-38 to 3.402823466E+38

#無符號:
           1.175494351E-38 to 3.402823466E+38
#精確度: 
           **** 隨着小數的增多,精度變得不許確 ****


 -------------------------DOUBLE-----------------------
DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]

#參數解釋: 雙精度浮點數(非準確小數值),M是全長,D是小數點後個數。M最大值爲255,D最大值爲30

#有符號:
           -1.7976931348623157E+308 to -2.2250738585072014E-308
           2.2250738585072014E-308 to 1.7976931348623157E+308

#無符號:
           2.2250738585072014E-308 to 1.7976931348623157E+308

#精確度:
           ****隨着小數的增多,精度比float要高,但也會變得不許確 ****

======================================
--------------------DECIMAL------------------------
decimal[(m[,d])] [unsigned] [zerofill]

#參數解釋:準確的小數值,M是整數部分總個數(負號不算),D是小數點後個數。 M最大值爲65,D最大值爲30。


#精確度:
           **** 隨着小數的增多,精度始終準確 ****
           對於精確數值計算時須要用此類型
           decaimal可以存儲精確值的緣由在於其內部按照字符串存儲。
複製代碼

驗證三種類型建表:

複製代碼
#1驗證FLOAT類型建表:
mysql> create table t5(x float(256,31));
ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30.
mysql> create table t5(x float(256,30));
ERROR 1439 (42000): Display width out of range for column 'x' (max = 255)
mysql> create table t5(x float(255,30)); #建表成功
Query OK, 0 rows affected (0.03 sec)

#2驗證DOUBLE類型建表:
mysql> create table t6(x double(255,30)); #建表成功
Query OK, 0 rows affected (0.03 sec)

#3驗證deimal類型建表:
mysql> create table t7(x decimal(66,31));
ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30.
mysql> create table t7(x decimal(66,30));
ERROR 1426 (42000): Too big precision 66 specified for column 'x'. Maximum is 65.
mysql> create table t7(x decimal(65,30)); #建表成功
Query OK, 0 rows affected (0.00 sec)
複製代碼

驗證三種類型的精度:

複製代碼
# 分別對三張表插入相應的記錄
mysql> insert into t5 values(1.1111111111111111111111111111111);#小數點後31個1
Query OK, 1 row affected (0.01 sec)

mysql> insert into t6 values(1.1111111111111111111111111111111);
Query OK, 1 row affected (0.01 sec)

mysql> insert into t7 values(1.1111111111111111111111111111111);
Query OK, 1 row affected, 1 warning (0.00 sec)

# 查詢結果
mysql> select * from t5; #隨着小數的增多,精度開始不許確
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111164093017600000000000000 |
+----------------------------------+
1 row in set (0.00 sec)

mysql> select * from t6; #精度比float要準確點,但隨着小數的增多,一樣變得不許確
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111111111111200000000000000 |
+----------------------------------+
1 row in set (0.00 sec)

mysql> select * from t7; #精度始終準確,d爲30,因而只留了30位小數
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111111111111111111111111111 |
+----------------------------------+
1 row in set (0.00 sec)
複製代碼

 

3、日期類型

DATE TIME DATETIME TIMESTAMP YEAR
做用:存儲用戶註冊時間,文章發佈時間,員工入職時間,出生時間,過時時間等

複製代碼
語法:
        YEAR
            YYYY(1901/2155)

        DATE
            YYYY-MM-DD(1000-01-01/9999-12-31)

        TIME
            HH:MM:SS('-838:59:59'/'838:59:59')

        DATETIME

            YYYY-MM-DD HH:MM:SS(1000-01-01 00:00:00/9999-12-31 23:59:59    Y)

        TIMESTAMP

            YYYYMMDD HHMMSS(1970-01-01 00:00:00/2037 年某時)
複製代碼

驗證:

一、year

 

複製代碼
mysql> create table t8(born_year year);#不管year指定何種寬度,最後都默認是year(4)
Query OK, 0 rows affected (0.03 sec)
#插入失敗,超出範圍(1901/2155) mysql> insert into t8 values -> (1900), -> (1901), -> (2155), -> (2156); ERROR 1264 (22003): Out of range value for column 'born_year' at row 1

mysql> select * from t8; Empty set (0.01 sec) mysql> insert into t8 values -> (1905), -> (2018); Query OK, 2 rows affected (0.00 sec) #插入記錄成功 Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from t8; +-----------+ | born_year | +-----------+ | 1905 | | 2018 | +-----------+ 2 rows in set (0.00 sec)
複製代碼

 

 

二、date、year、datetime

複製代碼
#建立t9表
mysql> create table t9(d date,t time,dt datetime);
Query OK, 0 rows affected (0.06 sec)

#查看錶的結構
mysql> desc t9;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| d     | date     | YES  |     | NULL    |       |
| t     | time     | YES  |     | NULL    |       |
| dt    | datetime | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.14 sec)

# 調用mysql自帶的now()函數,獲取當前類型指定的時間 以下結構 mysql> insert into t9 values(now(),now(),now()); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> select * from t9; +------------+----------+---------------------+ | d | t | dt | +------------+----------+---------------------+ | 2018-06-09 | 09:35:20 | 2018-06-09 09:35:20 | +------------+----------+---------------------+ 1 row in set (0.00 sec)
複製代碼

 

三、timestamp(瞭解便可)

 

複製代碼
mysql>  create table t10(time timestamp);
Query OK, 0 rows affected (0.06 sec)

mysql>  insert into t10 values();
Query OK, 1 row affected (0.00 sec)

mysql>  insert into t10 values(null);
Query OK, 1 row affected (0.00 sec)

mysql>  select * from t10;
+------+
| time |
+------+
| NULL |
| NULL |
+------+

mysql> insert into t10 values(now());
Query OK, 1 row affected (0.01 sec)

mysql> select * from t10;
+---------------------+
| time                |
+---------------------+
| 2018-06-09 09:44:48 |
+---------------------+
1 row in set (0.01 sec)
複製代碼

 

 

 

datetime與timestamp的區別

 

複製代碼
在實際應用的不少場景中,MySQL的這兩種日期類型都可以知足咱們的須要,存儲精度都爲秒,但在某些狀況下,會展示出他們各自的優劣。
下面就來總結一下兩種日期類型的區別。

1.DATETIME的日期範圍是1001——9999年,TIMESTAMP的時間範圍是1970——2038年。

2.DATETIME存儲時間與時區無關,TIMESTAMP存儲時間與時區有關,顯示的值也依賴於時區。在mysql服務器,
操做系統以及客戶端鏈接都有時區的設置。

3.DATETIME使用8字節的存儲空間,TIMESTAMP的存儲空間爲4字節。所以,TIMESTAMP比DATETIME的空間利用率更高。

4.DATETIME的默認值爲null;TIMESTAMP的字段默認不爲空(not null),默認值爲當前時間(CURRENT_TIMESTAMP),
若是不作特殊處理,而且update語句中沒有指定該列的更新值,則默認更新爲當前時間。
複製代碼

 

 

注意事項

 

複製代碼
============注意啦,注意啦,注意啦===========
#1. 單獨插入時間時,須要以字符串的形式,按照對應的格式插入
#2. 插入年份時,儘可能使用4位值
#3. 插入兩位年份時,<=69,以20開頭,好比50,  結果2050      
                >=70,以19開頭,好比71,結果1971
 create table t12(y year);
 insert into t12 values  (50),(71);
 select * from t12;
+------+
| y    |
+------+
| 2050 |
| 1971 |
+------+
複製代碼

 

 

綜合練習:

建立一張學生表(student),要求有id,姓名,出生年份,出生的年月日,進班的時間,以及來老男孩學習的如今具體時間。

 

複製代碼
mysql> create table student(
    -> id int,
    -> name varchar(20),
    -> born_year year,
    -> birth date,
    -> class_time time,
    -> reg_time datetime
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> insert into student values
    ->   (1,'alex',"1995","1995-11-11","11:11:11","2017-11-11 11:11:11"),
    ->   (2,'egon',"1997","1997-12-12","12:12:12","2017-12-12 12:12:12"),
    ->   (3,'wsb',"1998","1998-01-01","13:13:13","2017-01-01 13:13:13");
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql>   select * from student;
+------+------+-----------+------------+------------+---------------------+
| id   | name | born_year | birth      | class_time | reg_time            |
+------+------+-----------+------------+------------+---------------------+
|    1 | alex |      1995 | 1995-11-11 | 11:11:11   | 2017-11-11 11:11:11 |
|    2 | egon |      1997 | 1997-12-12 | 12:12:12   | 2017-12-12 12:12:12 |
|    3 | wsb  |      1998 | 1998-01-01 | 13:13:13   | 2017-01-01 13:13:13 |
+------+------+-----------+------------+------------+---------------------+
3 rows in set (0.00 sec)
複製代碼

08-數據類型(2)

 

本節重點

  • 掌握char類型和varchar類型
  • 掌握枚舉類型和集合類型

 

 

字符類型

複製代碼
#官網:https://dev.mysql.com/doc/refman/5.7/en/char.html
#注意:char和varchar括號內的參數指的都是字符的長度

#char類型:定長,簡單粗暴,浪費空間,存取速度快
    字符長度範圍:0-255(一箇中文是一個字符,是utf8編碼的3個字節)
    存儲:
        存儲char類型的值時,會往右填充空格來知足長度
        例如:指定長度爲10,存>10個字符則報錯,存<10個字符則用空格填充直到湊夠10個字符存儲

    檢索:
        在檢索或者說查詢時,查出的結果會自動刪除尾部的空格,除非咱們打開pad_char_to_full_length SQL模式(設置SQL模式:SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';
      查詢sql的默認模式:select @@sql_mode;) #varchar類型:變長,精準,節省空間,存取速度慢 字符長度範圍:0-65535(若是大於21845會提示用其餘類型 。mysql行最大限制爲65535字節,字符編碼爲utf-8:https://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html) 存儲: varchar類型存儲數據的真實內容,不會用空格填充,若是'ab ',尾部的空格也會被存起來 強調:varchar類型會在真實數據前加1-2Bytes的前綴,該前綴用來表示真實數據的bytes字節數(1-2Bytes最大表示65535個數字,正好符合mysql對row的最大字節限制,即已經足夠使用) 若是真實的數據<255bytes則須要1Bytes的前綴(1Bytes=8bit 2**8最大表示的數字爲255) 若是真實的數據>255bytes則須要2Bytes的前綴(2Bytes=16bit 2**16最大表示的數字爲65535) 檢索: 尾部有空格會保存下來,在檢索或者說查詢時,也會正常顯示包含空格在內的內容
複製代碼

官網解釋以下:

驗證:

驗證以前瞭解兩個函數:

length():查看字節數
char_length():查看字符數

 

1.char填充空格來知足固定長度,可是在查詢時卻會很不要臉地刪除尾部的空格(裝做本身好像沒有浪費過空間同樣),而後修改sql_mode讓其現出原形。

複製代碼
# 建立t1表,分別指明字段x爲char類型,字段y爲varchar類型
mysql> create table t1(x char(5),y varchar(4));
Query OK, 0 rows affected (0.16 sec)

# char存放的是5個字符,而varchar存4個字符
mysql>  insert into t1 values('你瞅啥 ','你瞅啥 ');
Query OK, 1 row affected (0.01 sec)

# 在檢索時char很不要臉地將本身浪費的2個字符給刪掉了,裝的好像本身沒浪費過空間同樣,而varchar很老實,存了多少,就顯示多少
mysql> select x,char_length(x),y,char_length(y) from t1;
+-----------+----------------+------------+----------------+
| x         | char_length(x) | y          | char_length(y) |
+-----------+----------------+------------+----------------+
| 你瞅啥    |              3 | 你瞅啥     |              4 |
+-----------+----------------+------------+----------------+
1 row in set (0.02 sec)

 #略施小計,讓char現原形
 mysql> SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';
Query OK, 0 rows affected (0.00 sec)

#查看當前mysql的mode模式
mysql> select @@sql_mode;
+-------------------------+
| @@sql_mode              |
+-------------------------+
| PAD_CHAR_TO_FULL_LENGTH |
+-------------------------+
1 row in set (0.00 sec)

#原形畢露了吧。。。。
mysql> select x,char_length(x) y,char_length(y) from t1;
+-------------+------+----------------+
| x           | y    | char_length(y) |
+-------------+------+----------------+
| 你瞅啥      |    5 |              4 |
+-------------+------+----------------+
1 row in set (0.00 sec)

# 查看字節數
#char類型:3箇中文字符+2個空格=11Bytes
#varchar類型:3箇中文字符+1個空格=10Bytes
mysql> select x,length(x),y,length(y) from t1;
+-------------+-----------+------------+-----------+
| x           | length(x) | y          | length(y) |
+-------------+-----------+------------+-----------+
| 你瞅啥      |        11 | 你瞅啥     |        10 |
+-------------+-----------+------------+-----------+
1 row in set (0.02 sec)
複製代碼

總結:

複製代碼
#經常使用字符串系列:char與varchar
注:雖然varchar使用起來較爲靈活,可是從整個系統的性能角度來講,char數據類型的處理速度更快,有時甚至能夠超出varchar處理速度的50%。所以,用戶在設計數據庫時應當綜合考慮各方面的因素,以求達到最佳的平衡

#其餘字符串系列(效率:char>varchar>text)
TEXT系列 TINYTEXT TEXT MEDIUMTEXT LONGTEXT
BLOB 系列    TINYBLOB BLOB MEDIUMBLOB LONGBLOB 
BINARY系列 BINARY VARBINARY

text:text數據類型用於保存變長的大字符串,能夠組多到65535 (2**16 − 1)個字符。
mediumtext:A TEXT column with a maximum length of 16,777,215 (2**24 − 1) characters.
longtext:A TEXT column with a maximum length of 4,294,967,295 or 4GB (2**32 − 1) characters.
複製代碼

 

 

枚舉類型和集合類型

字段的值只能在給定範圍中選擇,如單選框,多選框

enum 單選 只能在給定的範圍內選一個值,如性別 sex 男male/女female

set 多選 在給定的範圍內能夠選擇一個或一個以上的值(愛好1,愛好2,愛好3...)

複製代碼
mysql> create table consumer(
    -> id int,
    -> name varchar(50),
    -> sex enum('male','female','other'),
    -> level enum('vip1','vip2','vip3','vip4'),#在指定範圍內,多選一
    -> fav set('play','music','read','study') #在指定範圍內,多選多
    -> );
Query OK, 0 rows affected (0.03 sec)


mysql> insert into consumer values
    -> (1,'趙雲','male','vip2','read,study'),
    -> (2,'趙雲2','other','vip4','play');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from consumer;
+------+---------+-------+-------+------------+
| id   | name    | sex   | level | fav        |
+------+---------+-------+-------+------------+
|    1 | 趙雲    | male  | vip2  | read,study |
|    2 | 趙雲2   | other | vip4  | play       |
+------+---------+-------+-------+------------+
2 rows in set (0.00 sec)
複製代碼
 
 
 

09-完整性約束

 

本節重點:

  • not null 與 default
  • unique
  • primary
  • auto_increment
  • foreign key

 

 

1、介紹

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

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

主要分爲:

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

UNSIGNED #無符號
ZEROFILL #使用0填充
複製代碼

說明:

複製代碼
#1. 是否容許爲空,默認NULL,可設置NOT NULL,字段不容許爲空,必須賦值
#2. 字段是否有默認值,缺省的默認值是NULL,若是插入記錄時不給字段賦值,此字段使用默認值
sex enum('male','female') not null default 'male'

#必須爲正值(無符號) 不容許爲空 默認是20
age int unsigned NOT NULL default 20 
# 3. 是不是key
主鍵 primary key
外鍵 foreign key
索引 (index,unique...)
複製代碼

 

2、not null 與default

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

默認值,建立列時能夠指定默認值,當插入數據時若是未主動設置,則自動添加默認值

create table tb1(
    nid int not null defalut 2,
    num int not null

);

 

驗證1:

 

複製代碼
mysql> create table t11(id int);# id字段默承認覺得空
Query OK, 0 rows affected (0.05 sec)

mysql> desc t11;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES   |          | NULL    |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.03 sec)
mysql> insert into t11 values(); #給t11表插一個空的值
Query OK, 1 row affected (0.00 sec)

#查詢結果以下
mysql> select * from t11;
+------+
| id   |
+------+
| NULL |
+------+
1 row in set (0.00 sec)
複製代碼

 

 

驗證2:

複製代碼
mysql> create table t12(id int not null);#設置字段id不爲空
Query OK, 0 rows affected (0.03 sec)

mysql> desc t12;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.01 sec)

mysql> insert into t12 values();#不能插入空
ERROR 1364 (HY000): Field 'id' doesn't have a default value
複製代碼

 

驗證3:

複製代碼
# 第一種狀況
mysql> create table t13(id int default 1);
Query OK, 0 rows affected (0.03 sec)

mysql> desc t13;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |           | 1              |              |
+-------+---------+------+-----+---------+-------+
1 row in set (0.01 sec)

mysql> insert into t13 values();
Query OK, 1 row affected (0.00 sec)

mysql> select * from t13;
+------+
| id   |
+------+
|    1  |
+------+
1 row in set (0.00 sec)


# 第二種狀況
mysql> create table t14(id int not null default 2);
Query OK, 0 rows affected (0.02 sec)

mysql> desc t14;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO      |         | 2               |             |
+-------+---------+------+-----+---------+-------+
1 row in set (0.01 sec)

mysql> select * from t14;
+----+
| id |
+----+
|  2 |
+----+
1 row in set (0.00 sec)
複製代碼

 

小練習:

建立學生表student2,設置每一個字段的約束條件。

複製代碼
mysql> create table student2(
    -> id int not null,
    -> name varchar(50) not null,
    -> age int(3) unsigned not null default 18,
    -> sex enum('male','female') default 'male',
    -> fav set('smoke','drink','tangtou') default 'drink,tangtou'
    -> );
Query OK, 0 rows affected (0.01 sec)

# 只插入了not null約束條件的字段對應的值
mysql> insert into student2(id,name) values(1,'mjj');
Query OK, 1 row affected (0.00 sec)

# 查詢結果以下
mysql> select * from student2;
+----+------+-----+------+---------------+
| id | name | age | sex  | fav           |
+----+------+-----+------+---------------+
|  1 | mjj  |  18 | male | drink,tangtou |
+----+------+-----+------+---------------+
1 row in set (0.00 sec)
複製代碼

 

三、unique

中文翻譯:不一樣的。在mysql中稱爲單列惟一

 

舉例說明:建立公司部門表(每一個公司都有惟一的一個部門)。

複製代碼
mysql> create table department(
    -> id int,
    -> name char(10)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> insert into department values(1,'IT'),(2,'IT');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from department;
+------+------+
| id   | name |
+------+------+
|    1 | IT   |
|    2 | IT   |
+------+------+
2 rows in set (0.00 sec)
# 發現: 同時插入兩個IT部門也是能夠的,但這是不合理的,因此咱們要設置name字段爲unique 解決這種不合理的現象。
複製代碼

 

接下來,使用約束條件unique,來對公司部門的字段進行設置。

複製代碼
#第一種建立unique的方式
#例子1:
create table department(
    id int,
    name char(10) unique
);
mysql> insert into department values(1,'it'),(2,'it');
ERROR 1062 (23000): Duplicate entry 'it' for key 'name'

#例子2:
create table department(
    id int unique,
    name char(10) unique
);
insert into department values(1,'it'),(2,'sale');

#第二種建立unique的方式
create table department(
    id int,
    name char(10) ,
    unique(id),
    unique(name)
);
insert into department values(1,'it'),(2,'sale');
複製代碼

 

聯合惟一:

複製代碼
# 建立services表
mysql> create table services(
    -> id int,
    -> ip char(15),
    -> port int,
    -> unique(id),
    -> unique(ip,port)
    -> );
Query OK, 0 rows affected (0.05 sec)

mysql> desc services;
+-------+----------+------+-----+---------+-------+
| Field | Type      | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id        | int(11)   | YES   | UNI  | NULL       |             |
| ip        | char(15) | YES   | MUL  | NULL       |             |
| port    | int(11) | YES   |          | NULL       |             |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.01 sec)

#聯合惟一,只要兩列記錄,有一列不一樣,既符合聯合惟一的約束
mysql> insert into services values
    -> (1,'192,168,11,23',80),
    -> (2,'192,168,11,23',81),
    -> (3,'192,168,11,25',80);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from services;
+------+---------------+------+
| id   | ip            | port |
+------+---------------+------+
|    1 | 192,168,11,23 |   80 |
|    2 | 192,168,11,23 |   81 |
|    3 | 192,168,11,25 |   80 |
+------+---------------+------+
3 rows in set (0.00 sec)

mysql> insert into services values (4,'192,168,11,23',80);
ERROR 1062 (23000): Duplicate entry '192,168,11,23-80' for key 'ip'
複製代碼

 

4.primary key

一個表中能夠:

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

約束:等價於 not null unique,字段的值不爲空且惟一

存儲引擎默認是(innodb):對於innodb存儲引擎來講,一張表必須有一個主鍵。

單列主鍵

複製代碼
# 建立t14表,爲id字段設置主鍵,惟一的不一樣的記錄
create table t14(
    id int primary key,
    name char(16)
);

insert into t14 values
(1,'xiaoma'),
(2,'xiaohong');

mysql> insert into t14 values(2,'wxxx');
ERROR 1062 (23000): Duplicate entry '6' for key 'PRIMARY'


#   not null + unique的化學反應,至關於給id設置primary key
create table t15(
    id int not null unique,
    name char(16)
);
mysql> create table t15(
    -> id int not null unique,
    -> name char(16)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> desc t15;
+-------+----------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id        | int(11)  | NO     | PRI | NULL       |             |
| name   | char(16) | YES  |         | NULL       |             |
+-------+----------+------+-----+---------+-------+
2 rows in set (0.02 sec)
複製代碼

 

複合主鍵

複製代碼
create table t16(
    ip char(15),
    port int,
    primary key(ip,port)
);

insert into t16 values
('1.1.1.2',80),
('1.1.1.2',81);
複製代碼

 

5.auto_increment

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

 

(重點)驗證:

複製代碼
# 建立student
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    |                |
+-------+-----------------------+------+-----+---------+----------------+
3 rows in set (0.17 sec)

#插入記錄
mysql>  insert into student(name) values ('老白'),('小白');
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from student;
+----+--------+------+
| id | name   | sex  |
+----+--------+------+
|  1 | 老白   | male |
|  2 | 小白   | male |
+----+--------+------+
2 rows in set (0.00 sec)
複製代碼

 

複製代碼
mysql> insert into student values(4,'asb','female');
Query OK, 1 row affected (0.00 sec)

mysql> insert into student values(7,'wsb','female');
Query OK, 1 row affected (0.01 sec)

mysql> select * from student;
+----+--------+--------+
| id | name   | sex    |
+----+--------+--------+
|  1 | 老白   | male   |
|  2 | 小白   | male   |
|  4 | asb    | female |
|  7 | wsb    | female |
+----+--------+--------+
4 rows in set (0.00 sec)

# 再次插入一條不指定id的記錄,會在以前的最後一條記錄繼續增加
mysql>  insert into student(name) values ('大白');
Query OK, 1 row affected (0.00 sec)

mysql> select * from student;
+----+--------+--------+
| id | name   | sex    |
+----+--------+--------+
|  1 | 老白   | male   |
|  2 | 小白   | male   |
|  4 | asb    | female |
|  7 | wsb    | female |
|  8 | 大白   | male   |
+----+--------+--------+
5 rows in set (0.00 sec)
複製代碼

 

複製代碼
mysql> delete from student;
Query OK, 5 rows affected (0.00 sec)

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

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

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

mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  9 | ysb  | 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('xiaobai');
Query OK, 1 row affected (0.00 sec)

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

mysql>
複製代碼

 

瞭解:

複製代碼
查看可用的 開頭auto_inc的詞
mysql> show variables like 'auto_inc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+
2 rows in set (0.02 sec)
# 步長auto_increment_increment,默認爲1
# 起始的偏移量auto_increment_offset, 默認是1

 # 設置步長 爲會話設置,只在本次鏈接中有效
 set session auto_increment_increment=5;

 #全局設置步長 都有效。
 set global auto_increment_increment=5;

 # 設置起始偏移量
 set global  auto_increment_offset=3;

#強調:If the value of auto_increment_offset is greater than that of auto_increment_increment, the value of auto_increment_offset is ignored. 
翻譯:若是auto_increment_offset的值大於auto_increment_increment的值,則auto_increment_offset的值會被忽略 

# 設置完起始偏移量和步長以後,再次執行show variables like'auto_inc%';
發現跟以前同樣,必須先exit,再登陸纔有效。

mysql> show variables like'auto_inc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 5     |
| auto_increment_offset    | 3     |
+--------------------------+-------+
2 rows in set (0.00 sec)

#由於以前有一條記錄id=1
mysql> select * from student;
+----+---------+------+
| id | name    | sex  |
+----+---------+------+
|  1 | xiaobai | male |
+----+---------+------+
1 row in set (0.00 sec)
# 下次插入的時候,從起始位置3開始,每次插入記錄id+5
mysql> insert into student(name) values('ma1'),('ma2'),('ma3');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from student;
+----+---------+------+
| id | name    | sex  |
+----+---------+------+
|  1 | xiaobai | male |
|  3 | ma1     | male |
|  8 | ma2     | male |
| 13 | ma3     | male |
+----+---------+------+
複製代碼

 

清空表區分delete和truncate的區別:

delete from t1; #若是有自增id,新增的數據,仍然是以刪除前的最後同樣做爲起始。

truncate table t1;數據量大,刪除速度比上一條快,且直接從零開始。

 

6.foreign key

 

一 快速理解foreign key

以前建立表的時候都是在一張表中添加記錄,好比以下表:

 

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

這個時候,

解決方法:

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

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

咱們能夠將上表改成以下結構:

 

此時有兩張表,一張是employee表,簡稱emp表(關聯表,也就從表)。一張是department表,簡稱dep表(被關聯表,也叫主表)。

 

建立兩張表操做:

複製代碼
#1.建立表時先建立被關聯表,再建立關聯表
# 先建立被關聯表(dep表)
create table dep(
    id int primary key,
    name varchar(20) not null,
    descripe varchar(20) not null
);

#再建立關聯表(emp表)
create table emp(
    id int primary key,
    name varchar(20) not null,
    age int not null,
    dep_id int,
    constraint fk_dep foreign key(dep_id) references dep(id) 
);

#2.插入記錄時,先往被關聯表中插入記錄,再往關聯表中插入記錄

insert into dep values
(1,'IT','IT技術有限部門'),
(2,'銷售部','銷售部門'),
(3,'財務部','花錢太多部門');

insert into emp values
(1,'zhangsan',18,1),
(2,'lisi',19,1),
(3,'egon',20,2),
(4,'yuanhao',40,3),
(5,'alex',18,2);

3.刪除表
#按道理來講,刪除了部門表中的某個部門,員工表的有關聯的記錄相繼刪除。
mysql> delete from dep where id=3;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`db5`.`emp`, CONSTRAINT `fk_name` FOREIGN KEY (`dep_id`) REFERENCES `dep` (`id`))

#可是先刪除員工表的記錄以後,再刪除當前部門就沒有任何問題

mysql> delete from emp where dep =3;
Query OK, 1 row affected (0.00 sec)

mysql> select * from emp;
+----+----------+-----+--------+
| id | name     | age | dep_id |
+----+----------+-----+--------+
|  1 | zhangsan |  18 |      1 |
|  2 | lisi     |  18 |      1 |
|  3 | egon     |  20 |      2 |
|  5 | alex     |  18 |      2 |
+----+----------+-----+--------+
4 rows in set (0.00 sec)

mysql> delete from dep where id=3;
Query OK, 1 row affected (0.00 sec)

mysql> select * from dep;
+----+-----------+----------------------+
| id | name      | descripe             |
+----+-----------+----------------------+
|  1 | IT        | IT技術有限部門       |
|  2 | 銷售部    | 銷售部門             |
+----+-----------+----------------------+
2 rows in set (0.00 sec)
複製代碼

 

上面的刪除表記錄的操做比較繁瑣,按道理講,裁掉一個部門,該部門的員工也會被裁掉。其實呢,在建表的時候還有個很重要的內容,叫同步刪除,同步更新

接下來將剛建好的兩張表所有刪除,先刪除關聯表(emp),再刪除被關聯表(dep)

接下來:
重複上面的操做建表
注意:在關聯表中加入
on delete cascade #同步刪除
on update cascade #同步更新

修改emp表:

複製代碼
create table emp(
    id int primary key,
    name varchar(20) not null,
    age int not null,
    dep_id int,
    constraint fk_dep foreign key(dep_id) references dep(id) 
    on delete cascade #同步刪除
    on update cascade #同步更新
);
複製代碼

接下來的操做,就複合咱們正常的生活中的狀況了。

複製代碼
#再去刪被關聯表(dep)的記錄,關聯表(emp)中的記錄也跟着刪除
mysql> delete from dep where id=3;
Query OK, 1 row affected (0.00 sec)

mysql> select * from dep;
+----+-----------+----------------------+
| id | name      | descripe             |
+----+-----------+----------------------+
|  1 | IT        | IT技術有限部門       |
|  2 | 銷售部    | 銷售部門             |
+----+-----------+----------------------+
2 rows in set (0.00 sec)

mysql> select * from emp;
+----+----------+-----+--------+
| id | name     | age | dep_id |
+----+----------+-----+--------+
|  1 | zhangsan |  18 |      1 |
|  2 | lisi     |  19 |      1 |
|  3 | egon     |  20 |      2 |
|  5 | alex     |  18 |      2 |
+----+----------+-----+--------+
4 rows in set (0.00 sec)

#再去更改被關聯表(dep)的記錄,關聯表(emp)中的記錄也跟着更改

mysql> update dep set id=222 where id=2;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

# 趕忙去查看一下兩張表是否都被刪除了,是否都被更改了
mysql> select * from dep;
+-----+-----------+----------------------+
| id  | name      | descripe             |
+-----+-----------+----------------------+
|   1 | IT        | IT技術有限部門       |
| 222 | 銷售部    | 銷售部門             |
+-----+-----------+----------------------+
2 rows in set (0.00 sec)

mysql> select * from emp;
+----+----------+-----+--------+
| id | name     | age | dep_id |
+----+----------+-----+--------+
|  1 | zhangsan |  18 |      1 |
|  2 | lisi     |  19 |      1 |
|  3 | egon     |  20 |    222 |
|  5 | alex     |  18 |    222 |
+----+----------+-----+--------+
4 rows in set (0.00 sec)
複製代碼

10-外鍵的變種 三種關係

 

本節重點:

  • 如何找出兩張表之間的關係
  • 表的三種關係

 

1、介紹

由於有foreign key的約束,使得兩張表造成了三種了關係:

  • 多對一
  • 多對多
  • 一對一

2、重點理解若是找出兩張表之間的關係

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

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

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

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

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

 

3、表的三種關係

(1)書和出版社

  一對多(或多對一):一個出版社能夠出版多本書。看圖說話。

  關聯方式: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,
         constraint fk_book_press 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)
;

查詢結果:
mysql> select * from book;
+----+-----------------+----------+
| id | name            | press_id |
+----+-----------------+----------+
|  1 | 九陽神功        |        1 |
|  2 | 九陰真經        |        2 |
|  3 | 九陰白骨爪      |        2 |
|  4 | 獨孤九劍        |        3 |
|  5 | 降龍十巴掌      |        2 |
|  6 | 葵花寶典        |        3 |
+----+-----------------+----------+
6 rows in set (0.00 sec)

mysql> select * from press;
+----+--------------------------------+
| id | name                           |
+----+--------------------------------+
|  1 | 北京工業地雷出版社             |
|  2 | 人民音樂很差聽出版社           |
|  3 | 知識產權沒有用出版社           |
+----+--------------------------------+
3 rows in set (0.00 sec)
複製代碼

 

(2)做者和書籍的關係

  多對多:一個做者能夠寫多本書,一本書也能夠有多個做者,雙向的一對多,即多對多。看圖說話。

  關聯方式:foreign key+一張新的表

 

 

複製代碼
# 建立被關聯表author表,以前的book表在講多對一的關係已建立
create table author(
    id int primary key auto_increment,
    name varchar(20)
);
#這張表就存放了author表和book表的關係,即查詢兩者的關係查這表就能夠了
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('egon'),('alex'),('wusir'),('yuanhao');

# 每一個做者的表明做
egon: 九陽神功、九陰真經、九陰白骨爪、獨孤九劍、降龍十巴掌、葵花寶典
alex: 九陽神功、葵花寶典
wusir:獨孤九劍、降龍十巴掌、葵花寶典
yuanhao:九陽神功

# 在author2book表中插入相應的數據

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,1)
;
# 如今就能夠查author2book對應的做者和書的關係了
mysql> select * from author2book;
+----+-----------+---------+
| id | author_id | book_id |
+----+-----------+---------+
|  1 |         1 |       1 |
|  2 |         1 |       2 |
|  3 |         1 |       3 |
|  4 |         1 |       4 |
|  5 |         1 |       5 |
|  6 |         1 |       6 |
|  7 |         2 |       1 |
|  8 |         2 |       6 |
|  9 |         3 |       4 |
| 10 |         3 |       5 |
| 11 |         3 |       6 |
| 12 |         4 |       1 |
+----+-----------+---------+
12 rows in set (0.00 sec)
複製代碼

 

 

(3)用戶和博客

  一對一:一個用戶只能註冊一個博客,即一對一的關係。看圖說話

  關聯方式:foreign key+unique

 

 

 

複製代碼
#例如: 一個用戶只能註冊一個博客

#兩張表: 用戶表 (user)和 博客表(blog)
# 建立用戶表
create table user(
    id int primary key auto_increment,
    name varchar(20)
);
# 建立博客表
create table blog(
    id int primary key auto_increment,
    url varchar(100),
    user_id int unique,
    constraint fk_user foreign key(user_id) references user(id)
    on delete cascade
    on update cascade
);
#插入用戶表中的記錄
insert into user(name) values
('alex'),
('wusir'),
('egon'),
('xiaoma')
;
# 插入博客表的記錄
insert into blog(url,user_id) values
('http://www.cnblog/alex',1),
('http://www.cnblog/wusir',2),
('http://www.cnblog/egon',3),
('http://www.cnblog/xiaoma',4)
;
# 查詢wusir的博客地址
select url from blog where user_id=2;
複製代碼

11-數據的增刪改

 

本節重點:

  • 插入數據 INSERT
  • 更新數據 UPDATE
  • 刪除數據 DELETE

再來回顧一下以前咱們練過的一些操做,相信你們都對插入數據、更新數據、刪除數據有了全面的認識。那麼在mysql中其實最重要的不是這三大操做,而是查數據最重要,下節課知曉

複製代碼
1、
在MySQL管理軟件中,能夠經過SQL語句中的DML語言來實現數據的操做,包括

1.使用INSERT實現數據的插入
2.UPDATE實現數據的更新
3.使用DELETE實現數據的刪除
4.使用SELECT查詢數據以及。


2、插入數據 INSERT
1. 插入完整數據(順序插入)
    語法一:
    INSERT INTO 表名(字段1,字段2,字段3…字段n) VALUES(值1,值2,值3…值n);

    語法二:
    INSERT INTO 表名 VALUES (值1,值2,值3…值n);

2. 指定字段插入數據
    語法:
    INSERT INTO 表名(字段1,字段2,字段3…) VALUES (值1,值2,值3…);

3. 插入多條記錄
    語法:
    INSERT INTO 表名 VALUES
        (值1,值2,值3…值n),
        (值1,值2,值3…值n),
        (值1,值2,值3…值n);

 4. 插入查詢結果
    語法:
    INSERT INTO 表名(字段1,字段2,字段3…字段n) 
                    SELECT (字段1,字段2,字段3…字段n) FROM 表2
                    WHERE …;

3、更新數據UPDATE
語法:
    UPDATE 表名 SET
        字段1=值1,
        字段2=值2,
        WHERE CONDITION;

示例:
    UPDATE mysql.user SET password=password(‘123’) 
        where user=’root’ and host=’localhost’;
4、刪除數據DELETE
語法:
    DELETE FROM 表名 
        WHERE CONITION;

示例:
    DELETE FROM mysql.user 
        WHERE password=’’;
複製代碼

 

12-單表查詢

 

本節重點:

  單表查詢

 

語法:

複製代碼
1、單表查詢的語法
   SELECT 字段1,字段2... FROM 表名
                  WHERE 條件
                  GROUP BY field
                  HAVING 篩選
                  ORDER BY field
                  LIMIT 限制條數
2、關鍵字的執行優先級(重點)

重點中的重點:關鍵字的執行優先級
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                  
    姓名            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 primary key 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 |
| emp_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    |                |
| salart               | double(15,2)                  | YES  |         | NULL    |                |
| office              | int(11)                           | YES  |         | NULL    |                |
| depart_id        | int(11)                           | YES  |         | NULL    |                |
+--------------+-----------------------+------+-----+---------+----------------+
10 rows in set (0.08 sec)

#插入記錄
#三個部門:教學,銷售,運營
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),
('xiaomage','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)
;
複製代碼

 

(1)where 約束 

複製代碼
where子句中能夠使用
1.比較運算符:>、<、>=、<=、<>、!=
2.between 80 and 100 :值在80到100之間
3.in(80,90,100)值是10或20或30
4.like 'xiaomagepattern': pattern能夠是%或者_。%小時任意多字符,_表示一個字符
5.邏輯運算符:在多個條件直接能夠使用邏輯運算符 and or not
複製代碼

 

驗證結果:

複製代碼
#1 :單條件查詢
mysql> select id,emp_name from employee where id > 5;
+----+------------+
| id | emp_name   |
+----+------------+
|  6 | jingliyang |
|  7 | jinxin     |
|  8 | xiaomage   |
|  9 | 歪歪       |
| 10 | 丫丫       |
| 11 | 丁丁       |
| 12 | 星星       |
| 13 | 格格       |
| 14 | 張野       |
| 15 | 程咬金     |
| 16 | 程咬銀     |
| 17 | 程咬銅     |
| 18 | 程咬鐵     |

#2 多條件查詢
mysql> select emp_name from employee where post='teacher' and salary>10000;
+----------+
| emp_name |
+----------+
| alex         |
| jinxin     |
+----------+

#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;

#注意''是空字符串,不是null
 SELECT name,post_comment FROM employee WHERE post_comment='';
 ps:
        執行
        update employee set post_comment='' where id=2;
        再用上條查看,就會有結果了
#5:關鍵字IN集合查詢
mysql>  SELECT name,salary FROM employee WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ;
+------------+---------+
| name       | salary  |
+------------+---------+
| yuanhao    | 3500.00 |
| jingliyang | 9000.00 |
+------------+---------+
2 rows in set (0.00 sec)

mysql>  SELECT name,salary FROM employee  WHERE salary IN (3000,3500,4000,9000) ;
+------------+---------+
| name       | salary  |
+------------+---------+
| yuanhao    | 3500.00 |
| jingliyang | 9000.00 |
+------------+---------+
mysql>  SELECT name,salary FROM employee  WHERE salary NOT IN (3000,3500,4000,9000) ;
+-----------+------------+
| name      | salary     |
+-----------+------------+
| egon      |    7300.33 |
| alex      | 1000000.31 |
| wupeiqi   |    8300.00 |
| liwenzhou |    2100.00 |
| jinxin    |   30000.00 |
| xiaomage  |   10000.00 |
| 歪歪      |    3000.13 |
| 丫丫      |    2000.35 |
| 丁丁      |    1000.37 |
| 星星      |    3000.29 |
| 格格      |    4000.33 |
| 張野      |   10000.13 |
| 程咬金    |   20000.00 |
| 程咬銀    |   19000.00 |
| 程咬銅    |   18000.00 |
| 程咬鐵    |   17000.00 |
+-----------+------------+
16 rows in set (0.00 sec)

#6:關鍵字LIKE模糊查詢
通配符’%’
mysql> SELECT * FROM employee WHERE name LIKE 'jin%';
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
| id | name       | sex    | age | hire_date  | post    | post_comment | salary   | office | depart_id |
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
|  6 | jingliyang | female |  18 | 2011-02-11 | teacher | NULL         |  9000.00 |    401 |         1 |
|  7 | jinxin     | male   |  18 | 1900-03-01 | teacher | NULL         | 30000.00 |    401 |         1 |
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
2 rows in set (0.00 sec)


通配符'_'

mysql> SELECT  age FROM employee WHERE name LIKE 'ale_';
+-----+
| age |
+-----+
|  78 |
+-----+
1 row in set (0.00 sec)

練習:
1. 查看崗位是teacher的員工姓名、年齡
2. 查看崗位是teacher且年齡大於30歲的員工姓名、年齡
3. 查看崗位是teacher且薪資在9000-1000範圍內的員工姓名、年齡、薪資
4. 查看崗位描述不爲NULL的員工信息
5. 查看崗位是teacher且薪資是10000或9000或30000的員工姓名、年齡、薪資
6. 查看崗位是teacher且薪資不是10000或9000或30000的員工姓名、年齡、薪資
7. 查看崗位是teacher且名字是jin開頭的員工姓名、年薪

#對應的sql語句
select name,age from employee where post = 'teacher';
select name,age from employee where post='teacher' and age > 30; 
select name,age,salary from employee where post='teacher' and salary between 9000 and 10000;
select * from employee where post_comment is not null;
select name,age,salary from employee where post='teacher' and salary in (10000,9000,30000);
select name,age,salary from employee where post='teacher' and salary not in (10000,9000,30000);
select name,salary*12 from employee where post='teacher' and name like 'jin%';
複製代碼

 

(2)group by 分組查詢

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

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

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

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

#四、大前提:
    能夠按照任意字段分組,可是分組完畢後,好比group by post,只能查看post字段,若是想查看組內信息,須要藉助於聚合函數
複製代碼

 

當執行如下sql語句的時候,是以post字段查詢了組中的第一條數據,沒有任何意義,由於咱們如今想查出當前組的多條記錄。

複製代碼
mysql> select * from employee 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                                 |              | 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,因而也能夠有結果,默認都是組內的第一條記錄,但其實這是沒有意義的
若是想分組,則必需要設置全局的sql的模式爲ONLY_FULL_GROUP_BY
mysql> set global sql_mode='ONLY_FULL_GROUP_BY';
Query OK, 0 rows affected (0.00 sec)

#查看MySQL 5.7默認的sql_mode以下:
mysql> select @@global.sql_mode;
+--------------------+
| @@global.sql_mode  |
+--------------------+
| ONLY_FULL_GROUP_BY |
+--------------------+
1 row in set (0.00 sec)

mysql> exit;#設置成功後,必定要退出,而後從新登陸方可生效
Bye
複製代碼

 

繼續驗證經過group by分組以後,只能查看當前字段,若是想查看組內信息,須要藉助於聚合函數

複製代碼
mysql> select * from emp group by post;# 報錯
ERROR 1054 (42S22): Unknown column 'post' in 'group statement'



mysql>  select post from employee group by post;
+-----------------------------------------+
| post                                    |
+-----------------------------------------+
| operation                               |
| sale                                    |
| teacher                                 |
| 老男孩駐沙河辦事處外交大使              |
+-----------------------------------------+
4 rows in set (0.00 sec)
複製代碼

 

 

(3)聚合函數

複製代碼
max()求最大值
min()求最小值
avg()求平均值
sum() 求和
count() 求總個數

#強調:聚合函數聚合的是組的內容,如果沒有分組,則默認一組
# 每一個部門有多少個員工
select post,count(id) from employee group by post;
# 每一個部門的最高薪水
select post,max(salary) from employee group by post;
# 每一個部門的最低薪水
select post,min(salary) from employee group by post;
# 每一個部門的平均薪水
select post,avg(salary) from employee group by post;
# 每一個部門的全部薪水
select post,sum(age) from employee group by post;
複製代碼

 

複製代碼
1. 查詢崗位名以及崗位包含的全部員工名字
2. 查詢崗位名以及各崗位內包含的員工個數
3. 查詢公司內男員工和女員工的個數
4. 查詢崗位名以及各崗位的平均薪資
5. 查詢崗位名以及各崗位的最高薪資
6. 查詢崗位名以及各崗位的最低薪資
7. 查詢男員工與男員工的平均薪資,女員工與女員工的平均薪資
複製代碼

 

 

(4)HAVING過濾

  

複製代碼
HAVING與WHERE不同的地方在於

#!!!執行優先級從高到低:where > group by > having 
#1. Where 發生在分組group by以前,於是Where中能夠有任意字段,可是絕對不能使用聚合函數。

#2. Having發生在分組group by以後,於是Having中能夠使用分組的字段,沒法直接取到其餘字段,能夠使用聚合函數
複製代碼

 

驗證:

複製代碼
驗證:
mysql> select * from employee where salary>1000000;
+----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
| id | name | sex  | age | hire_date  | post    | post_comment | salary     | office | depart_id |
+----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
|  2 | alex | male |  78 | 2015-03-02 | teacher |              | 1000000.31 |    401 |         1 |
+----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
1 row in set (0.00 sec)

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

# 必須使用group by才能使用group_concat()函數,將全部的name值鏈接
mysql> select post,group_concat(name) from emp group by post having salary > 10000; ##錯誤,分組後沒法直接取到salary字段
ERROR 1054 (42S22): Unknown column 'post' in 'field list'
複製代碼

 

小練習:

1. 查詢各崗位內包含的員工個數小於2的崗位名、崗位內包含員工名字、個數
2. 查詢各崗位平均薪資大於10000的崗位名、平均工資
3. 查詢各崗位平均薪資大於10000且小於20000的崗位名、平均工資

 

小練習答案:

複製代碼
# 題1:
mysql> select post,group_concat(name),count(id) from employee group by post;
+-----------------------------------------+-----------------------------------------------------------+-----------+
| post                                    | group_concat(name)                                        | count(id) |
+-----------------------------------------+-----------------------------------------------------------+-----------+
| operation                               | 程咬鐵,程咬銅,程咬銀,程咬金,張野                          |         5 |
| sale                                    | 格格,星星,丁丁,丫丫,歪歪                                  |         5 |
| teacher                                 | xiaomage,jinxin,jingliyang,liwenzhou,yuanhao,wupeiqi,alex |         7 |
| 老男孩駐沙河辦事處外交大使              | egon                                                      |         1 |
+-----------------------------------------+-----------------------------------------------------------+-----------+
4 rows in set (0.00 sec)

mysql> select post,group_concat(name),count(id) from employee group by post having count(id)<2;
+-----------------------------------------+--------------------+-----------+
| post                                    | group_concat(name) | count(id) |
+-----------------------------------------+--------------------+-----------+
| 老男孩駐沙河辦事處外交大使              | egon               |         1 |
+-----------------------------------------+--------------------+-----------+
1 row in set (0.00 sec)


#題2:
mysql> select post,avg(salary) from employee group by post having avg(salary) > 10000;
+-----------+---------------+
| post      | avg(salary)   |
+-----------+---------------+
| operation |  16800.026000 |
| teacher   | 151842.901429 |
+-----------+---------------+
2 rows in set (0.00 sec)

#題3:
mysql> select post,avg(salary) from employee group by post having avg(salary) > 10000 and avg(salary) <20000;
+-----------+--------------+
| post      | avg(salary)  |
+-----------+--------------+
| operation | 16800.026000 |
+-----------+--------------+
1 row in set (0.00 sec)
複製代碼

 

(5)order by 查詢排序

複製代碼
按單列排序
    SELECT * FROM employee ORDER BY age;
    SELECT * FROM employee ORDER BY age ASC;
    SELECT * FROM employee ORDER BY age DESC;
按多列排序:先按照age升序排序,若是年紀相同,則按照id降序
    SELECT * from employee
        ORDER BY age ASC,
        id DESC;
複製代碼

 

複製代碼
驗證多列排序:
SELECT * from employee ORDER BY age ASC,id DESC;
mysql> SELECT * from employee ORDER BY age ASC,id DESC;
+----+------------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| id | name       | sex    | age | hire_date  | post                                    | post_comment | salary     | office | depart_id |
+----+------------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| 18 | 程咬鐵     | female |  18 | 2014-05-12 | operation                               | NULL         |   17000.00 |    403 |         3 |
| 17 | 程咬銅     | male   |  18 | 2015-04-11 | operation                               | NULL         |   18000.00 |    403 |         3 |
| 16 | 程咬銀     | female |  18 | 2013-03-11 | operation                               | NULL         |   19000.00 |    403 |         3 |
| 15 | 程咬金     | male   |  18 | 1997-03-12 | operation                               | NULL         |   20000.00 |    403 |         3 |
| 12 | 星星       | female |  18 | 2016-05-13 | sale                                    | NULL         |    3000.29 |    402 |         2 |
| 11 | 丁丁       | female |  18 | 2011-03-12 | sale                                    | NULL         |    1000.37 |    402 |         2 |
|  7 | jinxin     | male   |  18 | 1900-03-01 | teacher                                 | NULL         |   30000.00 |    401 |         1 |
|  6 | jingliyang | female |  18 | 2011-02-11 | teacher                                 | NULL         |    9000.00 |    401 |         1 |
|  1 | egon       | male   |  18 | 2017-03-01 | 老男孩駐沙河辦事處外交大使              | NULL         |    7300.33 |    401 |         1 |
| 14 | 張野       | male   |  28 | 2016-03-11 | operation                               | NULL         |   10000.13 |    403 |         3 |
| 13 | 格格       | female |  28 | 2017-01-27 | sale                                    | NULL         |    4000.33 |    402 |         2 |
|  5 | liwenzhou  | male   |  28 | 2012-11-01 | teacher                                 | NULL         |    2100.00 |    401 |         1 |
| 10 | 丫丫       | female |  38 | 2010-11-01 | sale                                    | NULL         |    2000.35 |    402 |         2 |
|  9 | 歪歪       | female |  48 | 2015-03-11 | sale                                    | NULL         |    3000.13 |    402 |         2 |
|  8 | xiaomage   | male   |  48 | 2010-11-11 | teacher                                 | NULL         |   10000.00 |    401 |         1 |
|  4 | yuanhao    | male   |  73 | 2014-07-01 | teacher                                 | NULL         |    3500.00 |    401 |         1 |
|  2 | alex       | male   |  78 | 2015-03-02 | teacher                                 |              | 1000000.31 |    401 |         1 |
|  3 | wupeiqi    | male   |  81 | 2013-03-05 | teacher                                 | NULL         |    8300.00 |    401 |         1 |
+----+------------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
18 rows in set (0.01 sec)

mysql>
複製代碼

 

小練習:

1. 查詢全部員工信息,先按照age升序排序,若是age相同則按照hire_date降序排序
2. 查詢各崗位平均薪資大於10000的崗位名、平均工資,結果按平均薪資升序排列
3. 查詢各崗位平均薪資大於10000的崗位名、平均工資,結果按平均薪資降序排列 

 

複製代碼
# 題目1
select * from employee ORDER BY age asc,hire_date desc;

# 題目2
mysql> select post,avg(salary) from employee group by post having avg(salary) > 10000 order by avg(salary) asc;
+-----------+---------------+
| post      | avg(salary)   |
+-----------+---------------+
| operation |  16800.026000 |
| teacher   | 151842.901429 |
+-----------+---------------+
2 rows in set (0.00 sec)

# 題目3
mysql> select post,avg(salary) from employee group by post having avg(salary) > 10000 order by avg(salary) desc;
+-----------+---------------+
| post      | avg(salary)   |
+-----------+---------------+
| teacher   | 151842.901429 |
| operation |  16800.026000 |
+-----------+---------------+
2 rows in set (0.00 sec)

mysql>
複製代碼

 

(5)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條
複製代碼

 

小練習:
分頁顯示,每頁5條

複製代碼
# 第1頁數據
  mysql> select * from  employee limit 0,5;
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| id | name      | sex  | age | hire_date  | post                                    | post_comment | salary     | office | depart_id |
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
|  1 | egon      | male |  18 | 2017-03-01 | 老男孩駐沙河辦事處外交大使              | NULL         |    7300.33 |    401 |         1 |
|  2 | alex      | male |  78 | 2015-03-02 | teacher                                 |              | 1000000.31 |    401 |         1 |
|  3 | wupeiqi   | male |  81 | 2013-03-05 | teacher                                 | NULL         |    8300.00 |    401 |         1 |
|  4 | yuanhao   | male |  73 | 2014-07-01 | teacher                                 | NULL         |    3500.00 |    401 |         1 |
|  5 | liwenzhou | male |  28 | 2012-11-01 | teacher                                 | NULL         |    2100.00 |    401 |         1 |
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
5 rows in set (0.00 sec)
# 第2頁數據
mysql> select * from  employee limit 5,5;
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
| id | name       | sex    | age | hire_date  | post    | post_comment | salary   | office | depart_id |
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
|  6 | jingliyang | female |  18 | 2011-02-11 | teacher | NULL         |  9000.00 |    401 |         1 |
|  7 | jinxin     | male   |  18 | 1900-03-01 | teacher | NULL         | 30000.00 |    401 |         1 |
|  8 | xiaomage   | male   |  48 | 2010-11-11 | teacher | NULL         | 10000.00 |    401 |         1 |
|  9 | 歪歪       | female |  48 | 2015-03-11 | sale    | NULL         |  3000.13 |    402 |         2 |
| 10 | 丫丫       | female |  38 | 2010-11-01 | sale    | NULL         |  2000.35 |    402 |         2 |
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
5 rows in set (0.00 sec)
# 第3頁數據
mysql> select * from  employee limit 10,5;
+----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
| id | name      | sex    | age | hire_date  | post      | post_comment | salary   | office | depart_id |
+----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
| 11 | 丁丁      | female |  18 | 2011-03-12 | sale      | NULL         |  1000.37 |    402 |         2 |
| 12 | 星星      | female |  18 | 2016-05-13 | sale      | NULL         |  3000.29 |    402 |         2 |
| 13 | 格格      | female |  28 | 2017-01-27 | sale      | NULL         |  4000.33 |    402 |         2 |
| 14 | 張野      | male   |  28 | 2016-03-11 | operation | NULL         | 10000.13 |    403 |         3 |
| 15 | 程咬金    | male   |  18 | 1997-03-12 | operation | NULL         | 20000.00 |    403 |         3 |
+----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
5 rows in set (0.00 sec)
複製代碼

 

# 第1頁數據
  mysql> select * from  employee limit 0,5;
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| id | name      | sex  | age | hire_date  | post                                    | post_comment | salary     | office | depart_id |
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
|  1 | egon      | male |  18 | 2017-03-01 | 老男孩駐沙河辦事處外交大使              | NULL         |    7300.33 |    401 |         1 |
|  2 | alex      | male |  78 | 2015-03-02 | teacher                                 |              | 1000000.31 |    401 |         1 |
|  3 | wupeiqi   | male |  81 | 2013-03-05 | teacher                                 | NULL         |    8300.00 |    401 |         1 |
|  4 | yuanhao   | male |  73 | 2014-07-01 | teacher                                 | NULL         |    3500.00 |    401 |         1 |
|  5 | liwenzhou | male |  28 | 2012-11-01 | teacher                                 | NULL         |    2100.00 |    401 |         1 |
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
rows in set (0.00 sec)
# 第2頁數據
mysql> select * from  employee limit 5,5;
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
| id | name       | sex    | age | hire_date  | post    | post_comment | salary   | office | depart_id |
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
|  6 | jingliyang | female |  18 | 2011-02-11 | teacher | NULL         |  9000.00 |    401 |         1 |
|  7 | jinxin     | male   |  18 | 1900-03-01 | teacher | NULL         | 30000.00 |    401 |         1 |
|  8 | xiaomage   | male   |  48 | 2010-11-11 | teacher | NULL         | 10000.00 |    401 |         1 |
|  9 | 歪歪       | female |  48 | 2015-03-11 | sale    | NULL         |  3000.13 |    402 |         2 |
| 10 | 丫丫       | female |  38 | 2010-11-01 | sale    | NULL         |  2000.35 |    402 |         2 |
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
rows in set (0.00 sec)
# 第3頁數據
mysql> select * from  employee limit 10,5;
+----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
| id | name      | sex    | age | hire_date  | post      | post_comment | salary   | office | depart_id |
+----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
| 11 | 丁丁      | female |  18 | 2011-03-12 | sale      | NULL         |  1000.37 |    402 |         2 |
| 12 | 星星      | female |  18 | 2016-05-13 | sale      | NULL         |  3000.29 |    402 |         2 |
| 13 | 格格      | female |  28 | 2017-01-27 | sale      | NULL         |  4000.33 |    402 |         2 |
| 14 | 張野      | male   |  28 | 2016-03-11 | operation | NULL         | 10000.13 |    403 |         3 |
| 15 | 程咬金    | male   |  18 | 1997-03-12 | operation | NULL         | 20000.00 |    403 |         3 |
+----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
rows in set (0.00 sec)

小練習答案

13-多表查詢

 

本節重點:

  • 多表鏈接查詢
  • 符合條件鏈接查詢
  • 子查詢

  

 

準備工做:準備兩張表,部門表(department)、員工表(employee)

複製代碼
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),
('nvshen','male',18,200),
('xiaomage','female',18,204)
;

# 查看錶結構和數據
mysql> desc department;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.19 sec)

mysql> desc employee;
+--------+-----------------------+------+-----+---------+----------------+
| Field  | Type                  | Null | Key | Default | Extra          |
+--------+-----------------------+------+-----+---------+----------------+
| id     | int(11)               | NO   | PRI | NULL    | auto_increment |
| name   | varchar(20)           | YES  |     | NULL    |                |
| sex    | enum('male','female') | NO   |     | male    |                |
| age    | int(11)               | YES  |     | NULL    |                |
| dep_id | int(11)               | YES  |     | NULL    |                |
+--------+-----------------------+------+-----+---------+----------------+
5 rows in set (0.01 sec)

mysql> select * from department;
+------+--------------+
| id   | name         |
+------+--------------+
|  200 | 技術         |
|  201 | 人力資源     |
|  202 | 銷售         |
|  203 | 運營         |
+------+--------------+
4 rows in set (0.02 sec)

mysql> select * from employee;
+----+----------+--------+------+--------+
| id | name     | sex    | age  | dep_id |
+----+----------+--------+------+--------+
|  1 | egon     | male   |   18 |    200 |
|  2 | alex     | female |   48 |    201 |
|  3 | wupeiqi  | male   |   38 |    201 |
|  4 | yuanhao  | female |   28 |    202 |
|  5 | nvshen   | male   |   18 |    200 |
|  6 | xiaomage | female |   18 |    204 |
+----+----------+--------+------+--------+
6 rows in set (0.00 sec)
複製代碼

ps:觀察兩張表,發現department表中id=203部門在employee中沒有對應的員工,發現employee中id=6的員工在department表中沒有對應關係。

 

 

1、多表鏈接查詢

兩張表的準備工做已完成,好比如今我要查詢的員工信息以及該員工所在的部門。從該題中,咱們看出既要查員工又要查該員工的部門,確定要將兩張表進行鏈接查詢,多表鏈接查詢。

重點:外連接語法

語法:

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

 

(1)先看第一種狀況交叉鏈接:不適用任何匹配條件。生成笛卡爾積(關於笛卡爾積的含義,你們百度自行補腦)。

複製代碼
mysql> select * from employee,department;
+----+----------+--------+------+--------+------+--------------+
| id | name     | sex    | age  | dep_id | id   | name         |
+----+----------+--------+------+--------+------+--------------+
|  1 | egon     | male   |   18 |    200 |  200 | 技術         |
|  1 | egon     | male   |   18 |    200 |  201 | 人力資源     |
|  1 | egon     | male   |   18 |    200 |  202 | 銷售         |
|  1 | egon     | male   |   18 |    200 |  203 | 運營         |
|  2 | alex     | female |   48 |    201 |  200 | 技術         |
|  2 | alex     | female |   48 |    201 |  201 | 人力資源     |
|  2 | alex     | female |   48 |    201 |  202 | 銷售         |
|  2 | alex     | female |   48 |    201 |  203 | 運營         |
|  3 | wupeiqi  | male   |   38 |    201 |  200 | 技術         |
|  3 | wupeiqi  | male   |   38 |    201 |  201 | 人力資源     |
|  3 | wupeiqi  | male   |   38 |    201 |  202 | 銷售         |
|  3 | wupeiqi  | male   |   38 |    201 |  203 | 運營         |
|  4 | yuanhao  | female |   28 |    202 |  200 | 技術         |
|  4 | yuanhao  | female |   28 |    202 |  201 | 人力資源     |
|  4 | yuanhao  | female |   28 |    202 |  202 | 銷售         |
|  4 | yuanhao  | female |   28 |    202 |  203 | 運營         |
|  5 | nvshen   | male   |   18 |    200 |  200 | 技術         |
|  5 | nvshen   | male   |   18 |    200 |  201 | 人力資源     |
|  5 | nvshen   | male   |   18 |    200 |  202 | 銷售         |
|  5 | nvshen   | male   |   18 |    200 |  203 | 運營         |
|  6 | xiaomage | female |   18 |    204 |  200 | 技術         |
|  6 | xiaomage | female |   18 |    204 |  201 | 人力資源     |
|  6 | xiaomage | female |   18 |    204 |  202 | 銷售         |
|  6 | xiaomage | female |   18 |    204 |  203 | 運營         |
複製代碼

 

(2)內鏈接:只鏈接匹配的行

 

複製代碼
#找兩張表共有的部分,至關於利用條件從笛卡爾積結果中篩選出了匹配的結果
#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;
+----+---------+------+--------+--------------+
| id | name    | age  | sex    | name         |
+----+---------+------+--------+--------------+
|  1 | egon    |   18 | male   | 技術         |
|  2 | alex    |   48 | female | 人力資源     |
|  3 | wupeiqi |   38 | male   | 人力資源     |
|  4 | yuanhao |   28 | female | 銷售         |
|  5 | nvshen  |   18 | male   | 技術         |
+----+---------+------+--------+--------------+
5 rows in set (0.00 sec)

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

 

(3)外連接之左鏈接:優先顯示左表所有記錄

複製代碼
#以左表爲準,即找出全部員工信息,固然包括沒有部門的員工
#本質就是:在內鏈接的基礎上增長左邊有,右邊沒有的結果
mysql> select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;
+----+----------+--------------+
| id | name     | depart_name  |
+----+----------+--------------+
|  1 | egon     | 技術         |
|  5 | nvshen   | 技術         |
|  2 | alex     | 人力資源     |
|  3 | wupeiqi  | 人力資源     |
|  4 | yuanhao  | 銷售         |
|  6 | xiaomage | NULL         |
+----+----------+--------------+
6 rows in set (0.00 sec)
複製代碼

(4) 外連接之右鏈接:優先顯示右表所有記錄

複製代碼
#以右表爲準,即找出全部部門信息,包括沒有員工的部門
#本質就是:在內鏈接的基礎上增長右邊有,左邊沒有的結果
mysql> select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;
+------+---------+--------------+
| id   | name    | depart_name  |
+------+---------+--------------+
|    1 | egon    | 技術         |
|    2 | alex    | 人力資源     |
|    3 | wupeiqi | 人力資源     |
|    4 | yuanhao | 銷售         |
|    5 | nvshen  | 技術         |
| NULL | NULL    | 運營         |
+------+---------+--------------+
6 rows in set (0.00 sec)
複製代碼

 

(5) 全外鏈接:顯示左右兩個表所有記錄(瞭解)

複製代碼
#外鏈接:在內鏈接的基礎上增長左邊有右邊沒有的和右邊有左邊沒有的結果
#注意:mysql不支持全外鏈接 full JOIN
#強調:mysql能夠使用此種方式間接實現全外鏈接
語法:select * from employee left join department on employee.dep_id = department.id 
       union all
      select * from employee right join department on employee.dep_id = department.id;

 mysql> select * from employee left join department on employee.dep_id = department.id
          union
        select * from employee right join department on employee.dep_id = department.id
           ;
+------+----------+--------+------+--------+------+--------------+
| id   | name     | sex    | age  | dep_id | id   | name         |
+------+----------+--------+------+--------+------+--------------+
|    1 | egon     | male   |   18 |    200 |  200 | 技術         |
|    5 | nvshen   | male   |   18 |    200 |  200 | 技術         |
|    2 | alex     | female |   48 |    201 |  201 | 人力資源     |
|    3 | wupeiqi  | male   |   38 |    201 |  201 | 人力資源     |
|    4 | yuanhao  | female |   28 |    202 |  202 | 銷售         |
|    6 | xiaomage | female |   18 |    204 | NULL | NULL         |
| NULL | NULL     | NULL   | NULL |   NULL |  203 | 運營         |
+------+----------+--------+------+--------+------+--------------+
7 rows in set (0.01 sec)

#注意 union與union all的區別:union會去掉相同的紀錄
複製代碼

 

 

2、符合條件鏈接查詢

示例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;

 

3、子查詢

#1:子查詢是將一個查詢語句嵌套在另外一個查詢語句中。
#2:內層查詢語句的查詢結果,能夠爲外層查詢語句提供查詢條件。
#3:子查詢中能夠包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等關鍵字
#4:還能夠包含比較運算符:= 、 !=、> 、<等

 

例子:

(1)帶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人的部門名
select name from department
    where id not in 
        (select dep_id from employee group by dep_id);
複製代碼

 

(2)帶比較運算符的子查詢

複製代碼
#比較運算符:=、!=、>、>=、<、<=、<>
#查詢大於全部人平均年齡的員工名與年齡
mysql> select name,age from employee where age > (select avg(age) from employee);
+---------+------+
| name    | age  |
+---------+------+
| alex    |   48 |
| wupeiqi |   38 |
+---------+------+

#查詢大於部門內平均年齡的員工名、年齡
思路:
      (1)先對員工表(employee)中的人員分組(group by),查詢出dep_id以及平均年齡。
(2)將查出的結果做爲臨時表,再對根據臨時表的dep_id和employee的dep_id做爲篩選條件將employee表和臨時表進行內鏈接。 (3)最後再將employee員工的年齡是大於平均年齡的員工名字和年齡篩選。 mysql> select t1.name,t1.age from employee as t1 inner join (select dep_id,avg(age) as avg_age from employee group by dep_id) as t2 on t1.dep_id = t2.dep_id where t1.age > t2.avg_age; +------+------+ | name | age | +------+------+ | alex | 48 |
複製代碼

 

(3)帶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);
+----+----------+--------+------+--------+
| id | name     | sex    | age  | dep_id |
+----+----------+--------+------+--------+
|  1 | egon     | male   |   18 |    200 |
|  2 | alex     | female |   48 |    201 |
|  3 | wupeiqi  | male   |   38 |    201 |
|  4 | yuanhao  | female |   28 |    202 |
|  5 | nvshen   | male   |   18 |    200 |
|  6 | xiaomage | female |   18 |    204 |
+----+----------+--------+------+--------+
#department表中存在dept_id=205,False
mysql> select * from employee  where exists (select id from department where id=204);
Empty set (0.00 sec)
複製代碼

小練習:

查詢每一個部門最新入職的那位員工

複製代碼
#建立表
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)
;
複製代碼
select * from employee as t1
inner join
(select post,max(hire_date) as new_date from employee group by post) as t2
on t1.post=t2.post
where t1.hire_date=t2.new_date;

14-補充內容:MySQl建立用戶和受權

 

權限管理

咱們知道咱們的最高權限管理者是root用戶,它擁有着最高的權限操做。包括select、update、delete、update、grant等操做。那麼通常狀況在公司以後DBA工程師會建立一個用戶和密碼,讓你去鏈接數據庫的操做,並給當前的用戶設置某個操做的權限(或者全部權限)。那麼這時就須要咱們來簡單瞭解一下:

  • 如何建立用戶和密碼
  • 給當前的用戶受權
  • 移除當前用戶的權限

若是你想建立一個新的用戶,則須要如下操做:


1.進入到mysql數據庫下

mysql> use mysql
Database changed

2.對新用戶增刪改

複製代碼
1.建立用戶:
# 指定ip:192.118.1.1的mjj用戶登陸
create user 'mjj'@'192.118.1.1' identified by '123';
# 指定ip:192.118.1.開頭的mjj用戶登陸
create user 'mjj'@'192.118.1.%' identified by '123';
# 指定任何ip的mjj用戶登陸
create user 'mjj'@'%' identified by '123';

2.刪除用戶
drop user '用戶名'@'IP地址';


3.修改用戶
rename user '用戶名'@'IP地址' to '新用戶名'@'IP地址';

4.修改密碼
set password for '用戶名'@'IP地址'=Password('新密碼');
複製代碼

 

3.對當前的用戶受權管理

複製代碼
#查看權限
show grants for '用戶'@'IP地址'

#受權 mjj用戶僅對db1.t1文件有查詢、插入和更新的操做
grant select ,insert,update on db1.t1 to "mjj"@'%';

# 表示有全部的權限,除了grant這個命令,這個命令是root纔有的。mjj用戶對db1下的t1文件有任意操做
grant all privileges  on db1.t1 to "mjj"@'%';
#mjj用戶對db1數據庫中的文件執行任何操做
grant all privileges  on db1.* to "mjj"@'%';
#mjj用戶對全部數據庫中文件有任何操做
grant all privileges  on *.*  to "mjj"@'%';
 
#取消權限
 
# 取消mjj用戶對db1的t1文件的任意操做
revoke all on db1.t1 from 'mjj'@"%";  

# 取消來自遠程服務器的mjj用戶對數據庫db1的全部表的全部權限

revoke all on db1.* from 'mjj'@"%";  

取消來自遠程服務器的mjj用戶全部數據庫的全部的表的權限 revoke all privileges on *.* from 'mjj'@'%';
複製代碼

ps:在公司中,通常狀況下是DBA工程師來作這些受權工做。給你一個用戶名和密碼,你來鏈接就能夠了。

 

 

4.MySql備份命令行操做

複製代碼
# 備份:數據表結構+數據
mysqdump -u root db1 > db1.sql -p


# 備份:數據表結構
mysqdump -u root -d db1 > db1.sql -p

#導入現有的數據到某個數據庫
#1.先建立一個新的數據庫
create database db10;
# 2.將已有的數據庫文件導入到db10數據庫中
mysqdump -u root -d db10 < db1.sql -p
複製代碼

15-可視化工具Navicat的使用

 

本節重點:

  • 掌握Navicat的基本使用

 

 

# PS:在生產環境中操做MySQL數據庫仍是推薦使用命令行工具mysql,但在咱們本身開發測試時,能夠使用可視化工具Navicat,以圖形界面的形式操做MySQL數據庫

 

 

官網下載:https://www.navicat.com/en/products/navicat-for-mysql

網盤下載:https://pan.baidu.com/s/1bpo5mqj

 

須要掌握基本的操做

複製代碼
掌握:
#1. 測試+連接數據庫
#2. 新建庫
#3. 新建表,新增字段+類型+約束
#4. 設計表:外鍵
#5. 新建查詢
#6. 備份庫/表

#注意:
批量加註釋:ctrl+?鍵
批量去註釋:ctrl+shift+?鍵
複製代碼

 

16-pymysql模塊的使用

 

本節重點:

  • pymysql的下載和使用
  • execute()之sql注入
  • 增、刪、改:conn.commit()
  • 查:fetchone、fetchmany、fetchall

 

1、pymysql的下載和使用

  以前咱們都是經過MySQL自帶的命令行客戶端工具mysql來操做數據庫,那如何在python程序中操做數據庫呢?這就用到了pymysql模塊,該模塊本質就是一個套接字客戶端軟件,使用前須要事先安裝。

(1)pymysql模塊的下載

pip3 install pymysql

(2)pymysql的使用

       數據庫和數據都已存在

 

複製代碼
# 實現:使用Python實現用戶登陸,若是用戶存在則登陸成功(假設該用戶已在數據庫中)


import pymysql
user = input('請輸入用戶名:')

pwd = input('請輸入密碼:')



# 1.鏈接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='', db='db8', charset='utf8')


# 2.建立遊標
cursor = conn.cursor()

#注意%s須要加引號
sql = "select * from userinfo where username='%s' and pwd='%s'" %(user, pwd)
print(sql)

# 3.執行sql語句
cursor.execute(sql)

result=cursor.execute(sql) #執行sql語句,返回sql查詢成功的記錄數目
print(result)


# 關閉鏈接,遊標和鏈接都要關閉
cursor.close()
conn.close()

if result:
    print('登錄成功')
else:
    print('登陸失敗')
複製代碼

 

2、execute()之sql注入

複製代碼
最後那一個空格,在一條sql語句中若是遇到select * from userinfo where username='mjj' -- asadasdas' and pwd='' 則--以後的條件被註釋掉了(注意--後面還有一個空格)

#一、sql注入之:用戶存在,繞過密碼
mjj' -- 任意字符

#二、sql注入之:用戶不存在,繞過用戶與密碼
xxx' or 1=1 -- 任意字符
複製代碼

 

解決方法: 

複製代碼
# 原來是咱們對sql進行字符串拼接
# sql="select * from userinfo where name='%s' and password='%s'" %(username,pwd)
# print(sql)
# result=cursor.execute(sql)

#改寫爲(execute幫咱們作字符串拼接,咱們無需且必定不能再爲%s加引號了)
sql="select * from userinfo where name=%s and password=%s" #!!!注意%s須要去掉引號,由於pymysql會自動爲咱們加上
result=cursor.execute(sql,[user,pwd]) #pymysql模塊自動幫咱們解決sql注入的問題,只要咱們按照pymysql的規矩來。
複製代碼

 

3、增、刪、改:conn.commit()

commit()方法:在數據庫裏增、刪、改的時候,必需要進行提交,不然插入的數據不生效。

複製代碼
import pymysql
username = input('請輸入用戶名:')

pwd = input('請輸入密碼:')



# 1.鏈接
conn = pymysql.connect(host='localhost', port=3306, user='root', password='', db='db8', charset='utf8')


# 2.建立遊標
cursor = conn.cursor()


# 操做
# 增
# sql = "insert into userinfo(username,pwd) values (%s,%s)"

# effect_row = cursor.execute(sql,(username,pwd))
#同時插入多條數據
#cursor.executemany(sql,[('李四','110'),('王五','119')])
# print(effect_row)# # 改 # sql = "update userinfo set username = %s where id = 2" # effect_row = cursor.execute(sql,username) # print(effect_row) # 刪 sql = "delete from userinfo where id = 2" effect_row = cursor.execute(sql) print(effect_row) #必定記得commit conn.commit() # 4.關閉遊標 cursor.close() # 5.關閉鏈接 conn.close()
複製代碼

 

4、查:fetchone、fetchmany、fetchall

fetchone():獲取下一行數據,第一次爲首行;
fetchall():獲取全部行數據源
fetchmany(4):獲取4行數據

查看一下表內容:

複製代碼
mysql> select * from userinfo;
+----+----------+-----+
| id | username | pwd |
+----+----------+-----+
|  1 | mjj      | 123 |
|  3 | 張三     | 110 |
|  4 | 李四     | 119 |
+----+----------+-----+
3 rows in set (0.00 sec)
複製代碼

 

使用fetchone():

複製代碼
import pymysql

# 1.鏈接
conn = pymysql.connect(host='localhost', port=3306, user='root', password='', db='db8', charset='utf8')


# 2.建立遊標
cursor = conn.cursor()

sql = 'select * from userinfo'
cursor.execute(sql)


# 查詢第一行的數據
row = cursor.fetchone()
print(row) # (1, 'mjj', '123')

# 查詢第二行數據
row = cursor.fetchone()
print(row) # (3, '張三', '110')

# 4.關閉遊標
cursor.close()

# 5.關閉鏈接
conn.close()
複製代碼

使用fetchall():

複製代碼
import pymysql

# 1.鏈接
conn = pymysql.connect(host='localhost', port=3306, user='root', password='', db='db8', charset='utf8')


# 2.建立遊標
cursor = conn.cursor()

sql = 'select * from userinfo'
cursor.execute(sql)

# 獲取全部的數據
rows = cursor.fetchall()
print(rows)

# 4.關閉遊標
cursor.close()

# 5.關閉鏈接
conn.close()

#運行結果
((1, 'mjj', '123'), (3, '張三', '110'), (4, '李四', '119'))
複製代碼

默認狀況下,咱們獲取到的返回值是元組,只能看到每行的數據,殊不知道每一列表明的是什麼,這個時候能夠使用如下方式來返回字典,每一行的數據都會生成一個字典:

cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  #在實例化的時候,將屬性cursor設置爲pymysql.cursors.DictCursor

在fetchone示例中,在獲取行數據的時候,能夠理解開始的時候,有一個行指針指着第一行的上方,獲取一行,它就向下移動一行,因此當行指針到最後一行的時候,就不能再獲取到行的內容,因此咱們能夠使用以下方法來移動行指針:

cursor.scroll(1,mode='relative')  # 相對當前位置移動
cursor.scroll(2,mode='absolute') # 相對絕對位置移動
第一個值爲移動的行數,整數爲向下移動,負數爲向上移動,mode指定了是相對當前位置移動,仍是相對於首行移動
複製代碼
# 1.Python實現用戶登陸
# 2.Mysql保存數據

import pymysql

# 1.鏈接
conn = pymysql.connect(host='localhost', port=3306, user='root', password='', db='db8', charset='utf8')


# 2.建立遊標
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

sql = 'select * from userinfo'
cursor.execute(sql)


# 查詢第一行的數據
row = cursor.fetchone()
print(row) # (1, 'mjj', '123')

# 查詢第二行數據
row = cursor.fetchone() # (3, '張三', '110')
print(row)

cursor.scroll(-1,mode='relative') #設置以後,光標相對於當前位置往前移動了一行,因此打印的結果爲第二行的數據
row = cursor.fetchone() 
print(row)

cursor.scroll(0,mode='absolute') #設置以後,光標相對於首行沒有任何變化,因此打印的結果爲第一行數據
row = cursor.fetchone() 
print(row)

# 4.關閉遊標
cursor.close()

# 5.關閉鏈接
conn.close()

#結果以下

{'id': 1, 'username': 'mjj', 'pwd': '123'}
{'id': 3, 'username': '張三', 'pwd': '110'}
{'id': 3, 'username': '張三', 'pwd': '110'}
{'id': 1, 'username': 'mjj', 'pwd': '123'}
複製代碼

fetchmany():

複製代碼
import pymysql

# 1.鏈接
conn = pymysql.connect(host='localhost', port=3306, user='root', password='', db='db8', charset='utf8')


# 2.建立遊標
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

sql = 'select * from userinfo'
cursor.execute(sql)



# 獲取2條數據
rows = cursor.fetchmany(2)
print(rows)

# 4.關閉遊標

# rows = cursor.fetchall()
# print(rows)
cursor.close()

# 5.關閉鏈接
conn.close()

#結果以下:
[{'id': 1, 'username': 'mjj', 'pwd': '123'}, {'id': 3, 'username': '張三', 'pwd': '110'}]
複製代碼
 
 

17-索引

 

1、索引的介紹

數據庫中專門用於幫助用戶快速查找數據的一種數據結構。相似於字典中的目錄,查找字典內容時能夠根據目錄查找到數據的存放位置嗎,而後直接獲取。

二 、索引的做用

約束和加速查找

3、常見的幾種索引:

複製代碼
- 普通索引
- 惟一索引
- 主鍵索引
- 聯合索引(多列)

- 聯合主鍵索引

  - 聯合惟一索引   
   - 聯合普通索引
複製代碼
複製代碼
無索引: 從前日後一條一條查詢
有索引:建立索引的本質,就是建立額外的文件(某種格式存儲,查詢的時候,先去格外的文件找,定好位置,而後再去原始表中直接查詢。可是建立索引越多,會對硬盤也是有損耗。

創建索引的目的:
a.額外的文件保存特殊的數據結構
b.查詢快,可是插入更新刪除依然慢
c.建立索引以後,必須命中索引纔能有效
複製代碼
hash索引和BTree索引
(1)hash類型的索引:查詢單條快,範圍查詢慢
(2)btree類型的索引:b+樹,層數越多,數據量指數級增加(咱們就用它,由於innodb默認支持它)

 

3.1 普通索引

做用:僅有一個加速查找

複製代碼
create table userinfo(
                   nid int not null auto_increment primary key,
                   name varchar(32) not null,
                   email varchar(64) not null,
                   index ix_name(name)
               );
複製代碼
create index 索引的名字 on 表名(列名)
drop index 索引的名字 on 表名
show index from 表名

3.2 惟一索引

 惟一索引有兩個功能:加速查找和惟一約束(可含null)

複製代碼
  create table userinfo(
                   id int not null auto_increment primary key,
                   name varchar(32) not null,
                   email varchar(64) not null,
                   unique  index  ix_name(name)
               );
複製代碼
create unique index 索引名 on 表名(列名)
drop index 索引名 on 表名;

 

3.3 主鍵索引

主鍵索引有兩個功能: 加速查找和惟一約束(不含null)

複製代碼
    create table userinfo(

                   id int not null auto_increment primary key,
                   name varchar(32) not null,
                   email varchar(64) not null,
                   unique  index  ix_name(name)
           )
          or

           create table userinfo(

                   id int not null auto_increment,
                   name varchar(32) not null,
                   email varchar(64) not null,
                   primary key(nid),
                   unique  index  ix_name(name)
         )
複製代碼
alter table 表名 add primary key(列名);
alter table 表名 drop primary key;
alter table 表名  modify  列名 int, drop primary key;

3.4 組合索引

 組合索引是將n個列組合成一個索引

 其應用場景爲:頻繁的同時使用n列來進行查詢,如:where name = 'alex' and email = 'alex@qq.com'。

create index 索引名 on 表名(列名1,列名2);

4、索引名詞

複製代碼
#覆蓋索引:在索引文件中直接獲取數據
        例如:
        select name from userinfo where name = 'alex50000';


#索引合併:把多個單列索引合併成使用
        例如:
        select * from  userinfo where name = 'alex13131' and id = 13131;
複製代碼

6、正確使用索引的狀況

  數據庫表中添加索引後確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,若是以錯誤的方式使用,則即便創建索引也會不奏效。

  使用索引,咱們必須知道:

    (1)建立索引 

    (2)命中索引

    (3)正確使用索引

 準備:

  準備300w條數據

  測試:

複製代碼
     - like '%xx'
            select * from userinfo where name like '%al';
        - 使用函數
            select * from userinfo where reverse(name) = 'alex333';
        - or
            select * from userinfo where id = 1 or email = 'alex122@oldbody';
            特別的:當or條件中有未創建索引的列才失效,如下會走索引
                    select * from userinfo where id = 1 or name = 'alex1222';
                    select * from userinfo where id = 1 or email = 'alex122@oldbody' and name = 'alex112'
        - 類型不一致
            若是列是字符串類型,傳入條件是必須用引號引發來,否則...
            select * from userinfo where name = 999;
        - !=
            select count(*) from userinfo where name != 'alex'
            特別的:若是是主鍵,則仍是會走索引
                select count(*) from userinfo where id != 123
        - >
            select * from userinfo where name > 'alex'
            特別的:若是是主鍵或索引是整數類型,則仍是會走索引
                select * from userinfo where id > 123
                select * from userinfo where num > 123
        - order by
            select email from userinfo order by name desc;
            當根據索引排序時候,選擇的映射若是不是索引,則不走索引
            特別的:若是對主鍵排序,則仍是走索引:
                select * from userinfo order by nid desc;
         
        - 組合索引最左前綴
            若是組合索引爲:(name,email)
            name and email       -- 使用索引
            name                 -- 使用索引
            email                -- 不使用索引
複製代碼

什麼是最左前綴呢?

複製代碼
最左前綴匹配:
        create index ix_name_email on userinfo(name,email);
                 select * from userinfo where name = 'alex';
                 select * from userinfo where name = 'alex' and email='alex@oldBody';

                 select * from userinfo where  email='alex@oldBody';

             若是使用組合索引如上,name和email組合索引以後,查詢
             (1)name和email ---使用索引
             (2)name        ---使用索引
             (3)email       ---不適用索引
              對於同時搜索n個條件時,組合索引的性能好於多個單列索引
        ******組合索引的性能>索引合併的性能*********
複製代碼

7、索引的注意事項

複製代碼
       (1)避免使用select *
       (2)count(1)或count(列) 代替count(*)
       (3)建立表時儘可能使用char代替varchar
       (4)表的字段順序固定長度的字段優先
       (5)組合索引代替多個單列索引(常用多個條件查詢時)
       (6)儘可能使用短索引 (create index ix_title on tb(title(16));特殊的數據類型 text類型)
       (7)使用鏈接(join)來代替子查詢
       (8)連表時注意條件類型需一致
       (9)索引散列(重複少)不適用於建索引,例如:性別不合適
複製代碼

8、執行計劃

  explain + 查詢SQL - 用於顯示SQL執行信息參數,根據參考信息能夠進行SQL優化

  

複製代碼
mysql> explain select * from userinfo;
    +----+-------------+----------+------+---------------+------+---------+------+---------+-------+
    | id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows    | Extra |
    +----+-------------+----------+------+---------------+------+---------+------+---------+-------+
    |  1 | SIMPLE      | userinfo | ALL  | NULL          | NULL | NULL    | NULL | 2973016 | NULL  |
    +----+-------------+----------+------+---------------+------+---------+------+---------+-------+

    mysql> explain select * from (select id,name from userinfo where id <20) as A;
    +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
    | id | select_type | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
    +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
    |  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL    | NULL    | NULL |   19 | NULL        |
    |  2 | DERIVED     | userinfo   | range | PRIMARY       | PRIMARY | 4       | NULL |   19 | Using where |
    +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
    2 rows in set (0.05 sec)
複製代碼

參數說明:

複製代碼
select_type:
                查詢類型
                    SIMPLE          簡單查詢
                    PRIMARY         最外層查詢
                    SUBQUERY        映射爲子查詢
                    DERIVED         子查詢
                    UNION           聯合
                    UNION RESULT    使用聯合的結果
table:
                正在訪問的表名
type:
                查詢時的訪問方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
                ALL             全表掃描,對於數據表從頭至尾找一遍
                                select * from userinfo;
                                特別的:若是有limit限制,則找到以後就不在繼續向下掃描
                                       select * from userinfo where email = 'alex112@oldboy'
                                       select * from userinfo where email = 'alex112@oldboy' limit 1;
                                       雖然上述兩個語句都會進行全表掃描,第二句使用了limit,則找到一個後就再也不繼續掃描。

INDEX :      全索引掃描,對索引從頭至尾找一遍
                                select nid from userinfo;

RANGE:        對索引列進行範圍查找
                                select *  from userinfo where name < 'alex';
                                PS:
                                    between and
                                    in
                                    >   >=  <   <=  操做
                                    注意:!= 和 > 符號


INDEX_MERGE:  合併索引,使用多個單列索引搜索
                                select *  from userinfo where name = 'alex' or nid in (11,22,33);

REF:       根據索引查找一個或多個值
                                select *  from userinfo where name = 'alex112';

EQ_REF:    鏈接時使用primary key 或 unique類型
                                select userinfo2.id,userinfo.name from userinfo2 left join tuserinfo on userinfo2.id = userinfo.id;



CONST:常量
            表最多有一個匹配行,由於僅有一行,在這行的列值可被優化器剩餘部分認爲是常數,const表很快,由於它們只讀取一次。
                 select id from userinfo where id = 2 ;

SYSTEM:系統
             表僅有一行(=系統表)。這是const聯接類型的一個特例。
                 select * from (select id from userinfo where id = 1) as A;


possible_keys:可能使用的索引
key:真實使用的 key_len:  MySQL中使用索引字節長度 rows: mysql估計爲了找到所需的行而要讀取的行數 ------ 只是預估值 extra: 該列包含MySQL解決查詢的詳細信息 「Using index」 此值表示mysql將使用覆蓋索引,以免訪問表。不要把覆蓋索引和index訪問類型弄混了。 「Using where」 這意味着mysql服務器將在存儲引擎檢索行後再進行過濾,許多where條件裏涉及索引中的列,當(而且若是)它讀取索引時,就能被存儲引擎檢驗,所以不是全部帶where子句的查詢都會顯示「Using where」。有時「Using where」的出現就是一個暗示:查詢可受益於不一樣的索引。 「Using temporary」 這意味着mysql在對查詢結果排序時會使用一個臨時表。 「Using filesort」 這意味着mysql會對結果使用一個外部索引排序,而不是按索引次序從表裏讀取行。mysql有兩種文件排序算法,這兩種排序方式均可以在內存或者磁盤上完成,explain不會告訴你mysql將使用哪種文件排序,也不會告訴你排序會在內存裏仍是磁盤上完成。 「Range checked for each record(index map: N)」 這個意味着沒有好用的索引,新的索引將在聯接的每一行上從新估算,N是顯示在possible_keys列中索引的位圖,而且是冗餘的
複製代碼

9、慢日誌記錄

開啓慢查詢日誌,可讓MySQL記錄下查詢超過指定時間的語句,經過定位分析性能的瓶頸,才能更好的優化數據庫系統的性能。

複製代碼
(1) 進入MySql 查詢是否開了慢查詢
         show variables like 'slow_query%';
         參數解釋:
             slow_query_log 慢查詢開啓狀態  OFF 未開啓 ON 爲開啓
        slow_query_log_file 慢查詢日誌存放的位置(這個目錄須要MySQL的運行賬號的可寫權限,通常設置爲MySQL的數據存放目錄)

(2)查看慢查詢超時時間 show variables like 'long%'; ong_query_time 查詢超過多少秒才記錄 默認10秒 (3)開啓慢日誌(1)(是否開啓慢查詢日誌,1表示開啓,0表示關閉。) set global slow_query_log=1; (4)再次查看 show variables like '%slow_query_log%'; (5)開啓慢日誌(2):(推薦) 在my.cnf 文件中 找到[mysqld]下面添加: slow_query_log =1      slow_query_log_file=C:\mysql-5.6.40-winx64\data\localhost-slow.log     long_query_time = 1 參數說明: slow_query_log 慢查詢開啓狀態 1 爲開啓 slow_query_log_file 慢查詢日誌存放的位置 long_query_time 查詢超過多少秒才記錄 默認10秒 修改成1秒
複製代碼

 

10、分頁性能相關方案

先回顧一下,如何取當前表中的前10條記錄,每十條取一次.......

複製代碼
第1頁:
select * from userinfo limit 0,10;
第2頁:
select * from userinfo limit 10,10;
第3頁:
select * from userinfo limit 20,10;
第4頁:
select * from userinfo limit 30,10;
......
第2000010頁
select * from userinfo limit 2000000,10;

PS:會發現,越日後查詢,須要的時間約長,是由於越日後查,全文掃描查詢,會去數據表中掃描查詢。
複製代碼

最優的解決方案

複製代碼
(1)只有上一頁和下一頁
        作一個記錄:記錄當前頁的最大id或最小id
        下一頁:
        select * from userinfo where id>max_id limit 10;

        上一頁:
        select * from userinfo where id<min_id order by id desc limit 10;


  (2) 中間有頁碼的狀況
           select * from userinfo where id in(
               select id from (select * from userinfo where id > pre_max_id limit (cur_max_id-pre_max_id)*10) as A order by A.id desc limit 10
           );    
複製代碼
相關文章
相關標籤/搜索