MySQL數據庫:SQL語句基礎、庫操作、表操作、數據類型、約束條件、表之間的關系
數據庫相關概念:
1. 數據庫服務器:運行數據庫管理軟件的計算機
2. 數據庫管理軟件:MySQL、Oracle、db2、slqserver
3. 庫:文件夾,用來組織文件/表
4. 表:文件(類似於excel),用來存放多行內容/多條記錄
5. 記錄:事物一系列典型的特征
6. 數據:描述事物特征的符號
MySQL數據庫就是一個套接字軟件,用來管理其他機器上的數據文件
MySQL介紹:
MySQL是一個關系型數據庫管理系統;就是一個基於socket編寫的C/S架構胡軟件
客戶端軟件
mysql自帶:如mysql命令,mysqldump命令等
python模塊:如pymysql
數據庫管理軟件分類:
分兩大類:
關系型:如 sqllite,db2,oracle,access,sql server,mysql,註意:sql語句通用
非關系型:mongodb,redis,memcache
可以簡單的理解為:
關系型數據庫需要有表結構
非關系型數據庫是key-value存儲的,沒有表結構
SQL語句基本操作:
MySQL服務端軟件即mysqld幫我們管理好文件夾及文件,前提是作為使用者的我們,需要下載mysql的客戶端,或者其他模塊來連接到mysqld,然後使用mysql軟件規定的語法格式去提交自己的命令,實現對文件夾或文件的管理。該語句即sql(Structured Query Language 結構化查詢語言)
SQL語言主要用於存取數據、查詢數據、更新數據和管理關系數據庫系統;分為3種類型:
1. DDL語句: 數據庫定義語言:數據庫、表、視圖、索引、存儲過程,例如create,drop,alter
2. DML語句: 數據庫操縱語言:插入數據insert、刪除數據delete、更新數據update、查詢數據select
3. DCL語句: 數據庫控制語言:例如控制用戶胡訪問權限grant、revoke
操作文件夾(庫)
增: create database db1 charset utf8; (創建數據庫db1,其字符編碼為UTF-8;db1是庫名)
查: show create database db1;
show databases; (查看所有的數據庫)
改: alter database db1 charset gbk; (改數據庫 db1 的字符編碼 為 gbk; 不能改名字,只能改字符編碼)
刪: drop database db1; (刪數據庫db1)
操作文件(表)
先切換文件夾: use db1; (切換到數據庫db1)
查看當前所在的文件夾(庫): select database();
增: create table t1(id int,name char); (創建文件(表),文件名是t1,表中字段是id(id的數據類型是整型) 和 name(name是字符))
查: show create table t1; (查看創建的文件t1)
desc t1; (查看表t1;desc是describe的縮寫)
show tables; (查看當前庫下所有的表/文件)
改: alter table t1 modify name char(6); (修改表t1,把t1中name字段char的寬度改為6)
alter table t1 change name NAME char(7); (修改表t1,把t1中name字段改為NAME,並把char改為7)
刪: drop table t1; (刪除t1這個表)
操作文件內容(記錄)
增:insert t1(id,name) values(1,"neo1"),(2,"neo2"),(3,"neo3"); (往t1這個文件中插入values;插入多條value用逗號隔開;values中的值按照t1後面的字段順序添加)
insert t1 values(1,"neo1"),(2,"neo2"),(3,"neo3"); (t1後面不加字段名,默認按字段順序添加values)
查:select id,name from t1; (查看當前庫下t1這個表的id和name)
select id,name from db1.t1; (如果所查看的t1表不在當前庫下,則在t1前加上db1這個庫名前綴)
select id from t1; (只查詢id)
select * from t1; (查詢所有字段)
改:update db1.t1 set name="NEO"; (更改db1庫下的t1表,把name字段全部設置成NEO)
update t1 set name="Neo" where id=2; (更新當前庫下的t1表,把id為2那一行name設置成Neo)
刪:delete from t1; (把t1表下的所有記錄都刪除)
delete from t1 where id=2; (把t1表下id為2的記錄刪除)
庫操作:
系統數據庫:
information_schema:虛擬庫,不占用磁盤空間,存儲的是數據庫啟動後的一些參數,如用戶表信息、列信息、權限信息、字符信息等
performance_schema:MySQL 5.5開始新增一個數據庫:主要用於收集數據庫服務器性能參數,記錄處理查詢請求時發生的各種事件、鎖等現象
mysql:授權庫,主要存儲系統用戶胡權限信息
test:MySQL數據庫系統自動創建胡測試數據庫
創建數據庫:
1. 語法: create database 數據庫名 charset utf8;
2. 數據庫命名規則:
可以由字母、數字、下劃線、@、#、¥
區分大小寫
唯一性
不能使用關鍵字如create、select等
不能單獨使用數字
最長128位
數據庫相關操作:
查看數據庫:
show databases;
show create database db1;
select database();
選擇數據庫:
use 數據庫名;
刪除數據庫:
drop database 數據庫名;
修改數據庫:
alter database db1 charset utf8;
存儲引擎介紹:
1. 數據庫中的表有不同胡類型,表的類型不同,會對應mysql不同的存取機制,表類型又稱存儲引擎;存儲引擎就是表的類型
2. 查看MySQL支持的存儲引擎: show engines; # 默認的存儲引擎是innodb
3. 指定表類型/存儲引擎:
create table t1(id int)engine=innodb;
create table t1(id int)engine=memory;
create table t1(id int)engine=blackhole;
表操作:
1. 表介紹:表相當於文件,表中的一條記錄就相當於文件胡一行內容,不同的是,表中的一條記錄有對應的標題,稱為表的字段
id,name,age,sex稱為字段,其余的,一行內容稱為一條記錄
2. 創建表:
語法:
create table 表名(
字段名1 類型[(寬帶)約束條件],
字段名2 類型[(寬帶)約束條件],
字段名3 類型[(寬帶)約束條件]
) ;
附:表中最後一個字段後面不要再加逗號
註意:
1. 同一張表種,字段名不能相同
2. 寬帶和約束條件可選
3. 字段名肯類型椒必須的
3. 查看表結構:
1. describe 表名; # 查看表結構,可簡寫為 desc 表名;
2. show create table 表名; # 查看表詳細結構,可加 \G
4. 修改表結構:
1. 修改表名: alter table 表名 rename 新表名;
2. 增加字段: alter table 表名 add 字段名 數據類型 [完整性約束條件], add 字段名 數據類型 [完整性約束條件];
alter table 表名 add 字段名 數據類型 [完整性約束條件] first; # 把這個字段放到第幾個位置
alter table 表名 add 字段名 數據類型 [完整性約束條件] after 字段名; # 把新添加的字段放到某個字段後面
3. 刪除字段: alter table 表名 drop 字段名;
4. 修改字段: alter table 表名 modify 字段名 數據類型 [完整性約束條件]; # 修改字段的數據類型相關信息
alter table 表名 change 舊字段名 新字段名 新/舊數據類型 [完整性約束條件]; # 修改字段名和數據類型
5. 刪除表: drop table 表名;
6. 復制表:
1. 復制表結構和記錄: create table 表名1 select name,age from db1.表名2; # 數據庫db1中的表名2中的name和age復制到表名1中(把表2胡查詢結果當作復制的內容傳給表1)
2. 只復制表結構,不復制紀錄:create table 表名1 select name,age from db1.表名2 where 1>5; # where 1>5是一個假條件(沒有紀錄能滿足這個條件),但表名2的表結構卻是存在的,通過這種方式去只復制表結構
3. 只復制全部的表結構: create table 表名1 like db1.表名2; # 復制db1數據庫中表名2的所有表結構,不復制紀錄
數據類型:
存儲引擎決定了表的類型,而表內存放胡數據也要有不同的類型,每種數據類型都有自己的寬帶,但寬度是可選胡
詳細參考:
http://www.runoob.com/mysql/mysql-data-types.html
https://dev.mysql.com/doc/refman/5.7/en/data-type-overview.html
MySQL常用數據類型:
1. 數字
整形:tinyint, int, bigint
小數:
float:在位數比較短的情況下不精確
double:在位數比較長的情況下不精確
decimal:精確,內部原理是字符串形式存儲
2. 字符串:
char(10):簡單粗暴,浪費空間,存取速度快;root存成root000000
varchar:精確,節省空間,存取速度慢
3. 時間類型: 最常用:datetime
4. 枚舉類型於集合類型
數值類型:
1. 整數類型:tinyint, smallint, mediumint,bigint; 作用:存儲年齡、等級、id、各種號碼等
tinyint[(m)] [unsigned] [zerofill]
小整數,數據類型用於保存一些範圍的整數數值範圍:
有符號: -128~127 ; 無符號: 0~255 ; ps: MySQL中無布爾值,使用tinyint(1)構造
inyint[(m)] [unsigned] [zerofill]
整數,數據類型用於保存一些範圍的整數數值範圍:
有符號:-2147483648 ~ 2147483647;無符號: 0 ~ 4294967295
註意:為整數類型指定寬度時,僅僅只是指定查詢結果的顯示寬度,與存儲範圍無關;其實我們完全沒必要為整數類型指定顯示寬帶,使用默認的就可以了;默認的顯示寬帶,都是在最大值的基礎上加1
int的存儲寬度是4個bytes,即32個bit,即2**32; 無符號最大值為:4294967296-1;有符號最大值:2147483648-1
有符號和無符號的最大數字需要的顯示寬度均為10,而針對有符號的最小值則需要11位才能顯示完整,所以int類型默認的顯示寬帶為11是非常合理的;所以,整形類型,沒有必要指定顯示寬度,使用默認的就行
浮點型:定點數類型:decimal(等同於dec); 浮點類型:float,double;作用:存儲薪資、身高、體重、體質參數等
float[(m,d)] [unsigned] [zerofill]:
定義:單精度浮點數(非準確小數值),m是數字總個數,d是小數點後個數;m最大值為255,d最大值為30;隨著小數的增多,精度變得不準確
double[(m,d)] [unsigned] [zerofill]:
定義:雙精度浮點數(非準確小數值),m是數字總個數,d是小數點後個數。m最大值為255,d最大值為30;隨著小數的增多,精度比float要高,但也會變得不準確
decimal[(m[,d])] [unsigned] [zerofill]:
定義: 準確的小數值,m是數字總個數(負號不算),d是小數點後個數。 m最大值為65,d最大值為30;隨著小數的增多,精度始終準確;對於精確數值計算時需要用此類型;decaimal能夠存儲精確值的原因在於其內部按照字符串存儲。
補充知識點:加入一條sql語句寫錯了,可以利用 \c 來終止這條語句的運行; 加入少了一個引號,就先把引號補全再用\c, 如: ‘\c
日期類型:year, date, time, datetime, timestamp;作用:存儲用戶註冊時間、文章發布時間、入職時間、出生時間、過期時間等
形式與範圍:
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 )
timestamp:YYYYMMDD HHMMSS(1970-01-01 00:00:00/2037 年某時)
先看下面一段sql語句:
create table stu1( id int, name char(6), born_year year, birth_date date, class_time time, regis_time datetime ); # char(6)是最多能存儲6個字符,所以名字最多6個字符 insert stu1 values(1,"neo",now(),now(),now(),now()); # now()是mysql是自帶的一個函數,調用當前時間
執行結果如下:
也可以自己添加日期:
insert stu1 values(2,"alex","2007","2007-1-11","08:00:00","2016-1-11 11:11:00");
如下圖:
字符類型:
char和varchar括號內的參數指的都是字符的長度
char類型:定長,簡單粗暴,浪費空間,存取速度快
字符長度範圍:0-255 (一個中文是一個字符,是utf8編碼的3個字節)
存儲:存儲char類型的值時,會往右填充空格來滿足長度,例如:指定長度為10,存<10個字符則用空格填充直到湊夠10個字符存儲
檢索:在檢索或者說查詢時,查出的結構會自動刪除尾部的空格,除非我們打開pad_char_to_full_length SQL 模式(SET sql_mode = "PAD_CHAR_TO_FULL_LENGTH";)
varchar類型:變長,精準,節省空間,存取速度慢
字符長度範圍:0-65535(mysql行最大限制為65535字節)
存儲:varchar類型存儲數據的真實內容,不會用空格填充;
varchar類型會在真實數據前加1~2個bytes作為前綴,該前綴用來表示真實數據的bytes字節數(1~2bytes最大表示65535個數字,正好符合mysql對row的最大字節限制,即已經足夠使用)
如果真實的數據<255則需要一個bytes的前綴(1Bytes=8bit 2**8最大表示的數字為255)
如果真實的數據>255bytes則需要2Bytes的前綴(2Bytes=16bit 2**16最大表示的數字為65535)
檢索: 尾部有空格會保存下來,在檢索或者說查詢時,也會正常顯示包含空格在內的內容
# length:查看字節數; char_length:查看字符數
1. char填充空格來滿足固定長度,但是在查詢時會自動刪除尾部的空格來匹配查詢值
2. 雖然char和varchar的存儲方式不太相同,但是對於兩個字符串的比較,都是只比較其值,忽略char存在的右填充,即使將sql_mode設置成PAD_CHAR_TO_FULL_LENGTH也一樣;但這不適用於like
所以,雖然varchar使用起來比較靈活,但是從整個系統的性能角度來說,char數據類型的處理速度更快
枚舉類型和集合類型:
字段的值只能在給定範圍內選擇,如單選框、多選框
enum 單選 只能在給定的範圍內選一個值,如性別 sex male/female
set 多選 在給定的範圍內可以選擇一個或多個值(愛好1,愛好2.。。)
create table client(name char(20), age int, sex enum("female","male"), level enum("vip1","vip2","vip3"), hobbies set("reading","working out","music","run") ); insert client values("neo",18,"male","vip1","music,run"), ("alex",73,"female","vip3","boy");
運行結果:
約束條件:
not null和default:
create table condition_null_default( id int, name char(10), sex enum("male","female") not null default "male" ); insert condition_null_default(id,name) values(1,"neo"), (2,"alina","female");
如下:
約束條件 unique key:
單列唯一:
方式一:
create table department1( id int unique, name char(10) unique ); insert department1 values(1,"IT"),(2,"Sales);
方式二:
create table department2( id int, name char(10), unique(id), unique(name) );
聯合唯一:
create table server( id int unique, ip char(15), port int, unique(ip,port) ); # unique(ip,port)的含義是: ip和port拼到一起後必須是唯一的
primary key:
約束:not null unique(不為空且唯一)
存儲引擎(默認innodb):對於innodb存儲引擎來說,一張表內必須有一個主鍵(通常將id字段設為主鍵)
單列主鍵:
create table t_primary( id int primary key,name char(16));
對於innodb,如果你不指定主鍵,innodb會找一個不為空且唯一的字段作為主鍵;如果沒找到,就用它自己隱藏的字段作為主鍵;如下
復合主鍵:
create table t_union_primary( ip char(15), port int, primary key(ip,port) ); # ip和port聯合組成主鍵
auto_increment: (自增長)
create table t_auto_incre( id int primary key auto_increment, name char(16)); # auto_increment的字段需要指定key # 默認是從1開始,每次增加1 insert t_auto_incre(name) values("neo"), ("egon"), ("alex");
如果中間自己不按順序插入了id,後面的id auto_increment時以你新插入的id作為起點
insert t_auto_incre(id,name) values(7,"neo1"); insert t_auto_incre(name) values ("NEO1"), ("NEO2"), ("NEO3");
# 查看mysql關於auto_increment的默認設置 show variables like "auto_inc%"; # show variables 是查看變量,like是模糊匹配,%代表任意長度的任意字符
# 步長: auto_increment_increment默認為1
# 起始偏移量(位置): auto_increment_offset默認為1
#設置步長: set session auto_increment_increment=5; set global auto_increment_increment=5; #session是會話級別的修改,就是只在本次運行時有效,退出再登錄後會恢復到原先的設置; #global是全局級別的修改,長期有效,但需要推出後重新登錄mysql才會生效 #設置起始偏移量: set session auto_increment_offset=3; set global auto_increment_offset=3; #用法同上;需要註意的一點:起始偏移量必須要小於等於步長
清空表:
delete from 表名 where xxx; 不要用delete去清空表,delete用在跟where語句連用的情況下;delete from 表名 無法刪除自增長(auto_increment)的紀錄
truncate 表名; 清空表應該用 truncate(能把自增長的紀錄也刪除掉)
foreign key(外鍵):建立表之間的關系
1. 建表
# 先建被關聯的表,並且保證保證被關聯的字段唯一 create table dept( id int primary key, name char(16), comment char(50)); # 再建關聯表 create table emp( id int primary key, name char(10), sex enum("male","female"), dept_id int, foreign key(dept_id) references dept(id)); # dept_id是外鍵,關聯到dept表的id字段
2. 插入數據
# 先往被關聯表中插入紀錄 insert dept values (1,"IT","幹技術的"), (2,"Sales","賣東西的"), (3,"Finance","花錢的"); # 再往關聯表中插入數據 insert emp values (1,"neo","male",1), (2,"alex","female",2), (3,"egon","male",3); # 因為只有被關聯表的關聯字段建起來後關聯表才能去關聯;後有紀錄的那張表加foreign key
上述建表方式由於沒有指定 on delete cascade on update cascade,所以不能直接操作被關聯表
如果想刪除、更新同步(即 刪除、更細被關聯表的關聯字段,關聯表也自動跟著刪除、更新),關聯表建表時要加上 on delete cascase on update cascade 例如:foreign key(dept_id) references dept(id) on delete cascade on update cascade
# 建被關聯的表 create table dept( id int primary key, name char(16), comment char(50)); # 建關聯表 create table emp( id int primary key, name char(10), sex enum("male","female"), dept_id int, foreign key(dept_id) references dept(id) on delete cascade on update cascade ); # 加上 on delete cascade on update cascade
delete from dept where id=1; update dept set id=202 where id=2;
tips:實際項目中盡量不要把兩張表建立硬性限制(foreign key),最好能從邏輯上去實現兩張表的關系,即從應用程序代碼的層面上去實現兩張表的關系,不要再數據庫利用foreign key去建立硬性關系(這樣不利於擴展)
表與表之間的關系: 多對一、多對多、一對一
多對一:例如上面的例子,員工表emp中多個人紀錄可以對應部門表dept中的一個部門紀錄,但多個部門紀錄卻不能對應一個人(即 多個人可以在一個部門下,但一個人卻不能在多個部門),這就是多對一
多對多:A表中的多條紀錄可以對應B表中的一條紀錄,同時B表中的多條紀錄也可以對應A表中的一條紀錄,這就是多對多;多對多需要專門另外建一張表來存多對多之間的關系;例如下面的書與作者的例子:
create table author( id int primary key auto_increment, name char(16)); create table book( id int primary key auto_increment, name char(50)); # 專門建一張表來保存多對多那兩張表之間的關系 create table author2book( id int not null unique auto_increment, author_id int not null, foreign key(author_id) references author(id) on delete cascade on update cascade, book_id int not null, foreign key(book_id) references book(id) on delete cascade on update cascade, primary key(author_id,book_id)); # author_id去多對一author表中的id字段,book_id去多對一book表中的id字段 insert author(name) values("neo"),("egon"),("alex"),("wusir"); insert book(name) values("python自動化"),("linux運維"),("python全棧"); # 插入多對多之間的關系 insert author2book(author_id,book_id) values (1,1),(1,2),(1,3), (2,1),(2,2), (3,2), (4,2),(4,3);
一對一:兩張表中的紀錄最多只能互相對應中的一條紀錄,即一一對應,例如博客園中一個昵稱只能對應一個博客鏈接,一個博客鏈接也只能對應一個昵稱
以培訓機構的custome和student為例,客戶(customer)表中的一條紀錄最多只能對應student表中的一個紀錄,student表中的一條紀錄也一定對應customer表中的一條紀錄:
# 先有潛在客戶customer才能有學生(student),後有紀錄的那鐘表加foreign key create table customer( id int primary key auto_increment, name char(10) not null, phone int not null); create table student( id int primary key auto_increment, class_name char(16) not null, customer_id int unique, foreign key(customer_id) references customer(id) on delete cascade on update cascade); # 要想稱為一對一的表,student的字段 customer_id必須要指定為 unique; 外鍵一定要保證 unique !!! insert into customer(name,phone) values (‘李飛機‘,13811341220), (‘王大炮‘,15213146809), (‘守榴彈‘,1867141331), (‘吳坦克‘,1851143312), (‘贏火箭‘,1861243314), (‘戰地雷‘,18811431230); insert student(class_name,customer_id) values ("python周末5期",3), ("linux運維6期",5);
MySQL數據庫:SQL語句基礎、庫操作、表操作、數據類型、約束條件、表之間的關系