1. 程式人生 > >MYSQL快速入門(2)

MYSQL快速入門(2)

前言:本篇部落格是接著MYSQL快速入門(1)的繼續學習。
MYSQL快速入門(1):https://blog.csdn.net/hansionz/article/details/84111426

MYSQL快速入門

一.MYSQL的資料型別

1.資料型別分類

在這裡插入圖片描述

2.數值型別

2.1 BIT的使用

bit[(M)]位欄位型別。M表示每個值的位數,範圍從1到64。如果M被忽略,預設為1

create table p1( id int, tel bit(8));
insert into p1 values(10,10
); select * from p1;

sql語句執行結果如下:
在這裡插入圖片描述
tel欄位的值並沒有顯示,bit欄位在顯示時,是按照ASCII碼對應的值顯示。下圖,當插入65時,對應的字元為A
在這裡插入圖片描述

如果我們有這樣的值,只存放0或1,只存在兩種狀態,這時可以定義bit(1)。這樣可以節省空間

create table p2(gender bit(1));
insert into p2 values(0);
insert into p2 values(1);
insert into p2 values(2); -- 不能插入2,因為只有1位,插入2會越界

2.2 整型型別的使用

在這裡插入圖片描述
對於上邊的幾個型別,我們應該注意的是它們所能使用的範圍,注意越界問題

crate table p3(id tinyint); -128-127
insert into p3 values(1);
insert into p3 values(128);-- 會報錯,越界插入

MySQL中,整型可以指定是有符號的和無符號的,預設是有符號的。 可以通過UNSIGNED來說明某個欄位是無符號的。

create table p4(num tinyint unsigned); -- 0-255
insert into p4 values(-1);-- 越界插入
insert into p4 values(255);

其他的整型型別和TINYINT型別的使用完全一樣,只要使用時注意範圍即可。

2.3 UNSINGED的使用

int的表示範圍是-2147483648 ~ 2147483647int unsigned的範圍是0 ~ 4294967295。所以我們在很多時候需要使用unsigned來表示非負數,比如年齡等。然而在實際使用中,unsigned可能會帶來一些負面的影響

create table p5(a int unsigned, b int unsigned);
insert into p5 values(1,2);
select a - b from p5; 
-- 預料的應該是-1,但其實不然,-1減去2是正的最大值,-1(FFFFFFFF)4294967295(FFFFFFFF)的補碼相同,將這個數按照無符號數輸出,結果是4294967295而不是-1

要獲得正確的結果,我們想要設定引數對SQL_ MODE

 set sql_mode='NO_UNSIGNED_SUBTRACTION';

這樣結果才是我們想要的結果。
在這裡插入圖片描述
實際使用中,儘量不使用unsigned,因為可能帶來一些意想不到的效果。另外,對於int型別可能存放不下的資料,int unsigned同樣可能存放不下,與其如此,還不如設計時,將int型別提升為bigint型別。

2.4 小數型別的使用

2.4.1 float的使用

float[(m, d)][unsigned]:m指定顯示長度,d指定小數位數,佔用空間4個位元組。

float(4,2)表示的範圍是-99.99 ~ 99.99MySQL在儲存值時會進行四捨五入

create table p6(id int, sal float(4,2));
insert into p6 values(1,-99.99);
insert into p6 values(1,-99.991); -- 先進行四捨五入,然後在插入
insert into p6 values(1,99.991);
insert into p6 values(1,99.999); -- 報警告,但依然會捨棄超出部分

執行結果: show warnings 可以打印出所有的警告資訊。
在這裡插入圖片描述

如果定義的是float(4,2) unsigned這時,因為把它指定為無符號的數,範圍是 0 ~ 99.99

create table p7(id int, sal float(4,2) unsigned);
insert into p7 values(1,-0.1);-- 報警告
insert into p7 values(1,-0); -- yes
insert into p7 values(1,99.99); -- yes

打印出警告資訊:
在這裡插入圖片描述

2.4.2 decimal的使用

decimal(m, d) [unsigned]:定點數m指定長度,d表示小數點的位數

decimal整數最大位數m為65。支援小數最大位數d是30。如果d被省略,預設為0。如果m被省略,預設 是10

-- float和decimal很相似,但是他們有區別,表示的精度不同,float表示的精度大約是7decimal(5,2) 表示的範圍是 -999.99 ~ 999.99 
decimal(5,2) unsigned 表示的範圍 0 ~ 999.99
create table p8(sal1 float(10,8),sal2 decimal(10,8))
insert into t8 values(12.12345678,11.12345678);

