MySQL入門知識
技術標籤:mysql
MySQL入門
MySQL入門
前言
MySQL介紹
- MySQL是一種開放原始碼的關係型資料庫管理系統(RDBMS),使用最常用的資料庫管理語言–結構化查詢語言(SQL)進行資料庫管理。
- MySQL是開放原始碼的,因此任何人都可以在General Public License的許可下下載並根據個性化的需要對其進行修改。
- MySQL因為其速度、可靠性和適應性而備受關注。MySQL是管理內容最好的選擇。
socket介紹
- 客戶端和服務端是使用socket連線的;
- socket叫套接字,就是計算機和計算機連結的方式。
- 一個計算機使用ip+埠使用某種協議就能和另外一臺機子的ip+埠連結通訊。(TCP / UDP)
- mysql使用的預設埠是3306,一個客戶端隨便使用一個埠,就能連線上服務。
- 伺服器的ip+埠是固定的,客戶端往往是隨機的
一、SQL語句分類
1.1 DCL 資料控制語言
該語言用來定義訪問許可權,理解即可,以後不會多用。
需要記住的是,一個專案建立一個使用者,一個專案對應的資料庫只有一個。這個使用者只能對這個資料庫有許可權,其它資料庫該使用者就操作不了。一般開發中不會開放所有的資料庫許可權。
1.1.1建立使用者
賬戶設定
檢視MySQL初始密碼策略
SHOW VARIABLES LIKE 'validate_password%';
設定密碼強度等級
set global validate_password_policy=LOW;
設定密碼長度
set global validate_password__length=6;
重新整理許可權
FLUSH PRIVILEGES;
(修改許可權後使用)
語法:create user 使用者名稱@‘IP地址’ indentfied by ‘密碼’;
create user [email protected]'%' indentfied by '1234';
%:使用者可以在任意ip地址上登入
1.1.2使用者授權
語法:grant 許可權1,許可權2,……,許可權N on 資料庫.* to 使用者名稱@IP地址;
許可權例如:create
alert
drop
insert
update
delete
select
--這裡的all代表所有許可權
grant all on test.* to crz;
1.1.3撤銷許可權
語法:revoke 許可權1,許可權2,……,許可權N 資料庫.* from 使用者名稱@IP地址;
許可權同授權的許可權
revoke all on test.* from crz;
1.1.4檢視許可權
語法:show grants for 使用者名稱@IP地址;
show grants for crz;
1.1.5刪除使用者
drop user 使用者名稱@IP地址;
1.2 DDL資料定義語言
1.2.1 常見資料型別
1.2.1.1 日期和時間型別
MySQL資料型別 | 含義 |
---|---|
date | 3位元組 日期格式:2014-09-18 |
time | 3位元組 時間格式:08:42:30 |
datetime | 8位元組 日期時間格式:2014-09-18 08:42:30 |
timestamp | 4位元組 時間戳(1970-1-1到現在的毫秒數) |
year | 1位元組 年份 |
1.2.1.2 整型
MySQL資料型別 | 含義(含符號) |
---|---|
tinyint | 1位元組 範圍 -128 ~ 127 |
smallint | 2位元組 範圍 -2^15 ~ 2^15-1 |
mediumint | 3位元組 範圍 -2^23 ~2^23-1 |
int | 4位元組 範圍 -2^31 ~2^31-1 |
bigint | 8位元組 範圍 -2^63 ~2^63-1 |
關鍵字unsigned
可定義成無符號型別,整數部分範圍則會翻翻
1.2.1.3 浮點型
MySQL資料型別 | 含義(含符號) |
---|---|
float(m,d) | 4位元組 單精度 m總位數,d小數位數 |
double(m,d) | 8位元組 雙精度 m總位數,d小數位數 |
decimal(m,d) | 儲存為字串的浮點數 用於金融方面較多 |
MySQL中建立了一個表,有一列為float(5, 3);做了以下試驗:
1.插入123.45678,最後查詢得到的結果為99.999;
2.插入123.456,最後查詢結果為99.999;
3.插入12.34567,最後查詢結果為12.346;
所以,在使用浮點型的時候,還是要注意陷阱的,要以插入資料庫中的實際結果為準。
1.2.1.4 字串
MySQL資料型別 | 含義(含符號) |
---|---|
char(n) | 固定長度 最多255個字元(n:字元個數) |
varchar(n) | 可變長度 最多65535個字元 |
tinytext | 可變長度 最多255個字元 |
text | 可變長度 最多65535個字元 |
mediumtext | 可變長度 最多2^24-1個字元 |
longtext | 可變長度 最多2^32-1個字元 |
1.char(n)和varchar(n)中括號中n代表字元的個數,並不代表位元組個數,所以當使用了中文的時候(UTF8)意味著可以插入m箇中文,但是實際會佔用m*3個位元組。
2.同時char和varchar最大的區別就在於char不管實際value都會佔用n個字元的空間,而varchar只會佔用實際字元應該佔用的空間+1,並且實際空間+1<=n。
3.超過char和varchar的n設定後,字串會被截斷。
4.char的上限為255位元組,varchar的上限65535位元組,text的上限為65535。
5.char在儲存的時候會截斷尾部的空格,varchar和text不會。
6.varchar會使用1-3個位元組來儲存長度,text不會。
1.2.1.5其他型別
-
enum(“member1”,“member2”,……,“member65535”)
實際上就是定義了一個列舉,最多包含65535個成員
-
set(“member1”,“member2”,……,“member64”)
set資料型別指定為一組預定義值中的零個或多個值提供一組方法,最多包含64個成員
1.2.2 對資料庫的操作(增刪改查)
- 檢視所有的資料庫:
SHOW DATABASES;
- 使用/切換資料庫:
USE 資料庫名;
- 建立資料庫並指定編碼:
CREATE DATABASE test DEFAULT CHARACTER SET utf-8;
- 刪除資料庫:
DROP DATABASE 資料庫名;
1.2.3 對錶結構的操作
1.2.3.1 建立表語法
CREATE TABLE 表名(
欄位名1 資料型別 欄位寬度 約束條件,
欄位名2 資料型別 欄位寬度 約束條件,
欄位名3 資料型別 欄位寬度 約束條件,
……
);
建表約束條件有:
主鍵:PRIMARY KEY
一個表只能有一個主鍵,自】}帶不能為空和唯一約束
自增:AUTO_INCREMENT
不能為空:NOT NULL
外來鍵約束:FOREIGN KEY
唯一約束,取值不允許重複:UNIQUE
……
CREATE TABLE student(
id INT(10) PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(20) NOT NULL,
age tinyint unsigned,
grade CHAR(1)
);
檢視當前資料庫中所有表: SHOW TABLES
;
查看錶結構: DESC 表名
;
刪除表: DROP table 表名
;
1.2.3.2 修改表
- 新增列
/*新增address和hobby列 型別為varchar*/
ALTER TABLE student add(address VARCHAR(20),hobby VARCHAR(20));
- 修改型別
/*將hobby列 的型別修改為int*/
ALTER TABLE student MODIFY hobby int;
- 修改列名稱和型別
/*將hobby列名稱修改為newHobby 型別變為varchar*/
ALTER TABLE student CHANGE hobby newHobby VERCHAR(15);
- 刪除列
ALTER TABLE student DROP newHobby;
- 修改表名
ALTER TABLE student RENAME TO stu;
1.3 DML資料操作語言
1.3.1 插入資料
insert into stu (id,name,age,gander,address) values(1,'張三',18,'男','中國');
insert int stu values(1,'張三',18,'男','中國'),(2,'李四',19,'女','美國')
說明:
- 在資料庫中所有的字串型別,必須使用單引號。
- (列名1,列名2,列名3)可省略,表示按照表中的順序插入。但不建議採取這種寫法,因為降低了
程式的可讀性。
1.3.2 修改資料
upadte stu set age=23,name='王五' where id = 1;
修改(某行或者多行記錄的)列的指定值: update 表名 set 列名1=列值1 where 列名2=列值2 or 列名3=列值3;
運算子:=、!=、<>、<、>、>=、<=、between...and、in(…)、is null、not、or、and
,其中in(…)的用法表示集合。例如: update 表名 set 列名1=列值1 where 列名2=列值2 or 列名2=列值22
用in(…)寫成update 表名 set 列名1=列值1 where 列名2 in(列值2,列值3)
1.3.3 刪除資料
不加任何條件會將該表所有內容刪除
delete from stu where id = 1;
1.4 DQL資料查詢語言
1.4.1 單表查詢
1.4.1.1 簡單查詢
select * from stu;
select distinct name,age from stu where id = 1;
select * from stu where id in (1,3,5);
select * from stu where id >1 and id <5;
distinct
去重
1.4.1.2 模糊查詢
select * from stu where name like '%a';
select * from stu where name like 'a%';
select * from stu where name like '%a%';
1.4.1.3 排序
select * from stu order by age; (預設正序)
select * from stu order by age asc; (正序)
select * from stu order by age desc; (倒序)
1.4.1.4 聚合函式
select max(age) from stu;
select min(age) from stu;
select avg(age) from stu;
select sum(age) from stu;
select count(age) from stu;
1.4.1.5 分組查詢
分組後只能使用聚合函式和分的組
select gander,avg(age) from stu group by gander;
select gander,avg(age) from stu group by gander having gander ='男';
having
對分組的進行條件判斷
1.4.1.6 Limit子句(mysql獨有)
/*一個引數n,從最開始查詢n行資料*/
select id,name,age,gander from stu limit 3;
/*兩個引數a,b 從a行開始(不含)向下查詢b行資料*/
select id,name,age,gander from stu limit 1,3;
1.4.1.7 Union和Union all
Union
關鍵字會把兩個表中重複的資料過濾,再顯示兩個表的所有內容
Union all
顯示兩個表的所有內容
select id,name from teacher
union
select id,name from teacher2;
select id,name from teacher
union all
select id,name from teacher2;
1.4.2 多表查詢
笛卡爾積:簡單來說就是兩個集合相乘的結果,集合A和集合B任意兩個元素結合在一起。
select * from table_a,table_b
查詢出來的就是笛卡爾積
需要篩選結果
select *
from table_a as a,table_b b
where a_id = b_id
1.4.2.1 內連線
select *
from table_a as a inner join table_b b
on a_id = b_id
兩個表中有null的資料就不顯示
1.4.2.2 外連線
左連線:
select *
from table_a as a left join table_b b
on a_id = b_id
左表所有資料都要,右表中與左表沒有關聯的不要
右連線:
select *
from table_a as a right join table_b b
on a_id = b_id
右表所有資料都要,左表中與右表沒有關聯的不要
1.4.2.3 全連線
MySQL本身不支援全連線,可通過左連線+右連線的方式實現
select *
from table_a as a left join table_b b
on a_id = b_id
union
select *
from table_a as a right join table_b b
on a_id = b_id
oracle預設支援全連線:
select *
from table_a as a full join table_b b
on a_id = b_id
1.4.3 子查詢
1.4.3.1 where型子查詢
將查詢結果當條件
例:查詢一門學科分數大於90的學生資訊
select * from stu where id in
(select s_id from scores where score >90);
1.4.3.2 from型子查詢
查詢的結果在結構上當成表
例:查詢數學成績前五的學生,正序排列
select * from
(select s.id,s.name,e.score,c.name from
stu s left join scores e
on s.id = e.s_id left join course c on e,c_id = c.id
where c.name = '數學' order by e.score desc limit 5) t order by
t.score
1.4.4 其他函式
1.4.4.1 數值型函式
ceiling(x)
返回大於x的最小整數,向上取整
floor(x)
返回小於x的最大整數,向下取整
round(x,y)
返回引數x的四捨五入的有y位小數的值
truncate(x,y)
返回數字x截短y位小數的結果
PI()
返回π的值,圓周率
rand()
返回0到1內的隨機值
1.4.4.2 字串函式
length(s)
計算字串長度,返回字串的位元組長度
concat(s1,s2,……,sn)
合併字串函式,返回結尾為連線引數產生的字串
lower(str)
轉換為小寫
upper(str)
轉換為大寫
left(str,x)
返回字串最左邊x個字元
right(str,x)
返回字串最右邊x個字元
trim(str)
刪除字串左右的空格
replace(str,char_a,char_b)
替換字串函式,返回替換後的新字串 replace(name,‘白’,‘黑’)
substring(str,x,y)
擷取字串從x位開始擷取y個
reverse(str)
返回逆序字串結果
1.4.4.3 日期函式
current_date()
/ curdate()
返回當前系統日期
current_time()
/ curtime()
返回當前系統時間
now()
/ sysdate()
返回當前系統的日期和時間值
unix_timestamp()
獲取Unix時間戳函式
month()
獲取指定日期中的月份
monthname()
獲取指定日期中月份的英文名稱
dayname()
獲取指定日期對應的星期幾的英文名稱
dayofweek()
獲取指定日期對應的一週的索引位置值
week()
獲取指定日期在一年中的週數
dayofyear()
獲取指定日期是一年中第幾天
dayofmonth()
獲取指定日期是一月中第幾天
year()
獲取年份
date_add()
/ adddate()
向日期新增指定的時間間隔
date_sub()
/ subdate()
向日期減去指定的時間間隔
addtime()
時間加法運算,在原始時間上新增指定時間
subtime()
時間減法運算,在原始時間上減去指定時間
datediff()
獲取兩個日期的時間間隔
date_formate
格式化指定日期,根據引數返回固定格式的值
當使用表示式計算後,不能直接使用別名
SELECT DATE_ADD('2020-11-11 11:11:11',INTERVAL 1 SECOND) AS c1,DATE_ADD("2020-11-11 11:11:11",INTERVAL '1:1' MINUTE_SECOND) AS c2
SELECT DATEDIFF("2020-11-11 11:11:11",'2020-11-10 10:10:10') AS COL
SELECT DATE_FORMATE(NOW(),'%p %Y年%m月%d %h-%i-%s')
1.4.4.4 流程控制函式
if(test,t,f)
如果test是真,返回t,否則返回f
ifnull(arg1,arg2)
如果arg1不是空,返回arg1,否則返回arg2
nullif(arg1,arg2)
如果arg1=arg2返回null,否則返回arg1
case when[test1] then [result1]...else[default] end
如果testN是真,返回resultN,否則返回default
case [test] when[val1] then [result1]...else[default] end
如果test和valN相等,則返回resultN,否則返回default
行轉列案例:
select
user_name "姓名",
max(case course when '語文' then score else -1 end) "語文",
max(case course when '數學' then score else -1 end) "數學",
max(case course when '英語' then score else -1 end) "英語",
from student
group by user_name
1.4.4.5 雜湊加密
雜湊演算法 不可逆
select md5('123') from dual
二、SQL檢視
檢視的作用就是為了保護資料的安全性而只把部分資料展示出來供他人使用
和表的區別:
1.表直接將資料存在磁碟上,檢視是將sql語句儲存到磁碟上
2.檢視是建立在表的基礎上,表儲存資料庫中的資料,而檢視顯示已經存在表中資料的外觀
3.表是靜態的,檢視是動態的,表中的資料傳送改變,建立在表基礎上的檢視跟著改變
4.一般情況下,檢視不能改變表中的資料
5.刪除視圖表不受影響,而刪除表檢視將不再起作用
6.檢視本身沒有資料,只儲存了sql語句
2.1 建立檢視
基本格式:create view 檢視名(列名1,列名2...) as select語句
create view stu_view(id,name) as
select * from stu
2.2 顯示檢視
基本格式:
select * from stu_view
2.3 刪除檢視
基本格式:
drop view stu_view
三、資料庫設計
3.1 三正規化
設計只是一種思想一種理念,安裝規範來設計資料庫有好處,但不一定要嚴格遵守,三正規化能極大減少資料冗餘,但是相對編寫sql而言是增加了難度,所以所有好的設計都是要權衡利弊的。
設計資料庫表的時候所依據的三個規範:
第一正規化:要有主鍵,並且每一個欄位原子性不可再分
第二正規化:要求所有非主鍵欄位完全依賴主鍵,不能產生部分依賴
第三正規化:所有非主鍵欄位和主鍵欄位之間不能產生傳遞依賴
3.1.1 第一正規化
資料庫中不能出現重複記錄,每個欄位是原子性不能再分
不符合例項:(聯絡方式應分成郵箱和手機號碼)
編號 | 學生姓名 | 聯絡方式 |
---|---|---|
1001 | 張三 | [email protected] 13891234567 |
1002 | 李四 | [email protected] 13659874598 |
1003 | 王五 | [email protected] 12598745698 |
3.1.2 第二正規化
第二正規化是建立在第一正規化基礎上的,要求所有非主鍵欄位完全依賴主鍵,不能產生部分依賴
不符合例項:
其中學號和課程編號為聯合主鍵
學號 | 性別 | 學生姓名 | 課程編號 | 課程名稱 | 教室 | 成績 |
---|---|---|---|---|---|---|
1001 | 男 | 張三 | 2001 | java | 3004 | 89 |
1002 | 男 | 李四 | 2002 | mysql | 3003 | 88 |
1003 | 女 | 王五 | 2003 | html | 3005 | 90 |
1001 | 男 | 張三 | 2002 | mysql | 3003 | 77 |
1001 | 男 | 張三 | 2003 | html | 3005 | 89 |
1003 | 女 | 王五 | 2001 | java | 3004 | 90 |
以上雖然確定了主鍵,但是會出現大量冗餘
性別和學生姓名依賴於學號,但是課程編號等資訊和學號毫無關係,這種情況應分成三個表,一張學生資訊表,一張課程資訊表,一張成績表
3.1.3 第三正規化
第三正規化是建立在第二正規化基礎上的,非主鍵欄位和主鍵欄位之間不能產生傳遞依賴
不符合例項:
其中學號是主鍵
學號 | 學生姓名 | 專業編號 | 專業名稱 |
---|---|---|---|
1001 | 張三 | 2001 | 計算機 |
1002 | 李四 | 2002 | 自動化 |
1003 | 王五 | 2001 | 計算機 |
什麼是傳遞依賴?
專業編號依賴於學號,專業名稱依賴於專業編號,但是專業名稱和學生實際上沒多少直接關係。
一般表中重複的資料只能是外來鍵編號
3.2 常見表關係
3.2.1 一對一
一張表和另一張表的關係是一對一,不常見,如果是這種關係,通常會多張表合併為一張表
舉例:學生資訊表可以分為基本資訊表和詳細資訊表(不暴露部分私密資訊)
3.2.2 一對多
舉例:第三正規化例子;商城訂單狀態(一個訂單對應下單,付款,發貨,送貨,收貨狀態)等
兩張表,外來鍵建在多的一方
3.2.3 多對多
舉例:第二正規化例子