史上最全的MySQL基礎知識清單

  • 本教程來源:我學習MySQL語法時所做的筆記
  • 補充:在cmd、PowerShell中進入MySQL命令行的一般命令是mysql -u root -p,然後輸入密碼即可
  • 今日,將筆記整理歸納後發出來供大家學習使用

相關文章推薦:


目錄一:概述

數據庫:

  • 本質上是文件(爲了讓數據永久保存)
  • 有很多寫好的流程(可以幫我們操作文件:讀、寫…)
  • 我們想要讀取和保存的數據,給數據庫發送指令,讓它幫我們操作文件的讀寫(省去了我們操作I/O的過程)

數據庫可以分爲兩類:

  • 關係型數據庫(以表格的形式記錄數據和關係),用的指令是SQL(Structured Query Language,結構化查詢語言)
  • 非關係型數據庫(以key-value形式只記錄數據本身),用的指令是NOSQL(Not Only SQL)

SQL:

(Structured Query Language,結構化查詢語言)

歷經幾乎20年,在1989年,由國際標準化組織(ISO)頒佈SQL正式國際標準
現在很多的數據庫廠商還在遵循沿用着這套規範(SQL89標準)

各家的數據庫:
學習任何一家的數據庫產品,其實都差不多一樣(大同小異,學習了一個數據庫後,再學習其它數據庫就簡單的多了)

  • IBM
    • DB2數據庫
  • Microsoft
    • SQLServer(和windows系統融合的很好,但是在其他系統上兼容性就差了挺多)
    • Access(Office辦公軟件中的很小的一個數據庫,不多見)
  • Oracle
    • Oracle(商用的)
    • MySQL(開源免費的,最早是一家瑞典的公司的,先被SUN併購,後SUN被Oracle併購,現在很流行)

MySQL:

  • 操作數據庫的語言規範:SQL(關鍵字不區分大小寫,但是建議寫大寫,風格統一)
  1. DDL(Data Definition Language,數據定義語言)

    • 創建、刪除、修改數據庫中的對象(表格,用戶,索引,視圖,存儲過程,觸發器)
    • 三個關鍵字:創建create、刪除drop、修改alter
    • 請看目錄二
  2. DML(Data Manipulation Language,數據操作語言)

    • 操作數據庫表格中的具體數據
    • 寫數據:新增insert、刪除delete、修改update
    • 讀數據:查詢select
    • 請看目錄三
  3. DCL(Data Control Language,數據控制語言)

    • 控制用戶權限
    • (賦予)grant 權限,權限 to 用戶
    • (回收)revoke 權限,權限 from 用戶
    • 請看目錄四
  4. TPL(Transaction Process Language,事務處理語言)

    • 可以理解爲多線程併發訪問同一個文件資源,帶來的安全問題
    • begin Transaction
    • 操作
    • commit提交
    • rollback回滾
    • save point A 保存還原點
    • 這部分內容,在使用編程語言操作數據庫的時候用的非常頻繁,而且用起來很簡單,本文暫不講

目錄二: 數據庫、表格的創建、修改和刪除(DDL)

1. 先在MySQL數據庫中創建一個database

create database 數據庫名;

建議大家起名字最好遵循一定的規範----英文(要見名知義)

注意:在很多編程語言中(比如:Python、Java),英文字母區分大小寫
而MySQL英文字母不區分大小寫(關鍵字、表格名字、列名字…)
在這裏插入圖片描述
顯然,test 數據庫創建成功了

2. 在我們自己的database裏面創建table的格式

(暫時,創建的表格中列的屬性只有數據類型和長度)

create table(
	列名  數據類型(長度),
	列名  數據類型(長度),
	列名  數據類型(長度)	
)

這個寫法其實和Java中domain實體類的寫法非常相似

3. 數據庫中的數據類型

按存儲數據的方式來分類,分爲三類:

  • 數值型
    • 整數:tinyint1字節,smallint2字節,mediumint3字節,int或者integer4字節,bigint8字節
    • 小數:float4字節,double8字節;decimal,numeric(前兩個的底層的計數方式更加精確,可以表示更多的數字;後兩者和前兩者差不多,但是則相對固定了些)
  • 字符串
    • 數據庫裏所有的字符串類型都是用單引號,不是雙引號)
    • char字符串,定義之後長度是固定的
    • varchar可變長字符串,定義之後長度是根據存儲信息發生改變的,這個用的更多
    • binary字符串形式存儲二進制,varbinary是可變二進制
    • blob二進制大文本,text正常字符大文本
  • 日期/時間
    • date日期
    • time時間
    • datetime日期&時間
    • 日期和時間,在定義的時候都不需要長度,因爲他們的格式是固定的
    • 還有,date只有年月日,time只有時分秒,datetime有年月日時分秒
    • timestamp時間戳:時間表示的信息比上面三個更加精細,顯示的時間除了年月日時分秒外,還有毫秒、時區

4. 在自己的datebase中創建一個表格

[例] 先選擇 test 數據庫

use test;

在這裏插入圖片描述
[例] 然後,在 test 數據庫中創建一個 student 表格

create table student(
	sid int(11),
	sname varchar(20),
	ssex varchar(4)
);

5. 通過DDL語句修改表格的結構

  • 表格名字錯誤
  • 修改原有的列(列名錯誤,列類型不對、列長度不夠)
  • 新增一個列
  • 刪除一個列

修改表名:

alter table 表名 rename [to] 新名字;

[例] 修改 student 的表名爲 zgh

alter table student rename to zgh;

[例] to可以省略:

alter table zgh rename student;

修改原有的列(列名錯誤,列類型不對、列長度不夠):

alter table 表名 change 原列名 新列名 新類型 新長度;

