1. 程式人生 > 其它 >mysql總結與複習

mysql總結與複習

技術標籤:MySQL

mysql

資料庫引擎

  1. innodb(預設使用)

  2. myisam(早些年使用的)

innodbmyisam
事務支援(跟spring遇到的是一個意思)支援不支援
資料行鎖定支援不支援
外來鍵約束支援不支援
全文索引不支援支援
表空間大小較大,約為myisam的兩倍較小
  • myisam 節約空間,速度較快

  • innodb 安全,事務的處理,多表多使用者操作

  • 共同點 儲存位置,資料庫檔案都在data目錄下

    在檔案上面的區別

    • innodb 在資料庫對應資料夾中只有一個.frm檔案,以及上級目錄下的ibdata1檔案

    • myisam 對應位置有.frm檔案(表結構),.myd檔案(資料檔案),.myi檔案(索引檔案)
      ps:跟在設定資料庫引擎後的DEFAULT charset=8是設定表的預設字符集編碼,不設定的話是mysql的預設字符集編碼(Latin1,不支援中文),my.ini可以設定預設的編碼:character-set-server=utf8(不建議)

新學的命令

show create database xxx
檢視建立資料庫的語句

show create table xxx
檢視某個資料表的語句
desc xxx
顯示錶的結構

複習

查詢(important)

select [all | distinct]
{* | table.* | [table.field1[as 別名1],table.field2[as 別名2],...],...}
from table [as 表別名]
	[left | right | inner join table2 on 條件]  --聯合查詢
	[where ...]  --結果需要滿足的條件
	[group by ...]  --結果按照哪些欄位分組
	[having ...]  --group by需要滿足的次要條件
	[order by ...]  --結果按照條件(一般是一些欄位)排序
	[limit {[offset,]row_count | row_count_offset offset}];  --指定結果從哪條到哪條
ps:[]代表可選,{}代表必選,where和on的結果差不多,可以寫一個也可以兩個都寫
  1. 指定了INNER關鍵字的連線是內連線,內連線是系統預設的,可以省略INNER關鍵字。使用內連線後仍可使用WHERE子句指定條件。
  2. left和right都是外連線,決定了查詢結果中哪個表裡的值為null
  3. 乾貨
    • inner join使用on或where結果是一樣的,區別就是join on是連線查詢(利於閱讀),where是等值查詢。where與join兩種方式
    • left/right join用on或where的區別:區別
    • on 條件是在生成臨時表時使用的條件,where 條件是在臨時表生成好後,再對臨時表進行過濾的條件(使用where之後就沒有 left join 的含義了,即必須返回左邊表的記錄),條件不為真的就全部過濾掉。
    • 自連線(瞭解即可),一張表拆為兩張一樣的表即可

記一個解題思路:如果查詢多張表,先查詢兩張表,然後增加(增加join on語句)

資料庫

unsigned(非負的意思):

  • 無符號的整數
  • 聲明瞭該列不能為負數

zerofill:

  • 0填充
  • 不足的位數使用0填充。int(3) 5 -> 005

null和not null

  • not null 不賦值就會報錯
  • null 不填寫值,預設為null

default

  • 預設值 sex default ‘男’

create database xxx character set utf8 collate utf _8_general_ci --建立資料庫,很多時候都是用的navicat建立的,這個是設定字符集的語句

  • collate 表示核對

create table `xxx` (

​ …

)engine = innodb default charset = utf8

  • 設定字符集時與建立資料庫時的語句稍有不一樣

聚合函式(important)

  1. COUNT()

    計數

    • COUNT(指定列欄位名) 根據列名計數,會忽略所有的null值
    • COUNT(*) 包含所有列,不會忽略列值為null的
    • COUNT(1) 忽略所有的列,用1代表程式碼行,不會忽略null值
  2. SUM(‘列名’)

    對某個列的值總和

其他,略

資料表

  1. 修改表名

    alter table 原名 rename as 新名

  2. 增加欄位

    alter table teacher add age int(11)

  3. 修改表的欄位(重新命名,修改約束)

    修改約束,原來是int,現在改成varchar

    alter table teacher modify age varchar(11)

    欄位重新命名

    alter table teacher change age age2 int(1)

  4. 刪除表的欄位

    alter table teacher drop age2

  5. 刪除表

    drop table teacher

    if exists :如果表存在再刪除,避免報錯(若沒有該表上面的語句會報錯,下面的就不會)

    drop table if exists teacher

