這里把自己學的mysql數據庫的知識總結一下,當是給自己復習一遍,也是方便以后查詢
安裝和配置mysql就不說了,可以借鑒這位博友的安裝過程 https://www.cnblogs.com/by330326/p/5608290.html
一.mysql基本命令
1.基礎常用命令
mysql -uroot -p密碼;(也可以不帶密碼,之后輸入) 本地登錄
mysql -h 登錄ip -p 端口(通常3306) -uroot -p密碼; 遠程登錄
desc 表名;查看表的各個字段的屬性,以及自增鍵
mysqldump -u用戶 -p 數據庫名 > xx.sql; 導出數據庫文件,保存
mysql -u用戶 -p密碼 數據庫名< xx.sql;導入數據庫文件(也可以選擇登錄進去,在選擇數據庫后,使用source命令導入數據)
2.創建命令
create user '用戶名' @'ip' identified by '密碼'; 創建用戶
ip是指用戶登錄mysql的電腦ip,可以寫%,本地寫localhost
grant 權限(select/insert/updata/all priveleges) on 表/數據庫名 to '用戶'@'ip' identified by '密碼'; 用戶授權
drop user 用戶名@ip 刪除用戶
show databases; 查數據庫
show tables; 看表
create database 數據庫名 default charset utf8; 創建數據庫
create table 表名(列名 數據類型 約束···,列名 數據類型 約束···)engine=innodb default charset=utf8 創建表
其中數據類型種類 數字(int,tinyint,smallint,float,double),字符串(char(個數)varchar(個數))時間(DATE,TIME,DATETIME),枚舉enum(值只能是枚舉中的元素),集合set(值只能是結合元素的組合)
create table 表名(列名 數據類型 primary key auto_increment,列名 數據類型 約束···)engine=innodb default charset=utf8 創建含主鍵的表
create table 表名(列名 數據類型 primary key,列名 數據類型 constraint fk_外鍵名 foreign key (列名[,]) references 表名2(列名[,])···)engine=innodb default charset=utf8 創建含外鍵的表
2.查表命令
條件查詢
select * from 表名;
select 列名···from 表名;
select 列名 from 表名 where 列名(id等) >/</!= value;
select 列名,常量 from 表名; 增加一個常量列
select 列名 from 表名 where 列名 in/not in/between and value;
select 列名 from 表名 where 條件1 and 條件2;
特殊的:select 列名 from 表名 where 列名 in (select 列名(只能一列) from 表名);
select 列名 from 表名 where 列名 like 'xx%'/'%xx'/"xx_"; 查詢以xx開頭/xx結尾 %代表任意位,_代表一位
select xx,(select xx from ...) from ..... 查詢條件做常量值
分頁
select 列名 from 表名 limit num; 顯示num個
select 列名 from 表名 limit num1,num2;從num1后取num2行數據,num1是起始位置,num2是個數
select 列名 from 表名 limit num1 offset num2;從num2后取num1行數據,num2是起始位置,num1是個數
排序
select * from 表名 order by 列名 desc;從大到小排序
select * from 表名 order by 列名 asc;從小到大排序
select * from 表名 order by 列名1 desc 列名2 asc; 首先遵循列1從大到小排序,遇到相同數據時,按列2從小到大排序
分組操作
select count/sum/max/min/avg(列名1),列名2 from 表名 group by 列名(通常是列名2);分組操作
select count/sum/max/min/avg(列名1),列名2 from 表名 group by 列名(通常是列名2)having 條件;分組操作后篩選
連表操作
select * from 表1 left join 表2 on 表1.列名=表2.列名; 左連接
select * from 表1 right join 表2 on 表1.列名=表2.列名; 右連接
select * from 表1 inner join 表2 on 表1.列名=表2.列名; 內連接
注意:如果超過3個表聯合操作,如果其中兩個表操作時已經改變了表結構,應該將這兩個表操作的結果作為一個臨時表再與第三個表聯合操作。
臨時表
(select * from 表名)as e
3.刪除,修改,插入命令
插入
insert into 表名(列名1,列名2···) values(值1,值2···),(值1,值2···),(值1,值2···); 插入值
insert into 表名1(列名) select 列名 from 表2; 在一個表中插入另一個表中數據
修改
update 表名 set 列名1=value1,列名2=value2 where 條件1 [and/or 條件2];
刪除
delete from 表名; 清除表(如果有自增id,id 不會重新開始)
delete from 表名 where 條件; 清除特定數據
truncate table 表名;清除表(如果有自增id,id 會重新開始)
4.修改表結構
alter table 表名 auto_increment=value;設置自增鍵起始值;
alter table 表名 drop 列名;刪除列
alter table 表名 add 列名 數據類型 約束; 增加列
alter table 表名 change 舊列名 新列名 數據類型; 修改字段類型
alter table 表名 modify 列名 數據類型; 修改數據類型
alter table 舊表名 rename 新表名; 修改表名
alter table 表名 drop primary key; 刪除表中主鍵
alter table 表名 add 列名 數據類型 primary key;添加主鍵
alter table 表名 add primary key(列名);設置主鍵
alter table 表名 add column 列名 數據類型 after 列名;在某一列后添加主鍵
二.mysql進階
1.外鍵
外鍵適用於一對多,一對一,多對多三種情況
一對多
典型案例員工與部門,一個部門對應於多個員工,一個員工對應於一個部分,所以要在員工表中設置部門id列,並設置為外鍵,與部門表id關聯。
一對一
案例博客園用戶與博客,不是每個用戶都寫博客,寫博客的用戶與擁有的博客地址一一對應,所以在博客用戶表user中設置blog_id,設置成外鍵和唯一索引,與博客表blog中id關聯
create table user(id int not null auto_increment primary key,name char(10), blog_id int,unique uq1(blog_id),constraint fk_user_blog foreign key(blog_id) references blog(id))engine=innodb default charset=utf8;
多對多
典型案例電腦與用戶,一個用戶可以使用多台電腦,一台電腦對應多個用戶,多對多,此時一般選擇新建一個表contact,在其中設置兩個外鍵,同時關聯用戶表id與電腦表id
create table contact(id int not null auto_increment primary key,user_id int,computer_id int,unique uq2(user_id,computer_id),constraint fk_user foreign key(user_id) references user(id),constraint fk_user foreign key(computer_id) references computer(id))engine=innodb default charset=utf8;
可以看情況決定要不要把兩個外鍵弄成聯合唯一索引。
2.自增
show create table 表名 [\G];查看表的創建信息
對於自增鍵,我們可以設置它的初始值以及與自增步長
alter table auto_increment=value;設置自增初始值
對於自增步長有兩種類型:
第一種:基於會話級別(只對本次登錄有效)
show session variables like "auto_incre%"; 查看步長
set session auto_increment_increment=value; 改變步長
set session auto_increment_offest=value; 設置起始值(不常用,因為有之前的alter)
第二種:基於全局級別(對所有會話都有用)
set global auto_increment_increment=value; 設置全局步長
3.pymysql
pymysql 是python第三方模塊,主要用於python與mysql交互。
pymysql 方法:
connect(host=,user=,passwd=,database=) 連接數據庫
cursor() 建立游標
execute(sql)執行sql語句
fetchone()從查詢結果中取出一條數據
fetchmany(num)從查詢結果中取出num條數據
fetchall()從查詢結果中取出所有數據
commit() 改變(updata,insert,drop)數據庫內容專用,execute sql語句后必須commit才能真正改變數據庫
close()注意最后有兩個close,游標要關閉,連接也要關閉
sql注入
sql注入就是通過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令。
實例如下:
假設我們輸入用戶名和密碼,然后登錄數據庫,在數據庫中查找用戶和密碼是否存在,存在即登錄成功,否則登錄失敗
程序如上,一開始我們輸入數據庫存在的用戶和密碼,自然能夠登錄成功
輸入錯誤用戶和密碼,也能成功
追究其原有,原因出在sql語句字符串拼接上,拼接的字符串為 ‘’ or 1=1 -- ‘‘ and passwd='123',有1=1,當然成立
解決辦法:將要拼接的內容放入execute括號中,由其自己拼接
視圖
視圖是一種虛擬存在的表,本身不包含數據,作為一個select語句保存在數據庫中。通俗的講視圖代表的是一條select語句產生的結果集。
create view 視圖名稱 as select語句; 創建視圖
視圖單獨不能插入,修改數據,因為視圖是虛擬的。但可以修改select語句,改變視圖結果集。
alter view 視圖名稱 as sql語句; 修改結果集
drop view 視圖名稱; 刪除視圖
4.索引
定義:索引(Index)是幫助MYSQL高效獲取數據的數據結構
索引的作用:約束,加速查找
索引種類
普通索引:加速查找
主鍵索引:加速查找;約束(主鍵不能為空,不能重復)
唯一索引:加速查找;約束(索引不能重復)
組合索引:多列組成一個索引(聯合主鍵索引,聯合唯一索引,聯合普通索引)
create index 索引名 on 表名(列名[,列名]);創建[聯合]普通索引
create table 表名(列名 數據類型···index 索引名(列名[,列名])); 創建表時創建[聯合]普通索引
create unique index 索引名 on 表名(列名);創建唯一索引
create table 表名(列名 數據類型···unique 索引名(列名)); 創建表時創建唯一索引
create unique index 索引名 on 表名(列名,列名);創建聯合唯一索引
create table 表名(列名 數據類型···unique 索引名(列名,列名)); 創建表時創建聯合唯一索引
drop index 索引名 on 表名; 刪除索引
索引結構
索引一般有兩種結構:哈希索引和BTree索引
哈希索引
哈希索引會產生一張索引表,把數據通過算法換算成哈希值,索引表存儲這些哈希值,並在表中保存指向數據的指針,值得注意的是索引表存儲哈希值時打亂了原有的存儲順序。哈希索引查找一條數據時特別快速,優於BTree索引,但因為打亂了原有的數據順序,不支持范圍查找與排序功能。
BTree索引
MYSQL普遍采用B+Tree結構
B+Tree所有索引數據都在葉子節點上,並且增加了順序訪問指針,每個葉子節點都有指向相鄰葉子節點的指針。BTree索引查找單條數據的速度不如哈希索引,但是更加適用於范圍查找與排序,所以用的最為廣泛,引擎innodb與MyIsam都使用了BTree索引。
索引是不是越多越好?
答:不是的,索引越多,占據的物理空間越大;索引只是加快了查詢速度,而減緩了插入和修改速度。
5.事務
定義:在MYSQL中,事務其實是一個最小的不可分割的工作單元,事務能保證一個業務的完整性。
場景:在開發中,有多條語句可能會有同時成功的要求,如果只有一部分成功,則全部失敗,回滾到原來的狀態。
mysql中如何控制事務
通過select @@autocommit;語句查詢自動提交是否開啟,1表示開啟,0表示沒有開啟
當查詢結果為1時,自動提交開啟,執行sql語句(insert into,alter),系統默認提交確認,在物理表生效
當查詢結果為0時,自動提交關閉,執行sql語句,系統會等待用戶手動提交確認(commit;),否則可以撤回修改,回滾為原狀態(rollback;)
開啟事務
一般@@autocommit我們默認開啟,否則每次都需手動提交太麻煩,但當我們想開啟一個事務時應該怎么做?
我們可以通過begin或start transaction 開啟一個事務,最后以commit;或rollback;結束一個事務。
事務的四大特性(ACID)
A 原子性:事務是最小的不可分割的工作單元
C 一致性:在一個事務中,事務前后數據的完整性必須保持一致,sql語句要么全部成功,要么失敗,回滾到原狀態。如銀行轉賬,總的錢數不變
I 隔離性:不同事務之間具有隔離性
D 持久性:事務一旦結束,就不可以返回,不可以rollback
mysql事務四大隔離級別
讀未提交(read uncommitted)
不可重復讀(read committed)
可重復讀(repeatable read)
串行化(serializable)
mysql事務隔離級別默認是可重復讀(repeatable-read)
select @@ global.tx_isolation;mysql(5.x版本)查看隔離級別
set [global/session] transaction isolation level 隔離級別; 設置隔離級別
四種隔離級別導致的問題:
臟讀:事務1讀到了事務2未提交的數據,如果事務2rollback,這些數據便是臟數據
不可重復讀:事務1對同一數據重復讀,但是另一個事務不斷修改這些數據,造成事務1每次讀到的數據不一樣
幻讀:是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及到表中的全部數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那么,以后就會發生操作第一個事務的用戶在新開啟的事務中發現表中還有沒有修改的數據行,就好象發生了幻覺一樣(用戶1開啟事務查看數據,然后同時有用戶2開啟事務對數據修改並提交,用戶1在當前事務沒有發現數據改變,結束事務,然后在新開啟的事務中發現了新修改的數據,這像幻覺)
注意:不可重復讀側重修改,幻讀側重插入和刪除
幻讀試驗:
設置隔離級別
開啟一個事務,查詢數據
重新打開一個窗口登錄,開啟事務插入數據,並commit
先前的事務查詢數據,看不到新增語句,解決了不可重復讀問題
關閉先前事務,重新查詢,查到新增數據,出現幻讀
三.mysql重要知識點
1.innodb與MyIsam的區別
InnoDB支持事務,而MyISAM不支持事務;
InnoDB支持行級鎖,而MyISAM支持表級鎖;
InnoDB支持MVCC(多版本並發控制), 而MyISAM不支持;
InnoDB支持外鍵,而MyISAM不支持;
InnoDB不支持全文索引,而MyISAM支持;
2.內連接,左連接,右連接的區別
內連接:返回兩表指定列名相同的數據,如果沒有返回空。
select * from 表1 inner join 表2 on 表1.列名=表2.列名; 內連接
左連接:左邊數據全顯示,右邊表只顯示符合條件的數據,如果右邊沒有相符數據或滿足的數據少於左邊數據行,以null代替(記錄不足的地方以null代替)
select * from 表1 left join 表2 on 表1.列名=表2.列名; 左連接
右連接:與左連接相反
select * from 表1 right join 表2 on 表1.列名=表2.列名; 右連接
3.drop,delete與truncate的區別
drop直接刪掉表
truncate刪除表中數據,再插入時自增長id又從1開始
delete刪除表中數據,可以加where字句,delete刪除整個表數據時,再插入自增id不會從1開始
4.為什么用BTree做索引結構
哈希:雖然單詞查詢快,但是沒有順序,不適合范圍查詢
二叉樹:樹的高度不均勻,不能自平衡,查找效率與樹的高度有關,IO代價高
紅黑樹:樹的高度隨數據量而變,IO代價高(數據量過大時,樹的深度越高,IO讀寫越頻繁)
Btree:數據很大時,不可能放在內存,所以放在磁盤上,BTree 每層節點數多,層數少,減少了IO讀寫次數,查詢結果更加穩定
5.主鍵 外鍵
主鍵:數據庫表中對儲存數據對象予以唯一和完整標識的數據列或屬性的組合。一個表只能有一個主鍵,且主鍵的取值不能缺失,即不能為空值(Null)。
外鍵:在一個表中存在的另一個表的主鍵稱此表的外鍵。
6.varchar與char區別
char是一種固定長度的類型,varchar則是一種可變長度的類型
char 長度是固定的,不管你存儲的數據是多少他都會都固定的長度。而varchar則處可變長度
varchar(50)中50表示最多有50個字符
varchar節省空間,查詢速度沒有char速度快
7.行級鎖和表級鎖
表級:直接鎖定整張表,在你鎖定期間,其它進程無法對該表進行寫操作。如果你是寫鎖,則其它進程則讀也不允許
行級:僅對指定的記錄進行加鎖,這樣其它進程還是可以對同一個表中的其它記錄進行操作。