下圖為插入記錄的結果:由此結果可以看出decimal的精度要比float的精度高,如果要儲存更高精度的數,推薦使用decimal
在這裡插入圖片描述

2.5 字串

2.5.1 char和varchar

  • char(L): 固定長度字串,L是可以儲存的長度,單位為字元,大長度值可以為255

  • varchar(L): 可變長度字串,L表示字元長度,最大長度65535個位元組
    注:L是表示字元的個數,而不是位元組的個數。

# 測試char
-- char(2) 表示可以存放兩個字元,可以是字母或漢字,但是不能超過2個。最多隻能是255
create table p8(id int, name char(2));
insert into p8 values(1,'ab'); -- ab
insert into p8 values(1,'張三'); -- 張三
-- 超出最大長度,則會建表失敗
create table tt10(id int ,name char(256)); 

-- 測試varchar
create table p9(id int, name varchar(6)) -- 表示可以存放6個字元
insert into p9 values(100, '我愛你,中國'); -- 插入成功

2.5.2 varchar的len

varchar的len到底是多長呢?varchar(L),L代表的是字元的個數,但是總的最大位元組數是65535varchar的len其實是與 編碼有關的。

  • varchar長度可以指定為0到65535之間的,但是有1 - 3個位元組用於記錄資料大小,所以說有效位元組數是65532
  • 當表的編碼是utf8時,varchar(n)n大值是65532/3=21844。(因為utf8中,一個漢字佔用3個位元組)
  • 如果編碼是gbkvarchar(n)。n大是65532/2=32766(因為gbk中,一個漢字佔用2位元組)。

當我們以utf8編碼建立一個varchar(21845)的表會失敗,但是建立varchar(21844)的表就會建立成功。
在這裡插入圖片描述

注意:我們在建立表的時候並不是只建立有一個varchar欄位,還可能存在其他欄位,如果存在其他欄位,那麼varchar的最大長度並不是21844,而是要減去其他型別所佔的長度,因為mysql規定,表中一行的記錄不能超過65535

在這裡插入圖片描述

上邊的例子中,varchar的最大長度應該是21844 - 4(int) = 21840,所以第一次建表報錯,第二次建表成功。

在一些使用場景下,應該如何選擇charvarchar:

  • 如果資料確定長度都一樣,就使用定長,比如身份證,手機號,md5加密的密碼。(定長的磁碟空間比較浪費,但是效率高)
  • 如果資料長度有變化,就使用變長,比如名字,地址,但是你要保證長的能存的進去。(變長的磁碟空間比較節省,但是效率低)

2.6 日期和時間型別

MYSQL中常用的日期和時間型別有:

  • datatime:日期時間格式為yyyy-mm-dd HH:MM:SS,表示範圍從1000-9999,佔用8個位元組
  • date:日期格式為yyyy-mm-dd,佔用3個位元組
  • timestamp:時間戳,,從1970年開始的 yyyy-mm-dd HH:MM:SS格式和datetime完全一致,佔用4位元組
create table birthday(t1 date, t2 datetime, t3 timestamp)
-- 新增資料時,時間戳自動補上當前時間 
-- 更新資料,時間戳會更新成當前時間 
insert into birthday(t1,t2) values('1997-3-6','1997-3-6 12:00:00')

在這裡插入圖片描述

當更新表中的資料時,時間戳會自動更新為當前的時間:

update birthday set t2 = '2008-3-6';

在這裡插入圖片描述

2.6 列舉和set型別

2.6.1 列舉型別

列舉,其實就是“單選”型別,對應介面表單中的“單選項”的資料值。該設定只是提供了若干個選項的值,最終在一個單元格中,實際只儲存了其中一個值;而且,處於效率考慮,這些值實際儲存的是“數字”,因為這些選項,每個選項值,一次對應如下數字:1,2,3,....多65535個。列舉型別其實和C中的列舉型別是一個概念。

enum('選項1','選項2','選項3',...); 

當我們新增列舉值時,也可以直接新增編號。

2.6.2 set型別

set型別正好和enum相對。set就是“多選”型別,對應於介面或表單的“多選項”的資料值。該設定只是提供了若干個選項的值,最終在一個單元格中,可儲存了任何其中的多個值。基於效率考慮, 這些實際儲存的是“數字”,因為這些選項,每個選項值,一次對應如下數字:1,2,4,8,16,32,....最多64個;[偶數]