ps:

  • 表名稱和欄位名儘量用``包裹,為了安全,防止出錯(防止被誤認為是關鍵字)

表資料

  1. 刪除表資料(delete)

    delete from 表名 where條件

    delete from `student` where id = 1
    
  2. 專業清空表資料(truncate)

    完全清空表,表結構和索引不會變,不建議使用delete清空

    truncate `student`
    

    與delete相比:

    • 相同點 完全清空表,表結構不會變
    • 區別 truncate會重新設定自增列(從零開始),不會影響事務;delete刪除後接著自增(不歸零),但是如果資料庫引擎是innodb,net start mysql之後,自增列會歸零(因為是存在記憶體當中的,斷電即失)

jdbc

一段感興趣的程式碼

InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
  --
Properties properties = new Properties();
properties.load(in);
String driver = properties.getProperty("driver");

ps:若此處配置資料庫連線池的是xml檔案,則不需要讀取程式碼

感興趣的一個區別:

java.sql.Date 資料庫的;使用 :java.sql.Date(new Date().getTime());

util.Date Java的 new Date().getTime() 獲得時間戳

statement物件,兩個方法

  • executeQuery()執行查詢語句,返回ResultSet物件
  • executeUpdate()執行增刪改語句,返回整數

sql注入問題(拼接字串,針對statement物件;而PreparedStatement物件就可以防止sql注入)

意思是web應用程式對使用者輸入資料的合法性沒有判斷或者過濾不嚴,攻擊者可以在web應用程式中事先定義好的查詢語句的結尾新增額外的sqsl語句,以此來實現欺騙資料庫伺服器執行非授權的任意查詢(把所有的使用者名稱密碼都查出來),從而進一步得到相應的資訊,上文參考百度百科,即sql存在漏洞,會被攻擊,導致資料洩露。輸入的時候sql被拼接 or

select * from users where `name` = '' or '1=1' and `password` = '' or '1=1'  
  --' or '1=1是拼接上去的;' or '1=1也是拼接上去的

PreparedStatement物件(防止sql注入)

原理:預編譯會在引數外面加引號並且過濾特殊字元(轉義字元),原來的注入語句就會變成下面這樣:

where name = '\'test\' or 1=1' --mysql的SQL文日誌

自然不會被注入

略(與statement物件類似,executeQuery()執行查詢語句,executeUpdate()執行增刪改語句)

資料庫連線池

資料庫連線的連線和釋放是十分浪費系統資源的

池化技術:預先準備一些資源,使用預先準備好的

  1. 最小連線數:10 根據常用的來

  2. 最大連線數:15 最高業務承載上限 超過15就排隊等待

  3. 等待超時:100ms 直接斷掉

編寫連線池需要實現一個介面:DataSource

開源的實現類

  1. DBCP
  2. C3P0
  3. Druid

使用不同的資料來源匯入不同的包就行

常用函式(不包括聚合函式)

官網全部函式點選檢視

數學函式

  1. ABS()

    絕對值

  2. CEILING()

    向上取整

  3. FLOOR()

    向下取整

  4. RAND()

    隨機數,0~1之間的隨機數

  5. SIGN

    判斷一個數的符號,0返回0,負數返回-1,正數返回1

字串函式

  1. CHAR_LENGTH()

    字串長度

  2. CONCAT(‘啦’,‘啦’,‘啦’)

    合併字串

  3. INSERT()

    在指定位置插入字串,也可以有替換的功能

  4. LOWER()、UPPER()

    轉換為小、大寫

  5. INSTR(‘yyh’,‘h’)

    返回第一次出現的子串索引

  6. REPLACE(‘hhhlll’,‘hl’,‘yyh’)

    替換出現的指定字串,hl -> yyh

  7. SUBSTR(‘hhhlll’,4,6)

    返回指定的子字串,4開始,擷取6個

  8. REVERSE(‘hhhlll’)

    字串反轉