[例] 將 student 表的 sid 列 改名爲 snum,並將類型改爲 char(11)

alter table student change sid snum char(11);

新增一個列:

alter table 表名 add 新列名 新類型 新長度;

[例] 在 student 表中新增一個列,列名爲 sbirthday,類型爲 date

alter table student add sbirthday date;

刪除原有的列:

alter table 表名 drop 原列名;

[例] 將 student 表的 sbirthday 列 刪除

alter table student drop sbirthday;

6. 刪除表格

drop table 表名;

[例] 刪除 student 表

drop table student;

7. 刪除數據庫

drop database 數據庫名;

[例] 將 test 數據庫刪除

drop database test;

目錄三:表格的增刪改查(DML)

  • 操作 的是 表格 中的 數據信息
  • 表格:
    行:記錄
    列:屬性
  • 寫入信息(數據庫中的信息發生了真實的改變)
    新增insert,刪除delete,修改update
  • 讀取信息(數據庫中的信息沒有發生改變)
    查詢select

學習DDL語句之前,
[例] 先創建一個數據庫 test,選擇這個數據庫,再在這個 test 中創建一個表格 student

create database test;

use test;

create table student(
	sid int(11),
	sname varchar(20),
	sage int(4),
	ssex varchar(4),
	saddress varchar(30)
);

然後,開始學習了:

1. 新增記錄

insert into 表名(列名,列名,列名,...)values(,,,...);

注意:列名和值是對應的(數據類型,數據的長度),還有列名可以根據需求,有不同的數量

[例]

insert into student(sid, sname) values(1, 'zgh');

在這裏插入圖片描述

2. 查詢記錄

select 列名,列名,列名,... from 表名

[例]

select sid, sname, sage, ssex, saddress from student;

可以看出,數據庫的表中存儲的元素都是引用類型的

如果是要查詢的信息包含所有的屬性(即:列)
還有一種寫法更加的簡單,不過它在底層方面上,比上面的的寫法的查詢速度要慢

select * from 表名;

[例]

select * from student;

要在表中新增一行信息,包含所有的屬性(即:列),有一個更加簡單的寫法

  • 省略掉列名不寫
  • 不過values裏面的值要和表格的屬性的順序對應好,類型,長度也要一一對應
insert into 表名 values(,,,...);

[例]

insert into student values(2, 'hq', 18, 'male', 'whxyedu');

一次性增加多條記錄:

insert into 表名 values(,,,...),(,,,...);

[例]

insert into student 
values(3, 'licw', 3, 'male', 'whxyedu'),
(4, 'xy', 38, 'male', 'whxyedu');

不能存儲中文的解決辦法

3. 存儲中文信息

此命令可以查詢數據庫的默認字符集:

 select schema_name,default_character_set_name 
 from information_schema.schemata 
 where schema_name = 'test';

我記得MySQL5.7的默認默認字符集是不支持存儲中文的,
前幾天,我使用zip壓縮包(免安裝方式)重新安裝了MySQL8.0,發現在命令行中可以直接存儲中文,研究之後發現:

  • 在MySQL5.7中,數據庫的默認字符集是latinl(不支持中文)
  • 而在MySQL8.0中,數據庫的默認字符集變爲了utf8mb4(兼容utf8,是支持中文的)

3 - 擴展:字符集設置

  • 如果你在使用MySQL的過程中,發現不能存儲中文字符,可以看一下這部分的內容

這部分內容是我很久以前的筆記,當時是使用installer安裝MySQL5.7,並且只選擇安裝MySQL Community Server,安裝完成後有兩個命令行客戶端給我使用,然後我學習時的截圖都是基於這兩個客戶端

其中一個客戶端是Unicode字符,但是使用此命令行客戶端直接輸入中文字符是不可以的,還要進行一些設置

原因是,MySQL8.0之前的某些版本,數據庫的默認字符集可能不支持存儲中文

  • MySQL有四個默認的database,information_schema是其中一個:
  • 方法一:設置database的默認字符集爲utf8,從此之後,使MySQL創建的新數據庫支持存儲中文
    但是基於默認字符集創建的(原有的)數據庫,其字符集不能修改了,若要使它存儲中文,只能刪掉咯
  • 方法二:不修改MySQL的全局字符集,在創建數據庫的時候可以單獨設置這個數據庫的字符
 create database test default character set = 'utf8';
  • 方法三:如果不想讓創建的數據庫中的所有表存儲中文,只單純的某一張表格需要中文,創建表格的時候設置字符集
create table 表名(
	列名 類型 長度,
	列名 類型 長度
)character set utf8;

還可以同時設置排序規則:

create table 表名(
	列名 類型 長度,
	列名 類型 長度
)character set utf8 collate utf8_general_ci;

排序規則有兩個:

  • utf8_general_ci默認,性能比較高,可能不太精確
  • utf8_unicode_ci性能比較低,擴展性好

4. 刪除記錄

如果不寫where,表中全部記錄將被全部刪掉:

delete from 表名
where 條件;

[例]

delete from student;

5. 修改記錄

update 表名 set=,=[where 條件];

[例] 先在 student 表中增加兩行數據,再進行修改操作

insert into student values(1, 'zgh', 18, 'male', '地府'),
(2, '索兒呀', 18, 'male', '冥府');

select * from student;

update student set sname = 'zhangguohao666', ssex = 'boy';

select * from student;

可以很明顯的看到,由於沒有對錶中的值進行篩選,默認選擇了 student 表中所有的內容,所有內容的 sname 和 ssex 都被改了

6. 顯示錶格的狀態

顯示student表格的狀態:

show table status 
from test 
like 'student';