set('選項值1','選項值2','選項值3', ...); 

當我們新增set型別的值時,也可以直接新增編號。

2.6.3 set和enum例子

有一個調查表votes,需要調查人的喜好,比如登山,游泳,籃球,武術(多選)。 性別為男和女(單選)

-- 建表
create table votes(
	name varchar(32),
	hobby set('登山','游泳','籃球','武術'),
	gender enum('男','女')
)charset=utf8;
-- 插入幾條記錄
insert into votes values('張三', '登山,武術', '男'); 
-- 列舉型別可以直接插入編號
insert into votes values('李四','登山,武術',2);
insert into votes values('王五','游泳',2);

select * from votes where hobby='登山'; 

以下為插入結果:
在這裡插入圖片描述

  • 找出所有愛好有登山的人
-- 這樣做查不出來
select * from votes where hobby='登山'; 
-- find_in_set(sub,str_list);  如果sub在str_list中,則返回下標,如果不在,返回0  str_list用逗號分隔的字串。 

-- 這樣做ok
select * from votes where find_in_set('登山', hobby); 
  • find_in_set的用法如下:
    在這裡插入圖片描述

二.表的約束

真正約束表中欄位的是資料型別,但是資料型別約束很單一,需要有一些額外的約束,更好的保證資料的合法性,從業務邏輯角度保證資料的正確性比如有一個欄位是id,要求是唯一的。

1.空屬性

1.1 空屬性概念

空屬性存在兩個值:null(預設的)not null(不為空)。 資料庫預設欄位基本都是欄位為空,但是實際開發時,儘可能保證欄位不為空,因為資料為空沒辦法參與運算

select null; -- null
select 1+null; -- 空值沒法參加運算,運算結果依然為空

下邊為運算結果:
在這裡插入圖片描述

1.2 空屬性約束的應用

假設要建立一個班級表,該表包含班級名和班級所在的教室。如果班級沒有名字,你知道你在哪個班級;如果教室名字可以為空,就不知道在哪上課

create table class(
	class_name varchar(20) not null,
	class_room varchar(20) not null
)charset=utf8;

使用desc class查看錶的結構:
在這裡插入圖片描述

當我們在插入資料,沒有給出class_name或者class_room時,就會報錯,因為我們已經設定約束該欄位不能為空:

insert into class values('1603','203'); -- ok
insert into class values('1604'); -- 報錯

下邊為執行結果:
在這裡插入圖片描述

2.預設值

預設值是指某一種資料會經常性的出現某個具體的值,可以在一開始就指定好,在需要真實資料的時候,使用者可以選擇性的使用預設值。(可以理解為C++中的預設引數)

-- 建立一個帶有預設值約束的學生表
create table stu(
	name varchar(30) not null,
	age tinyint unsigned default 0,
	gender char(2) default '男'
)charset=utf8;

使用desc stu查看錶的結構:
在這裡插入圖片描述

預設值的生效:資料在插入的時候不給該欄位賦值,就使用預設值

insert into stu values('張三',17,'女');
-- 年齡和性別欄位使用預設值
insert into stu values('李四');

以下為執行結果:
在這裡插入圖片描述
注:set和enum型別欄位不能設定預設值。

3.列描述

列描述:comment,沒有實際含義,專門用來描述欄位,會根據表建立語句儲存,用來給程式設計師來進行理解。可以理解為C語言中的註釋資訊

建立一個person表,給每一個欄位加上列描述:

create table person(
	name varchar(20) not null comment '姓名',
	age tinyint unsigned default 0 comment '年齡',
	gender char(2) default '男' comment '性別'
)charset=utf8;

使用desc person查看錶結構,可以發現看不到註釋資訊:
在這裡插入圖片描述

使用show create table person\G (加上\G可以以一種簡單的形式列印資訊)檢視建表的資訊,才可以檢視到註釋資訊:
在這裡插入圖片描述

4.zerofill(0填充)

建立一個帶有整型欄位的表:

create table z1(
	a int(10) unsigned zerofill default NULL,
	b int unsigned default 0
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

整型是代表的4個位元組,但是後邊的10代表的是什麼?其實int(10)如果沒有設定zerofill約束這個值沒有任何意義。但是如果設定zerofill約束,當你要插入的數位數沒有達到10位,其他位數就會被0填充

插入一條資料檢視結果:

insert into z1 values(1,2);

下邊為插入結果:
在這裡插入圖片描述
a的值由原來的1變成0000000001,這就是zerofill屬性的作用,如果寬度小於設定的寬度(這裡設定的是 10)自動填充0要注意的是,這只是後顯示的結果,在MySQL中實際儲存的還是1。

使用內建函式hex()將a的值轉為十六進位制:
在這裡插入圖片描述
由結果可以看出資料庫內部儲存的還是10000000001只是設定了zerofill屬性後的一種格式化輸出而已。

5.主鍵約束

主鍵primary key:用來唯一的約束該欄位裡面的資料,不能重複、不能為空、主鍵所在的列是整數型別。一張表中多只能有一個主鍵,建立表的時候直接在欄位上指定主鍵

5.1 單個欄位的主鍵

  • 建立一個帶有主鍵id的表
create table z2(
	id int unsigned primary key comment '學號', -- id一個欄位加主鍵約束
	name varchar(20) not null comment '姓名'
)charset=utf8;
  • 使用desc z2檢視該表的結構

在這裡插入圖片描述
Key中的PRI代表的是主鍵。

5.2 多個欄位的主鍵(複合主鍵)

建立表的時候,在所有欄位之後,使用primary key(主鍵欄位列表)來建立主鍵,如果有多個欄位作為主鍵,可以使用複合主鍵

  • 建立一張以多個欄位為主鍵的表
create table z3(     
	 id int unsigned comment '學號',     
	 course char(10) comment '課程程式碼',     
	 score tinyint unsigned default 60 comment '成績',     
	 primary key(id, course) -- id和course為複合主鍵,複合主鍵一定是在所有欄位後宣告的     
)charset=utf8;
  • 使用desc z3檢視該表的結構

在這裡插入圖片描述
可以看出id和course為複合主鍵。

  • 當一個表建好後,也可以追加主鍵約束
-- 語法:
alter table 表名 add primary key(欄位列表) 
-- 建立一個沒有主鍵的表
create table z4(
	id int,
	name varchar(20)
);
-- 增加主鍵約束
alter table z4 add primary key(id);

使用desc查看錶的結構,可以看到主鍵追加完成:
在這裡插入圖片描述

5.3 主鍵約束

主鍵對應的欄位中不能重複,一旦重複,操作失敗。

例如:在z4中插入兩個記錄:

insert into z4 values(1,'a'); -- 插入成功
insert into z4 values(1,'b'); -- 插入失敗,主鍵不唯一

下邊為插入結果:
在這裡插入圖片描述

5.4 刪除主鍵

語法:alter table 表名 drop primary key;

例如:刪除表z4中的主鍵:

alter table z4 drop primary key;

desc查看錶結構,發現主鍵被刪除:
在這裡插入圖片描述

6.自增長

6.1 自增長概念

自增長auto_increment:當對應的欄位,沒有給值,會自動的被系統觸發,系統會從當前欄位中已經有的值進行+1操作, 得到一個新的不同的值。通常和主鍵搭配使用,作為邏輯主鍵。

6.2 自增長的特點

  • 任何一個欄位要做自增長,前提是本身是一個索引(key一欄有值)
  • 自增長欄位必須是整數
  • 一張表多只能有一個自增長

例如:建立一個帶有自增長約束的表,並進行插入操作:

 create table z5(     
 	id int unsigned primary key auto_increment, -- 邏輯主鍵    
 	name varchar(10) not null default ''     
 ); 
 -- 插入兩條記錄
 insert into tt21(name) values('a'); 
 insert into tt21(name) values('b'); 

使用select * from z5檢視插入結果:
在這裡插入圖片描述

7.唯一鍵(unique)

一張表中有往往有很多欄位需要唯一性資料不能重複,但是一張表中只能有一個主鍵。唯一鍵就可以解決表中有多個欄位需要唯一性約束的問題。唯一鍵的本質和主鍵差不多,唯一鍵允許為空,而且可以多個為空,空欄位不做唯一性比較。

  • 建立一個帶有唯一性約束的表,並插入一些資料
create table z6(
	id int unique,
	name varchar(20) not null
);
-- 插入幾條記錄
insert into z6(id, name) values('01', 'a'); -- 插入成功
insert into z6(id, name) values('01', 'b'); -- id不唯一
insert into z6(id, name) values(null, 'c'); -- 可以插入null  
  • 使用select * from z6檢視插入結果

在這裡插入圖片描述

注:在MYSQL中的各類語句一般使用大寫,在本篇博文中,由於大寫寫起來比較難看懂,所以就採用小寫