時間和日期函式 這個個人用得還比較多

  1. CURRENT_DATE()/CURDATE()

    當前日期

  2. NOW()

    當前時間,包含時分秒

  3. LOCALTIME()

    本地時間

  4. SYSDATE()

    返回函式執行時間,系統時間

  5. YEAR/MONTH/DAY/HOUR/MINUTE/SECOND()

    不用多說

系統

  1. SYSTEM_USER()/USER()

    當前使用者

  2. VERSION()

    版本

資料庫的MD5加密(即MD5(),一個函式)

MD5:MD5叫資訊摘要演算法,MD5由MD4、MD3、MD2改進而來,主要增強演算法複雜度和不可逆性。MD5演算法因其普遍、穩定、快速的特點,仍廣泛應用於**普通資料的加密保護領域 ** ,1996年後該演算法被證實存在弱點,可以被加以破解,對於需要高度安全性的資料,專家一般建議改用其他演算法,如SHA-2

應用:

  • 密碼管理 可以將任意長度的輸入串經過計算得到固定長度的輸出,而且只有在明文相同的情況下,才能等到相同的密文,這樣就可以把使用者的密碼以MD5值的方式儲存起來,使用者註冊的時候,系統是把使用者輸入的密碼計算成 MD5 值,然後再去和系統中儲存的 MD5 值進行比較,如果密文相同,就可以認定密碼是正確的,否則密碼錯誤。
  • 電子簽名 MD5 演算法還可以作為一種電子簽名的方法來使用,使用 MD5演算法就可以為任何檔案(不管其大小、格式、數量)產生一個獨一無二的“數字指紋”,藉助這個“數字指紋”,通過檢查檔案前後 MD5 值是否發生了改變,就可以知道原始檔是否被改動。
  • 垃圾郵件篩選 在電子郵件使用越來越普遍的情況下,可以利用 MD5 演算法在郵件接收伺服器上進行垃圾郵件的篩選,以減少此類郵件的干擾。

總結:MD5不可逆,只有在明文相同的情況下,才能等到相同的密文

事務(只看加粗的就行)

ACID原則:原子性,一致性,隔離性,永續性

事務就是多條sql,要麼都ok,要麼都回滾

參考文章