在這裏插入圖片描述
這就是命令行客戶端的侷限性了,因爲查詢的內容太多,就如上圖這樣重合了

目錄四:用戶的創建、刪除與權限配置(DCL)

數據控制語言

  1. 控制用戶的權限
  2. grant賦予
  3. revoke回收

常用的MySQL權限

數據庫/數據表/數據列權限:

  • Create建立新的數據庫或數據表
  • Alter修改已存在的數據表(例如增加/刪除列)
  • Drop刪除數據庫或數據表
  • Insert增加表的記錄
  • Delete刪除表的記錄
  • Update修改表中已存在的記錄
  • Select顯示/搜索表的記錄
  • ==================================
  • References允許創建外鍵
  • Index建立或刪除索引
  • Create View允許創建視圖
  • Create Routine允許創建存儲過程和包
  • Execute允許執行存儲過程和包
  • Trigger允許操作觸發器
  • Create User允許更改、創建、刪除、重命名用戶和收回所有權限

全局管理MySQL用戶權限:

  • Grant Option允許向其他用戶授予或移除權限
  • Show View允許執行show create view語句
  • Show Databases允許賬戶執行show databases來查看數據庫
  • Lock Table允許執行lock tables來鎖定表格
  • File在MySQL上讀寫文件
  • Process顯示或殺死屬於其它用戶的服務線程
  • Reload重載訪問控制表,刷新日誌等
  • ShutDown關閉MySQl服務

特別的權限:

  • All允許做任何事(和root一樣)

  • Usage只允許登錄,其它什麼也不允許做

  • 如果一開始是通過MySQL命令行客戶端來學習MySQL,那麼本目錄內容需要在終端中進行,因爲MySQL命令行客戶端一打開就是以 root 身份登錄

  • 如果你會使用終端來玩MySQL,請自行跳過本目錄中擴展一、擴展二的內容

擴展一:Windows中配置環境變量(如果配置過,請自行跳過)

使用 installer 安裝MySQL5.7,並且只選擇安裝MySQL Community Server,安裝完成後有兩個命令行客戶端給我使用,然後我學習時的截圖都是基於這兩個客戶端

  • 使用這兩個客戶端,打開時默認以 root 身份進入

  • 如果要換身份登錄,我們需要先進行MySQL的環境變量配置,再使用windows的終端(cmd、PowelShell)

  • MySQL的默認安裝路徑:C:\Program Files\MySQL\MySQL Server 版本號

  • 需要配置的環境變量(比如說我安裝的是MySQL5.7):C:\Program Files\MySQL\MySQL Server 5.7\bin

右鍵此電腦 > 屬性 > 高級系統設置 > 高級 > 環境變量
在這裏插入圖片描述
上面的和下面都有一個 path ,這就是需要設置的環境變量了

選中其中一個,點擊編輯

連續點擊三次確定!!!直至所有打開的窗口都關閉了

好了,環境變量配置完成

擴展二:Windows中使用cmd或者PowerShell玩MySQL

鍵盤同時按下 win + r,打開運行窗口,在輸入框中輸入cmd 或者 PowerShell

點擊確定,windows的控制檯就打開了

也是很熟悉的黑框框

在 終端中 進入MySQL

mysql -u 用戶名 -p

回車後,發現這和我原來玩的MySQL命令行窗口一樣了

輸入密碼後,盤符變成了mysql

在 終端 中退出MySQL

輸入 exit; 或者 鍵盤同時按下 Ctrl + z ,然後回車

我現在的身份是SYSDBA管理員(即MySQL中的root賬號,管理員可以操作其他普通用戶的權限)

查看用戶信息

先用root賬號看一下MySQL中四個默認database
在這裏插入圖片描述
其中mysql數據庫中的user表格記錄了MySQL的用戶信息
在這裏插入圖片描述
user表格中有很多屬性

我們現在只需要查詢三個屬性

  • user用戶名
  • hostIP地址,默認是localhost,即本機
  • 在MySQL的5.5版本之前,密碼是存儲在password列中;我的版本是5.7,用戶密碼被md5加密了,放在了另一個列authentication_string
    在這裏插入圖片描述

創建新用戶

create user '用戶名'@'IP' identified by '密碼';

在這裏插入圖片描述
然而一個新創建的用戶,只有一個默認的權限usage,只允許登錄,不允許做其他事情

控制用戶的權限

1. 給新的用戶賦予權限

查看用戶權限

可以通過一個語句查看用戶的權限

show grants for '用戶名'@'IP';

在這裏插入圖片描述

給用戶賦予權限

grant 權限 on 數據庫.表格 to '用戶名'@'IP';

在這裏插入圖片描述
(補充*.*代表所有數據庫的所有表格)

賦予權限之後,如果發現沒起作用,最好做一個刷新

flush privileges;

2. 註銷 用新用戶登錄

註銷

exit;

在這裏插入圖片描述
然後
在這裏插入圖片描述
因爲zgh用戶的權限和root一樣
在這裏插入圖片描述

3. 回收用戶的權限

revoke 權限 on 數據庫.表格 from '用戶名'@'IP';

重新用root賬號登錄,
然後
在這裏插入圖片描述
(補充,usage權限是一定會保留的)

再進入zgh賬號看一下:

在這裏插入圖片描述

4. 修改用戶密碼(DML)

update user set authentication_string = password('密碼') 
where user = '用戶名'@'IP';

在這裏插入圖片描述
如果嘗試重新登錄改了密碼的用戶,發現改了的密碼不好用
那就返回root賬戶刷新一下數據庫

flush privileges;

5. 刪除創建的用戶(DDL)

使用DDL語句刪除用戶是最好的,因爲它刪除的更加乾淨

drop user '用戶名'@'IP';

在這裏插入圖片描述

目錄五:列的約束

  1. 主鍵約束
  2. 外鍵約束
  3. 唯一約束
  4. 非空約束
  5. 檢查約束

前情提要:

先創建一個數據庫cons
(因爲數據庫名字長度有限制,cons是constraint的縮寫)
在這裏插入圖片描述
然後在cons數據庫中
在這裏插入圖片描述
創建一張表:
myclass表

create table myclass(
classid int(4),
cname varchar(20),
loc varchar(20)
);

然後設置一下myclass表的字符集

alter table myclass character set utf8; 

我先在myclass表中添加一行元素

在這裏插入圖片描述
如果我在myclass表中添加一行相同的元素,會有衝突嗎?
在這裏插入圖片描述
顯然,相同的元素可以添加進去

但是,有時候對於存儲的元素是不允許重複的

爲了方便下面的學習,我把myclass的元素清空
在這裏插入圖片描述

一:主鍵約束

  • primary key
  • 在每一個表格中,只能有一個列被設置爲主鍵約束
  • 主鍵通常用來標記表格中數據的唯一存在
  • 主鍵約束要求當前的列,不能爲null值
  • 主鍵約束要求當前的列,值是唯一存在的,不能重複

添加約束,到底是改變表結構還是操作數據呢?
很顯然,添加約束時,表中是沒有元素的
所以要用DDL語句

添加主鍵約束的標準寫法

alter table 表名 add  constraint 約束名字 約束類型();

在這裏插入圖片描述

查看錶的約束

然後,怎麼查看錶是否有約束呢?
有兩個辦法:

第一個辦法:

desc 表名;

desc是description的縮寫

在這裏插入圖片描述
第二個辦法:

show keys from 表名;

在這裏插入圖片描述

添加主鍵約束的簡寫

可以看出,兩種查看約束的方式都與約束名無關
所以添加約束的語句可以簡寫爲:

alter table 表名 add 約束類型();

主鍵的自增操作

添加主鍵之後,若想要主鍵自增,可以做相應的設計

alter table 表名 modify 列名 類型(長度) autu_increment;

或者

alter table 表名 change 原列名 新列名 類型(長度) autu_increment;

changemodify兩個關鍵字的不同在於,change關鍵字還可以更改列名

這個語句,沒有做起始值的說明,主鍵列會從1開始

在這裏插入圖片描述

再加一條記錄:

在這裏插入圖片描述

設置主鍵自增的起始值:

alter table 表名 auto_increment = 起始值;

在這裏插入圖片描述

去掉主鍵自增:

重新設置一下列就好:
在這裏插入圖片描述

刪除主鍵約束

刪除主鍵:

alter table 表名 drop primary key;

在這裏插入圖片描述
刪除主鍵約束後,有一個小細節要注意一下:
在這裏插入圖片描述
刪除主鍵約束後,不重複的特性取消了,但是非空特性還在

所以,在刪除主鍵約束後,還要非空特性改回去:

alter table 表名 modify 列名 類型(長度) null;

在這裏插入圖片描述

二:唯一約束

  • unique keykey可以不寫
  • 可以爲表格中的某一個列添加唯一約束
  • 唯一約束表示的是列的值,不能重複,但是可以爲空
  • 在表格中可以有多個列存在唯一約束

先把myclass表清空
在這裏插入圖片描述

先在myclass表中添加一行元素

在這裏插入圖片描述
添加唯一約束的標準約束

然後給myclass表的loc屬性添加唯一約束
例如:
標準的:

alter table myclass add constraint uk_myclass unique key(loc);

簡寫的:

alter table myclass add unique key(loc);
//約束名是默認的列名

唯一約束不止一個,需要起約束名,方便通過約束名刪除唯一約束
在這裏插入圖片描述

在這裏插入圖片描述

刪除唯一約束

寫法有一些特殊:

alter table myclass drop index 約束名;

在這裏插入圖片描述

添加唯一約束的簡寫

alter table myclass add unique key(loc);
//約束名是默認的列名

在這裏插入圖片描述

三:非空約束

  • 在表格的某一個列上添加非空元素
  • 當前的列的值不能爲null

先把myclass表中的唯一約束刪掉
在這裏插入圖片描述

設置非空約束

非空約束,要通過modify或者change來改變表的結構

alter table 表名 modify 列名 類型(長度) not null;

在這裏插入圖片描述
去掉非空約束

alter table 表名 modify 列名 類型(長度) null;

在這裏插入圖片描述

設置非空約束的另一種寫法:

alter table 表名 change 原列名 新列名 類型(長度) not null;

在這裏插入圖片描述
刪除非空約束的另一種寫法:

alter table 表名 change 原列名 新列名 類型(長度) null;

在這裏插入圖片描述
四:默認值

當myclass表的cname屬性有非空約束,假如在開發中某一時間不知道填寫什麼

可以使用default關鍵字來避免這個問題
如果你不填寫,就是這個默認值

在這裏插入圖片描述
然後我在myclass表中添加一行元素:

在這裏插入圖片描述

五:外鍵約束

  • foreign key
  • 表格中可以有多個列被設置爲外鍵約束
  • 當前列的值可以爲空,可以重複
  • 當前列的值不能隨便填寫,值要去另一張表格中尋找
  • 外鍵是當前列的值受另外一張表格某一個列的影響
  • 另外一張表的列的值是唯一的(唯一約束或主鍵約束)

表之間的關聯,玩的就是外鍵約束

玩外鍵約束之前,先創建一個表格student

create table student(
sid int(4),
sname varchar(20),
ssex varchar(10),
classid int(4)
);

alter table student character set utf8;