產生一些問題:髒讀,幻讀

  1. 原子性

    a:800元,給b:200元,轉賬200兩個步驟

    800-200

    200+200

    這兩個步驟(sql)要麼都ok,要麼都回滾

  2. 一致性

    最終一致性:a和b的總價值一定是1000元(事務前後的資料要一致

  3. 永續性

    事務一旦提交就不可逆

    事務結束後資料不隨著外界原因導致資料丟失

    操作前:a 800,b 200

    操作後:a 600,b 400

    若在操作前(事務還沒有提交),伺服器宕機或斷電,那麼重啟資料庫後,應該是:a 800,b 200(恢復到原狀)

    若在操作後(事務已經提交),伺服器宕機或斷電,那麼重啟資料庫後,應該是:a 600,b 400(事務一旦提交就不可逆)

  4. 隔離性

    排除其他事務對本次事務的影響

    如:a(800)給b(200)轉200,c(1000)給b(200)轉100,多個使用者操作有個隔離的關係

    隔離失敗就會有問題:

    • 髒讀 一個事務讀取了另一個事務未提交的資料
    • 不可重複讀(不一定是錯誤,可能是場合不對) 在一個事務內讀取表中的某一行資料,多次讀取結果不同。比如在第二次讀取的時候b有人轉賬進來300
    • 虛讀(幻讀) 在一個事務內讀取到了別的事務插入的資料(一般是行影響,多了一行)

mysql是預設開啟事務自動提交的。

關閉:

set autocommit = 0

開啟(預設):

set autocommit = 1

手動處理事務

先關閉前面的自動提交,然後下面

  1. 事務開啟

    start transaction

    從這之後的sql都在同一個事務內

    sql語句;
    sql語句;
    sql語句;
    
  2. 提交(ok,不可逆,也就是持久化)

    commit;

  3. 回滾(fail,回到原來的樣子)

    rollback;

  4. 事務結束(開啟自動提交)

    set autocommit = 1;

ps:整個過程中可以設定儲存點(瞭解):

savepoint 儲存點名  --設定儲存點
rollback to savepoint 儲存點名  --回滾到儲存點
release savepoint 儲存點名  --撤銷儲存點

索引

官方原話:

索引(index)是幫助mysql高效獲取資料的資料結構。 0.5s -> 0.000001s(大大的節省了時間)

索引是資料結構,對於大量的資料正常查詢可能要查詢好多條記錄,索引只需要一條,非常快

  1. 分類

    • 主鍵索引 primary key navicat中索引選項中不顯示主鍵索引

      唯一的標識,主鍵不可重複

    • 唯一索引 unique key

      避免重複的列出現(兩列叫同一個名字肯定是不行的)

    • 常規索引 key/index

      預設的(不寫就有)

    • 全文索引 fulltext

      在特定的資料庫引擎才有(以前是myisam才有),快速定位資料。

      現在應該都有了,不只是myisam

    ps:主鍵索引只能有一個,唯一索引可以有多個(多個列可以標識為唯一索引,列名可以不同)

  2. 命令

    • 顯示錶的索引資訊

    show index from xxx

    • 增加一個全文索引(改表的語句)

      alter table `表名` add fulltext index `索引名`(`欄位名`);

      索引名:給索引起名字

      ps:還有兩種建立索引的方式,一個是建表的時候,另一個如下(常規索引)

      create index 索引名 on `表名`('欄位名');  --索引名:id_表名_欄位名
      
    • 分析sql執行的狀況 explain

      參考文章

      explain select * from `表名`; --非全文索引,會查很多行

      explain select * from `表名` where match(`欄位名`) against('字串'); --全文索引的使用,只查了一行,資料量比較少會沒有用

    • 寫函式之前必須的標誌(mysql的sql程式設計,瞭解)

      delimiter $$  --寫函式之前必須的標誌
      
      create function mock_data()
      returns int
      begin  --開始寫函式體
      	
      end;
      
  3. 索引原則

    • 索引不是越多越好
    • 不要對經常變動的資料加索引
    • 小資料量的表不需要加索引
    • 索引一般加在常用來查詢的欄位上

許可權管理

sql命令操作(navicat,略)

系統使用者表:mysql下的user表(在此表增刪改)

有三個預設使用者:root、mysql.session、mysql.sys

  1. 建立使用者

    create user yyh identified by '密碼'

  2. 修改密碼(當前使用者)

    set password = password('新密碼')

  3. 修改密碼(指定使用者)

    set password for yyh = password('新密碼')

  4. 給使用者重新命名

    rename user yyh to yyh2

  5. 使用者授權(all privileges,全部許可權,除了給別人授權的許可權;庫.表)

    grant all privileges on *.* to yyh2 --全部的庫全部的表,對所有表都有最高的許可權

  6. 檢視許可權

    show grants for yyh2 --檢視指定使用者的

    show grants for [email protected] --檢視root使用者的

  7. 撤銷許可權(跟授權一樣)

    revoke all privileges on *.* from yyh2

  8. 刪除使用者

    drop user yyh2

資料庫備份

原因:

  • 資料不丟失
  • 資料轉移

方式:

  1. 直接拷貝檔案(data下的資料庫檔案)

  2. navicat可以匯出(這個俺以前經常幹,略)

  3. 命令

    • 匯出一張表(mysqldump -h主機 -u使用者名稱 -p密碼 資料庫 資料表 >匯出位置)

      mysqldump -hlocalhost -uroot -p666 ssm users >D:/1.sql ---h表示host的意思

    • 匯出多張表(mysqldump -h主機 -u使用者名稱 -p密碼 資料庫 表1 表2 表3 >匯出位置)

      mysqldump -hlocalhost -uroot -p666 ssm users traveller role >D:/2.sql ---h表示host的意思

    • 匯出資料庫(mysqldump -h主機 -u使用者名稱 -p密碼 資料庫 >匯出位置)

      mysqldump -hlocalhost -uroot -p666 ssm >D:/3.sql ---h表示host的意思

    • 匯入資料表(use database之後)

      source d:/1.sql

      若沒有登入,則

      ``mysql -u使用者名稱 -p密碼 庫名< 備份檔案`