然後在student表格中添加元素

insert into student values(1,'ahri','female',1);
insert into student values(2,'lux','female',1);
insert into student values(3,'garen','male',2);
insert into student values(4,'akali','female',2);

student表:
在這裏插入圖片描述

還要涉及另外一張表myclass:
在這裏插入圖片描述

添加外鍵約束的標準寫法

alter table 表名字 add constraint fk_當前表_關聯表 foreign key() references 另一個表();

不過在添加外鍵約束時,要先使另一張表的列的值是唯一的(非空約束,主鍵約束)

在這裏插入圖片描述
在這裏插入圖片描述
MUL指的是multiple(多樣,並聯)

刪除外鍵約束

alter table 表名字 drop foreign key 約束名字;

在這裏插入圖片描述
注意:通過上述語句其實已經將這張表格的外鍵約束刪掉了

但是,外鍵約束涉及到兩張表格,爲了保證另外一張表的記錄不丟失,會自動在當前的表格內添加一個新的key

show create table 表名;
//這個語句可以看key

在這裏插入圖片描述

我們需要再次手動將這個生成的key刪掉,外鍵約束才真的刪乾淨

alter table 表名 drop key 外鍵約束名;

在這裏插入圖片描述

添加外鍵約束的簡寫

alter table 表名字 add foreign key() references 另一個表();

那麼,外鍵約束名是什麼呢?
只能以通過show create table 表名;查的外鍵約束名爲準(不是默認的列名!)

在這裏插入圖片描述
所以簡寫的方式,使刪掉外鍵時挺麻煩的(儘量不要這麼使用)
在這裏插入圖片描述
但是key的名字確是默認的列名
在這裏插入圖片描述
在這裏插入圖片描述

六:檢查約束

  • 列在存值的時候做一個細緻的檢查,值的範圍是否合理

首先,看一下student表的結構:

在這裏插入圖片描述
然後,我添加一個屬性
在這裏插入圖片描述

現在,我要對sage的值進行更新(但是更新的值要合理,就可以用檢查約束來保證數據的合理性)

添加檢查約束

alter table 表名 add constraint 約束名 check(值的範圍)

在這裏插入圖片描述
然後發現檢查約束的語句執行了,但是在MySQL中不好使(被MySQL的底層屏蔽了)
在這裏插入圖片描述

不過檢查約束,在Oracle數據庫中是好使的

目錄六: 關鍵字:any,some ,all ,union,union all

學習這幾個關鍵字之前的準備
student表
在這裏插入圖片描述
再創建一個myclass表

create table myclass(
classid int(3),
classname varchar(20),
classloc varchar(20)
);

在myclass表中插入元素

insert into myclass values(1,'classone','zhuhe');
insert into myclass values(2,'classtwo','xihe');
insert into myclass values(3,'classthree','wuhan');
insert into myclass values(4,'classfour','hubei');

myclass表:
在這裏插入圖片描述


  • 先說一下in關鍵字
    滿足查詢子集中的一個即可
    in 後面跟的語句可以是常量固定值,也可以是嵌套查詢
  • 如下三個關鍵字anysomeall使用起來與in類似,查詢是否滿足後面的子集中的條件
    但是這三個關鍵字的後面只能跟嵌套查詢,而且要配合運算符來使用

一:any,some

any和some的用法完全一樣

>any

大於最小值
在這裏插入圖片描述

<any

小於最大值
在這裏插入圖片描述

=any

等價於in關鍵字
在這裏插入圖片描述

=any

在這裏插入圖片描述
二:all

all滿足查詢子集的全部纔可以

<all

在這裏插入圖片描述

>all

在這裏插入圖片描述

=all

在這裏插入圖片描述

!=all

not in關鍵字等價
在這裏插入圖片描述

三:union,union all

對集合的操作有:

  1. 並集union
  2. 交集(Oracle數據庫有這個語句intersect
  3. 差集(Oracle數據庫有這個語句minus

並集union,將兩個表合併在一起

有兩個表,
student
在這裏插入圖片描述
teacher

create table teacher(
tid int(4),
tname varchar(20),
tsex varchar(10),
tbirthday date
);
insert into teacher values(1,'zgh1','male','1999-08-05');
insert into teacher values(2,'zgh2','male','1998-08-17');
insert into teacher values(3,'zgh3','male','1998-08-16');

在這裏插入圖片描述

並集的語句是這麼寫的,舉個例子:

select sid,sname,ssex from student union select tid,tname,tsex from teacher;

在這裏插入圖片描述

把兩張表的寫的順序調換一下:

select tid,tname,tsex from teacher union select sid,sname,ssex from student;

在這裏插入圖片描述
很顯然,並集後的表的列名取決於語句中寫的前一張表,當然,也可以取別名

合併的要求:

  1. 要求前後兩個查詢子集的列數是一致的
  2. 拼接後顯示的列名是前一個子集默認的列名
  3. 類型和長度是沒有要求的,可以不一樣
    在這裏插入圖片描述
  4. 注意unionunion all的區別:對於重複元素的處理

我再創建一個新的newteacher表格

create table newteacher as select * from teacher;
//這個語句可以通過後面一張表創建一個完全一樣的表格

在這裏插入圖片描述

再對newteacher表箇中的數據改動兩行,保留一行和teacher表中一樣的元素

update newteacher set tid = 10 where tname = 'zgh2';

update newteacher set tid = 11 where tname = 'zgh3';

在這裏插入圖片描述

union會在拼接的時候,又做一個處理,看一看有沒有重複,有就把重複的元素拒絕加入(所以性能較慢)
union all將兩張查詢的子集直接合並,不做任何處理,性能比較快

在這裏插入圖片描述

當數據沒有重複時,建議用union all來進行合併處理

目錄七: 函數的使用

用student表來學習函數的使用
在這裏插入圖片描述

函數直接放置在語句中,
可以放置在:

select  函數()
from 表格
where 函數() >

按照函數功能進行劃分

  • 比較函數
  • 數學函數(數值函數)
    abs(值)絕對值
    floor(值)向下取整
    mod(值,值)取餘數
    pow(值,值)求次方
    round(值)四捨五入
  • 日期和時間
    now()
    year(date)
    mouth(date)
    day(date)
    week(date)
  • 控制流程函數(轉換函數)
    if(expr1,expr2,expr3)三目運算符
    ifnull(值,v)是空值顯示v,如果非空就正常顯示
  • 字符串函數
    大部分和java中的String類的方法差不多
  • 分組函數(聚合函數
    最最最重要的

常用函數:

一:日期和時間函數
在這裏插入圖片描述
爲什麼會出現7個記錄,因爲student表格有七列

SQL有一個關鍵字distinct可以去重複
(注意,distinct修飾的是每一行記錄的全部選擇的屬性(列))
在這裏插入圖片描述
然後MySQL中有一個獨有的寫法,可以這樣寫:
在這裏插入圖片描述

在這裏插入圖片描述

二:流程控制函數

if(expr1,expr2,expr3)三目運算符
在這裏插入圖片描述
ifnull(值,v)是空值顯示v,如果非空就正常顯示

先把student表中的某行的某個值修改爲null

在這裏插入圖片描述
然後:
在這裏插入圖片描述

三:字符串函數

字符串函數			String類
length()			length()
concat()			concat()
substr()			substring()
instr()				indexOf()
replace()			replace()
upper()				toUpperCase()
lower()				toLowerCase()
ltrim(),rtrim()		trim()
lpad()
rpad()
reverse()			StringBuffer,StringBuilder中的reverse()

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

lpad()
sname的長度不夠10則在左邊補*,補到10個爲止
在這裏插入圖片描述

在這裏插入圖片描述

四:聚合函數+分組條件

  • count()個數
  • max()最大值
  • min()最小值
  • avg()平均數
  • sum()

舉一個例子:

查詢student表中語文成績最高的
在這裏插入圖片描述

目錄八: 條件篩選、排序、分組、嵌套

一:條件篩選

在找尋數據的時候做一個篩選

條件篩選where

  1. 除了insert語句以外的其它三個語句(update,select,delete)都可以進行篩選
    where是一個關鍵字,拼接在語句的基本結構之後
  2. 篩選用來篩選符合條件的記錄行數
    並不是控制顯示的列
  3. 按照某一列或者某一些條件進行篩選
    列,滿足一定的條件
  4. where後面具體怎麼用,連接什麼東西

在學習條件篩選之前,先創建一個database,再在裏面創建一個table,用來記錄學生信息
在這裏插入圖片描述
在這裏插入圖片描述

補充:float(m,n)總共可以存儲m位數字,小數點之後有n位;m的取值範圍是1-65,n的取值範圍是0-30;如果不寫參數,默認效果:m是10,n是0

然後在student表中加入這些數據

insert into student values(1,'zhangsan','male',18,'2000-01-01',10,60,80,1,100);
insert into student values(2,'lisi','female',18,'2000-12-5',61,59,35,1,0);
insert into student values(3,'wangwu','male',18,'2000-11-11',89,33,77,2,100);
insert into student values(4,'zhaoliu','female',18,'2000-05-01',60,60,60,3,60);
insert into student values(5,'qianqi','male',18,'2000-03-03',70,80,100,3,90);
insert into student values(6,'wangba','female',18,'2000-02-02',100,70,10,2,10);
insert into student values(7,'zgh','male',18,'1999-08-05',100,100,100,2,100);

student表格:
在這裏插入圖片描述

where後面具體怎麼用,連接什麼東西

  • 比較運算符> >= < <= != =
select *

選擇全部屬性(列)
在這裏插入圖片描述
選擇部分的屬性(列)
在這裏插入圖片描述

  • 算術運算符+ - * /

在這裏插入圖片描述

  • 邏輯運算符and or not
    優先級,做左往右,優先級降低

在這裏插入圖片描述

數據庫底層做的事情

  1. 解析SQL語句
  2. 從表格中把全部數據都讀取出來,放在數據庫中緩存,用集合list
  3. 將list集合做一個遍歷循環,每一次拿到一行記錄,然後和where語句做比較

假設我們的表格有7條記錄

如果只寫一個where條件
執行七次循環就可以出來了

但如果and連接了不止一個where條件
先按照第一個條件篩選(7個循環,假設有6個滿足)
然後按照第二個條件篩選(6個循環)

and語句的執行效率很低,and語句儘量少用;但如果在語句中寫了and,儘量將條件苛刻的寫在前面,提高執行效率,
or也是如此

所以SQL提供了許多可以替代and和or的執行效率更高的語句
如:

between

between 左邊界值 and 右邊界值

查詢的範圍:[ 左邊界值,右邊界值]
在這裏插入圖片描述
補充一個

not between 左邊界值 and 右邊界值

在這裏插入圖片描述
in

in

在這裏插入圖片描述
補充一個:

not in

在這裏插入圖片描述
like(模糊查詢)

like 
  • %用來代替0-n個字符
  • _用來代替1個字符

先把表的內容看一下:
在這裏插入圖片描述
進行模糊查詢

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

刪除delete,修改update語句中的條件篩選的玩法和查詢select語句一樣,不多說了

二:排序

  • 連接在查詢的語句之後的
  • order by 列
  • 升序排列asc,默認就是升序的,可以省略不寫
  • 降序排列desc

在這裏插入圖片描述
排序語句和條件篩選語句一起寫:
在這裏插入圖片描述

聯合查詢
當前面的排序語句相等時,再按照次級排序語句排序
在這裏插入圖片描述

三:分組

group by

如果SQL語句中一旦搭配了分組條件,能展示的信息只有兩種

  1. 分組條件
  2. 分組函數

先看一下studnet表:

在這裏插入圖片描述

  1. 查詢student表中每一個班級有多少個同學

在這裏插入圖片描述

  1. 查詢student表中男,女同學的人數

在這裏插入圖片描述

  1. 查詢student表中每個年齡層段有多少人

在這裏插入圖片描述

  1. 查詢student表中每一個班級的語文平均分

在這裏插入圖片描述

  1. 查詢student表中每一個班級的語文平均分,並且按照平均分升序排序
    在這裏插入圖片描述

四:對於分組條件+分組函數的查詢

  1. 查詢student表中所有男同學,他們都在哪個班級

先進行where,再進行分組group by

在這裏插入圖片描述

  1. 查詢student表中語文平均成績高於90分的班級

先分組,再對平均成績條件篩選
但是wheregroup by的優先級別高

所以SQL給我們提供了一個關鍵字having,它的用法和where差不多,但是它的優先級比group by

所以,一般group byhaving搭配使用

在這裏插入圖片描述

  • 在查詢之前需要先考慮,到底是先分組,還是先篩選條件
    如果是先篩選,後分組where+group by
    如果是先分組,再篩選group by+having
  • 在查詢的時候一旦分組了,行數會減少
    想要展示的信息的個數需要與分組條件的個數一致

五:嵌套

在一個完整的SQL語句中,嵌套了另一個完整的SQl語句(當涉及到多個不同的表)

嵌套可以將一個查詢的結果當作條件,來再次查詢(這種用法很常用)

  1. 查詢student表中語文成績最高分的同學

在這裏插入圖片描述
嵌套可以將一個查詢的結果當作一個表格(需要給這張表格取別名),在這張的表格的基礎上再次查詢

  1. 查詢student表中男同學的sname,ssex,sage,classid

在這裏插入圖片描述

目錄九: 表格之間的聯合查詢

就是將多張表的數據沒有任何條件的組合在一起,形成一張完整的大的表格,然後在這張大的表格上進行篩選

  • 等值連接(等值連接之前,需要先進行廣義笛卡爾積)
  • 外連接
  • 內連接(自連接)

一:廣義笛卡爾積

廣義笛卡爾積將兩張表格或多張表格,進行無條件的拼接

先看兩張表:
emp表(存儲僱員信息):
在這裏插入圖片描述

dept表(存儲部門信息):

在這裏插入圖片描述

然後,把這兩個表的數據沒有任何條件的組合在一起,形成一張完整的大的表格(廣義笛卡爾積)

列數爲兩張表的列數相加
行數爲兩張表的行數相乘

在這裏插入圖片描述
廣義笛卡爾積,簡單粗暴,兩張表的全部數據都組合起來了

但是很多數據是沒有意義的,
比如僱員smith和四個部門的組合的數據中,只有部門20的那一行組合的信息纔有意義

二:等值連接

在廣義笛卡爾積的基礎上,進行條件篩選
因爲一般篩選都是通過=來進行的,所以才叫等值連接
(注意,不一定必須是=,其它的判斷語句也行)
比如:
在這裏插入圖片描述

然後:
因爲emp表格中我在定義和插入數據時有一些錯誤,我把這些錯誤更正後的emp表:
在這裏插入圖片描述
然後,我創建一個表salgrade(記錄工資的等級),然後插入一些數據和一些約束:

create table salgrade(
grade int(4),
losal int(6),
hisal int(6)
);

alter table salgrade add primary key(grade);

insert into salgrade values(1,700,1200);
insert into salgrade values(2,1201,1400);
insert into salgrade values(3,1401,2000);
insert into salgrade values(4,2001,3000);
insert into salgrade values(5,3001,9999);

salgrade表:

在這裏插入圖片描述

然後,把emp表個salgrade表進行等值連接:
在這裏插入圖片描述

查詢一下每個工資等級有多少個僱員
在這裏插入圖片描述

其實,等值連接的性能不太好

因爲先要進行笛卡爾積,然後進行條件篩選

爲了提高查詢的性能,SQL提供了兩種查詢辦法(外連接和內連接,性能更高)

三:外連接

select * from A left/right [outer] join B on 條件;

補充:[]內的語句代表可有可無,/代表或者
看到left就是左外連接,right是右外連接

on關鍵字和where的作用差不多,但是where的優先級比from的低;而on的優先級比from的優先級高

  1. 兩張表格A和B,取決於誰的數據在左邊顯示
    A表格先出現,A左邊顯示
    B表格先出現,B左邊顯示
  2. leftright來控制以哪一個表格的數據作爲基準
    作爲基準的表格的數據必須全部顯示出來
    非基準的表格按照on條件與之拼接,條件滿足的正常顯示,不滿足條件的則爲null

拿emp表和dept表做演示
因爲兩張表的deptno的屬性都可以對應上,

我先在emp表中插入一個特殊的數據:

emp表:
在這裏插入圖片描述
dept表:
在這裏插入圖片描述
左外連接

在這裏插入圖片描述

右外連接

在這裏插入圖片描述

四:內連接

select * from A inner join B on 條件;

在這裏插入圖片描述
可以看出,內連接的查詢結構和等值連接的查詢結果是一樣的(但是,內連接的性能更加棒)

還有一個比較特殊的玩法(在當前表格中再次查詢當前表格的信息):
先看一下emp表:
在這裏插入圖片描述

在這裏插入圖片描述
(補充,其實等值連接也可以這玩)

目錄十: 行列互換、分頁查詢、設計範式

一:行列互換

先創建一個表warehouse(存儲倉庫信息):

create table warehouse(
wname varchar(8),
winventory int(8),
wmonth varchar(8)
)character set utf8;

insert into warehouse values
('A',100,'一月份'),('B',1000,'一月份'),('C',10,'一月份'),
('A',200,'二月份'),('B',2000,'二月份'),('C',20,'二月份'),
('A',300,'三月份'),('B',3000,'三月份'),('C',30,'三月份');

在這裏插入圖片描述

若要使表格像這麼顯示:
在這裏插入圖片描述
首先,要使用group by關鍵字進行條件分組

通過倉庫名稱分組:

  1. A組 三個值 每一個月份對應一個庫存
  2. B組 三個值 每一個月份對應一個庫存
  3. C組 三個值 每一個月份對應一個庫存

分組後,顯示的屬性的值要分情況討論,要使用if()三目運算函數

select  
	wname 倉庫名,
	max(if(wmonth = '一月份',winventory,0)) 一月份,
	max(if(wmonth = '二月份',winventory,0)) 二月份,
	max(if(wmonth = '三月份',winventory,0)) 三月份 
from warehouse 
group by wname;	

因爲,一旦使用了group by分組條件
select可以顯示的列只有兩種(分組條件和分組函數)
(注意:select中用到的分組函數可以是max(),也可以是min()…因爲反正只有一個嘛)
在這裏插入圖片描述
二:分頁查詢,limit

emp表格:
在這裏插入圖片描述

emp表格有14行記錄,假如每一頁只能顯示5行記錄,必然會產生分頁

怎麼做呢?

MySQL中有一個關鍵字limit a,b(a代表想要顯示的起始行索引,索引行是從0開始的;b代表想要顯示的行數)

顯示前五行:

select * 
from emp 
order by sal desc 
limit 0,5;

在這裏插入圖片描述

顯示中間五行:

select * 
from emp 
order by sal desc 
limit 5,5;

在這裏插入圖片描述
顯示最後面的:

select * 
from emp 
order by sal desc 
limit 10,5;

在這裏插入圖片描述
(補充:如果行數不夠,就算了)

Oracle數據庫的查詢就比較麻煩了,它要使用一個僞列rownum還有levelrowid

SQL Server要使用top

三:數據庫設計的範式Normal Form

  • 設計數據庫時,遵循的不同規範,這些規範統稱範式
  • 範式的目的是爲了減少數據庫的冗餘,管理表格的時候變得容易(修改、刪除)
  • 但是查詢的時候可能涉及到表格聯合的問題(性能會降低一點

有這麼一張表格(用來記錄學校裏面不同樓宇項目的一些信息)
在這裏插入圖片描述

上表存在很多問題

  1. 數據有大量冗餘
  2. 所以修改起來比較麻煩

1FN

  • 數據庫中每一張表格的每一個列都是不可分割的(數據的原子性)
    通俗的解釋:行列交叉點的單元格內只存儲一個數據
  • 每一個表格中必須有主鍵約束(快速查詢某一行記錄)

(上表不遵循1FN,原子性可以保證,
但表格內沒有主鍵----設定聯合主鍵:項目編號+工程師編號)

2FN

  • 在滿足1FN的前提下,
  • 不允許出現部分依賴性(非主鍵列不能受主鍵列或主鍵列的一部分影響)

(如果產生了非主鍵列受到主鍵或主鍵的部分影響----將數據拆開存儲在兩張表中)

看上表,當設定(聯合主鍵:項目編號+工程師編號)之後,雖然滿足了1FN
但是,工程師名稱和工程師編號有關係,這個沒問題
但是工程師名稱和項目編號本應該沒有關係的,但是由於聯合主鍵的緣故,工程師名稱受到了項目編的影響,不滿足2FN

改動:
將上表拆成兩個表格
工程表格
在這裏插入圖片描述
(拆開之後會發現,工程表格沒有了主鍵,這個先放在這裏,往後面看)
工程師表格
在這裏插入圖片描述

3FN

  • 在滿足前兩個範式的前提下,
  • 不允許出現傳遞依賴性(非主鍵列不能受到非主鍵列或非主鍵的一部分影響)

(如果非主鍵列受到了非主鍵列或非主鍵的一部分影響----將沒有關係的數據拆開單獨存放在表格中)

在工程表格中,
小時工資受到了職稱的影響,不滿足第三範式

改動:
將工程表格拆成兩個表格

項目表格
在這裏插入圖片描述
(主鍵是:項目編號)

職稱表格
在這裏插入圖片描述
(給職稱表格加一個屬性:職稱編號,來作爲主鍵)

再看一下
工程師表格
在這裏插入圖片描述
(主鍵是:工程師編號)


雖然滿足了3FN
但是,在實際應用中,用戶需要對這三張表格做聯合查詢

所以,三張表格之間的關係也要處理一下:

  • 工程師和項目是多對多的關係,所以需要構造另一張表(項目_工程師中間表

在這裏插入圖片描述
(項目編號和工程師編號是這張表的聯合主鍵;
項目編號是項目表的外鍵;
工程師編號是工程師表格的外鍵)

  • 工程師和職稱是多對一的關係

所以工程師表格需要添加一個職稱表格的外鍵
在這裏插入圖片描述



最終成果:
項目表格
在這裏插入圖片描述

職稱表格
在這裏插入圖片描述

項目_工程師中間表
在這裏插入圖片描述

工程師表格
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章