庫操作----------------------------------------------------------------- --創建數據庫 create database mydatabase; create database mydatabase2 charset utf8; --顯示數據庫 --顯示全部 show databases; --顯示部分 show databases like '匹配模式' 匹配模式 _:匹配當前位置單個字符 %:匹配指定位置多個字符 --查看以my開頭的數據庫 show databases like 'my%'; --顯示數據庫創建語句 show create database mydatabase; --選擇數據庫 use mydatabase2; --修改數據庫字符集(庫選項:字符集和校對集) alter database 數據庫名字 charset = 字符集 alter database mydatabase charset = utf8; --刪除數據庫 drop database mydatabase2; 表操作----------------------------------------------------------- --創建表 create table nclass( name varchar2(10), num int(10) )charset=utf8; --查看所有表 show tables; --匹配顯示表 show tables like '匹配模式'; --顯示表結構:顯示表中所包含的字段信息 describe 表名 desc 表名 show columns from 表名 --顯示表創建語句 show create table mytest; 表屬性指的就是表選項:engine,charset和collate 基本語法:alter table 表名 表選項 [=] 值; 修改表名:rename table 舊表名 to 新表名 新增字段:alter table 表名 add [column] 新字段名 列類型 [列屬性] [位置first/after 字段名] 字段位置:字段想要存放的位置 First:在某某之前(最前面),第一個字段 After 字段名:放在某個具體的字段之后(默認的) 修改字段名:alter table 表名 change 舊字段名 新字段名 字段類型 [列屬性] [新位置] 修改字段類型(屬性):alter table 表名 modify 字段名 新類型 [新屬性] [新位置] 刪除字段:alter table 表名 drop 字段名 刪除表結構:drop table 表名[,表名2…],可以同時刪除多個數據表 插入指定字段數據:insert into 表名[(字段列表)] values(對應字段列表) 表中所有字段插入數據:Insert into 表名 values(對應表結構)//值列表必須與字段列表一致 查詢表中全部數據:select * from 表名; 查詢表中部分字段:select 字段列表 from 表名; 簡單條件查詢數據:select 字段列表或* from 表名 where 字段名 = 值; 刪除:delete from 表名 [where 條件]; //如果沒有where條件:意味着系統會自動刪除該表所有數據(慎用) 修改:update 表名 set 字段名 = 新值 [where 條件]; //如果沒有where條件,那么所有的表中對應的那個字段都會被修改成統一值。 Set names 字符集的本質:就是一次性打通三層關系的字符集,變得一致。 在系統中有三個變量來記錄着這三個關系對應的字符集:show variables like ‘character_set_%’; mysql默認編碼配置---------------------------------------------- /* 配置mysql默認編碼為utf8: 在配置文件my.ini中的[client]和[mysqld]下添加如下代碼,然后重啟mysql服務 [client] default-character-set=utf8 ... [mysqld] character_set_server=utf8 collation-server=utf8_general_ci */ 字段類型---------------------------------------------------------- 整數類型: tinyint:迷你整形,系統采用一個字節來保存的整形:一個字節 = 8位,最大能表示的數值是0-255,mysql默認的為整形增加負數。實際表示的區間為-128,127 無符號:表示存儲的數據在當前字段中,沒有負數(只有正數,區間為0-255) 基本語法:在類型之后加上一個 unsigned --例如: alter table my_int add int_6 tinyint unsigned first; 新增字段int_6的范圍為0-255,此時就無法在該字段上插入負數 smallint:小整形,系統采用兩個字節來保存的整形:能表示0-65535之間 mediumint:中整形,采用三個字節來保存數據 int:整形(標准整形),采用四個字節來保存數據 顯示長度--------------------------------------------------------------- /* 顯示長度:指數據(整型)在數據顯示的時候,到底可以顯示多長位。 Tinyint(3): 表示最長可以顯示3位,unsigned說明只能是正數,0-255永遠不會超過三個長度 Tinyint(4):表示最長可以顯示4位,-128~127 顯示長度只是代表了數據是否可以達到指定的長度,但是不會自動滿足到指定長度:如果想要數據顯示的時候,保持最高位(顯示長度),那么還需要給字段增加一個zerofill屬性才可以。 Zerofill:從左側開始填充0(左側不會改變數值大小),所以負數的時候就不能使用zerofill,一旦使用zerofill就相當於確定該字段為unsigned 數據顯示的時候,zerofill會在左側填充0到指定位:如果不足3位,那么填充到3位,如果本身已經夠了或者超出,那么就不在填充。 顯示長度可以自己設定:超出長度(但是不超出范圍)不會影響,只會對不夠長度的進行補充(顯示長度) */ 小數類型:專門用於存儲小數的 在Mysql中將小數類型又分為兩類:浮點型和定點型 浮點型又稱之為精度類型:是一種有可能丟失精度的數據類型,數據有可能不那么准確(由其是在超出范圍的時候) /*浮點數 Float又稱之為單精度類型:系統提供4個字節用來存儲數據,但是能表示的數據范圍比整型大的多,大概是10^38; 只能保證大概7個左右的精度(如果數據在7位數以內,那么基本是准確的,但是如果超過7位數,那么就是不准確的) 基本語法 Float:表示不指定小數位的浮點數 Float(M,D):表示一共存儲M個有效數字,其中小數部分占D位 Float(10,2):整數部分為8位,小數部分為2位 浮點數可以采用科學計數法來存儲數據 浮點數的應用:通常是用來保存一些數量特別大,大到可以不用那么精確的數據 Double又稱之為雙精度:系統用8個字節來存儲數據,表示的范圍更大,10^308次方,但是精度也只有15位左右。 */ /*定點數 定點數:能夠保證數據精確的小數(小數部分可能不精確,超出長度會四舍五入),整數部分一定精確 Decimal定點數:系統自動根據存儲的數據來分配存儲空間,每大概9個數就會分配四個字節來進行存儲,同時小數和整數部分是分開的 Decimal(M,D):M表示總長度,最大值不能超過65,D代表小數部分長度,最長不能超過30。 定點數的應用:如果涉及到錢的時候有可能使用定點數 */ date 日期類型:系統使用三個字節來存儲數據,對應的格式為:YYYY-mm-dd,能表示的范圍是從1000-01-01 到9999-12-12,初始值為0000-00-00 time 時間類型:能夠表示某個指定的時間,但是系統同樣是提供3個字節來存儲,對應的格式為:HH:ii:ss, 但是mysql中的time類型能夠表示時間范圍要大的多,能表示從-838:59:59~838:59:59,在mysql中具體的用處是用來描述時間段。 time類型特殊性:本質是用來表示時間區間(當前時間之后的多少個小時),能表示的范圍比較大 datetime 日期時間類型:就是將前面的date和time合並起來,表示的時間,使用8個字節存儲數據,格式為YYYY-mm-dd HH:ii:ss, 能表示的區間1000-01-01 00:00:00 到9999-12-12 23:59:59,其可以為0值:0000-00-00 00:00:00 timestamp 時間戳類型:mysql中的時間戳只是表示從格林威治時間開始,但是其格式依然是:YYYY-mm-dd HH:ii:ss timestamp當對應的數據被修改的時候,會自動更新(這個被修改的數據不是自己) year 年類型:占用一個字節來保存,能表示1900~2155年,但是year有兩種數據插入方式:0~99和四位數的具體年 year的特殊性:可以采用兩位數的數據插入,也可以采用四位數的年份插入 year進行兩位數插入的時候,有一個區間划分,零界點為69和70:當輸入69以下,那么系統時間為20+數字,如果是70以上,那配系統時間為19+數字 char 定長字符:指定長度之后,系統一定會分配指定的空間用於存儲數據 基本語法:char(L),L代表字符數(中文與英文字母一樣),L長度為0到255 varchar 變長字符:指定長度之后,系統會根據實際存儲的數據來計算長度,分配合適的長度(數據沒有超出長度)。 基本語法:Varchar(L),L代表字符數,L的長度理論值位0到65535。 因為varchar要記錄數據長度(系統根據數據長度自動分配空間),所以每個varchar數據產生后,系統都會在數據后面增加1-2個字節的額外開銷:是用來保存數據所占用的空間長度 如果數據本身小於127個字符:額外開銷一個字節;如果大於127個,就開銷兩個字節。 Char和varchar的區別 1、 char一定會使用指定的空間,varchar是根據數據來定空間 2、 char的數據查詢效率比varchar高:varchar是需要通過后面的記錄數來計算 如果確定數據一定是占指定長度,那么使用char類型; 如果不確定數據到底有多少,那么使用varchar類型; 如果數據長度超過255個字符,不論是否固定長度,都會使用text,不再使用char和varchar text 文本類型:本質上mysql提供了兩種文本類型 Text:存儲普通的字符文本 Blob:存儲二進制文本(圖片,文件),一般都不會使用blob來存儲文件本身,通常是使用一個鏈接來指向對應的文件本身。 Text:系統中提供的四種text Tinytext:系統使用一個字節來保存,實際能夠存儲的數據為:2 ^ 8 + 1 Text:使用兩個字節保存,實際存儲為:2 ^ 16 + 2 Mediumtext:使用三個字節保存,實際存儲為:2 ^ 24 + 3 Longtext:使用四個字節保存,實際存儲為:2 ^ 32 + 4 注意: 1、 在選擇對應的存儲文本的時候,不用刻意去選擇text類型,系統會自動根據存儲的數據長度來選擇合適的文本類型。 2、 在選擇字符存儲的時候,如果數據超過255個字符,那么一定選擇text存儲 /*enum 枚舉類型:在數據插入之前,先設定幾個項,這幾個項就是可能最終出現的數據結果。 如果確定某個字段的數據只有那么幾個值:如性別,男、女、保密,系統就可以在設定字段的時候規定當前字段只能存放固定的幾個值:使用枚舉 基本語法:enum(數據值1,數據值2…) 系統提供了1到2個字節來存儲枚舉數據:通過計算enum列舉的具體值來選擇實際的存儲空間:如果數據值列表在255個以內, 那么一個字節就夠,如果超過255但是小於65535,那么系統采用兩個字節保存。 enum有規范數據的功能,能夠保證插入的數據必須是設定的范圍,其他類型都不可以 枚舉enum的存儲原理:實際上字段上所存儲的值並不是真正的字符串,而是字符串對應的下標:當系統設定枚舉類型的時候,會給枚舉中每個元素定義一個下標,這個下標規則從1開始 Enum(1=>‘男’,2=>’女’,3=>’保密’) 特性:在mysql中系統是自動進行類型轉換的:如果數據碰到“+、-、*、/”系統就會自動將數據轉換成數值:而普通字符串轉換成數值為0 既然實際enum字段存儲的結果是數值:那么在進行數據插入的時候,就可以使用對應的數值來進行。 枚舉的意義: 1、 規范數據本身,限定只能插入規定的數據項 2、 節省存儲空間 */ /* set集合:是一種將多個數據選項可以同時保存的數據類型,本質是將指定的項按照對應的二進制位來進行控制:1表示該選項被選中,0表示該選項沒有被選中。 基本語法:set(‘值1’,’值2’,’值3’…) 系統為set提供了多個字節進行保存,但是系統會自動計算來選擇具體的存儲單元 1個字節:set只能有8個選項 2個字節:set只能有16個選項 3個字節:set只能表示24個選項 8個字節:set可以表示64個選項 Set和enum一樣,最終存儲到數據字段中的依然是數字而不是真實的字符串 插入數據:可以插入多個數據,就是在數據插入的字符串中,使用對應的逗號“,”將選項進行隔開 數據選項所在的數據與數據插入的順序無關:最終都會變成選項對應的順序 數據在存儲的時候,如果被選中,那么對應的位的值就為1,否則為0 系統在進行存儲的時候會自動將得到的最終的二進制顛倒過來,然后再進行轉換成十進制存儲 既然是數值,那么就可以插入數值來代替實際插入數據 注意:數字插入的前提是對應的二進制位上都有對應的數據項 Set集合的意義: 1、 規范數據 2、 節省存儲空間 Enum:單選框 Set:復選框 */ 列屬性-------------------------------------------------------------------------------- 列屬性又稱之為字段屬性,在mysql中一共有6個屬性:null,默認值,列描述,主鍵,唯一鍵和自動增長 NULL屬性:代表字段為空 Default:默認值,當字段被設計的時候,如果允許默認條件下,用戶不進行數據的插入,那么就可以使用事先准備好的數據來填充:通常填充的是NULL 列描述:comment,是專門用於給開發人員進行維護的一個注釋說明 基本語法:comment ‘字段描述’; 查看Comment:必須通過查看表創建語句:show create table 表名 主鍵:primary key,在一張表中,有且只有一個字段,里面的值具有唯一性 主鍵創建方式: 隨表創建 1、 方案1:直接在需要當做主鍵的字段之后,增加primary key屬性來確定主鍵 2、 方案2:在所有字段之后增加primary key選項:primary key(字段信息) 表后創建 alter table 表名 add primary key(字段); 刪除主鍵:alter table 表名 drop primary key; 案例:有一張學生選修課表:一個學生可以選修多個選修課,一個選修課也可以由多個學生來選:但是一個學生在一個選修課中只有一個成績。 此時應該使用復合主鍵(一般中間表使用復合主鍵) create table score( stu_no char(10), corse_no char(10), primary key(stu_no,corse_no) )charset utf8; 主鍵一旦增加,那么對對應的字段有數據要求 1、 當前字段對應的數據不能為空; 2、 當前字段對應的數據不能有任何重復 主鍵分類采用的是主鍵所對應的字段的業務意義分類 業務主鍵:主鍵所在的字段,具有業務意義(學生ID,課程ID) 邏輯主鍵:自然增長的整型(應用廣泛) 自動增長:auto_increment,當給定某個字段該屬性之后,該列的數據在沒有提供確定數據的時候,系統會根據之前已經存在的數據進行自動增加后,填充數據。 通常自動增長用於邏輯主鍵。 自動增長的原理: 1、 在系統中有維護一組數據,用來保存當前使用了自動增長屬性的字段,記住當前對應的數據值,再給定一個指定的步長 2、 當用戶進行數據插入的時候,如果沒有給定值,系統在原始值上再加上步長變成新的數據 3、 自動增長的觸發:給定屬性的字段沒有提供值 4、 自動增長只適用於數值 語法:在字段之后增加一個屬性auto_increment 查看自增長:show create table 表名 自增長一旦觸發使用之后,會自動的在表選項中增加一個選項(一張表最多只能擁有一個自增長) 修改自增長 alter table my_auto auto_increment = 10; 自增長修改的時候,值可以較大,但是不能比當前已有的自增長字段的值小 刪除自增長:就是在字段屬性之后不再保留auto_increment,當用戶修改自增長所在字段時,如果沒有看到auto_increment屬性,系統會自動清除該自增長 alter table my_auto modify id int; 增加自增長 alter table my_auto modify id int auto_increment; 查看自增長初始變量 在系統中,有一組變量用來維護自增長的初始值和步長Show variables like ‘auto_increment%’; 1、 一張表只有一個自增長:自增長會上升到表選項中 2、 如果數據插入中沒有觸發自增長(給定了數據),那么自增長不會表現 唯一鍵:unique key,用來保證對應的字段中的數據唯一的。 主鍵也可以用來保證字段數據唯一性,但是一張表只有一個主鍵。 1、 唯一鍵在一張表中可以有多個。 2、 唯一鍵允許字段數據為NULL,NULL可以有多個(NULL不參與比較) 創建唯一鍵與創建主鍵非常類似 1、 直接在表字段之后增加唯一鍵標識符:unique[ key] 2、 在所有的字段之后使用unique key(字段列表); 3、 在創建完表之后也可以增加唯一鍵:alter table 表名 add unique key(字段列表); 查看唯一鍵:desc 表名 刪除唯一鍵:alter table 表名 drop index 唯一鍵名字; 修改唯一鍵:先刪除后增加 復合唯一鍵 唯一鍵與主鍵一樣可以使用多個字段來共同保證唯一性; 一般主鍵都是單一字段(邏輯主鍵),而其他需要唯一性的內容都是由唯一鍵來處理。 表關系-------------------------------------------------------------------------------------------------------- 表關系:表與表之間(實體)有什么樣的關系,每種關系應該如何設計表結構。 一對一:一張表中的一條記錄與另外一張表中最多有一條明確的關系:通常,此設計方案保證兩張表中使用同樣的主鍵即可 一對多:通常也叫作多對一的關系。通常一對多的關系設計的方案,在“多”關系的表中去維護一個字段,這個字段是“一”關系的主鍵。 多對多:一張表中的一條記錄在另外一張表中可以匹配到多條記錄,反過來也一樣。 多對多的關系如果按照多對一的關系維護:就會出現一個字段中有多個其他表的主鍵,在訪問的時候就會帶來不便。 既然通過兩張表自己增加字段解決不了問題,那么就通過第三張表來解決。 多對多解決方案;增加一個中間表,讓中間表與對應的其他表形成兩個多對一的關系:多對一的解決方案是在“多”表中增加“一”表對應的主鍵字段。 高級數據操作-------------------------------------------------------------------------------------------------- 新增數據 1、主鍵沖突更新:類似插入數據語法,如果插入的過程中主鍵沖突,那么采用更新方法。 Insert into 表名 [(字段列表)] values(值列表) on duplicate key update 字段 = 新值; 2、 主鍵沖突替換:當主鍵沖突之后,干掉原來的數據,重新插入進去。 Replace into [(字段列表)] values(值列表); 蠕蟲復制:一分為二,成倍的增加。從已有的數據中獲取數據,並且將獲取到的數據插入到數據表中。 基本語法: Insert into 表名 [(字段列表)] select */字段列表 from 表; insert into my_simple(name) select name from my_simple; 注意: 1、 蠕蟲復制的確通常是重復數據,沒有太大業務意義:可以在短期內快速增加表的數據量,從而可以測試表的壓力,還可以通過大量數據來測試表的效率(索引) 2、 蠕蟲復制雖好,但是要注意主鍵沖突。 更新數據 1、 在更新數據的時候,特別要注意:通常一定是跟隨條件更新 Update 表名 set 字段名 = 新值 where 判斷條件; 2、 如果沒有條件,是全表更新數據。但是可以使用limit 來限制更新的數量; Update 表名 set 字段名 = 新值 [where 判斷條件] limit 數量; 例如改變4個a變成e: Update my_simple set name = ‘e’ where name = ‘a’ limit 4; 刪除數據 1、 刪除數據的時候盡量不要全部刪除,應該使用where進行 判定; 2、 刪除數據的時候可以使用limit來限制要刪除的具體數量 Delete刪除數據的時候無法重置auto_increment Mysql有一個能夠重置表選項中的自增長的語法:truncate 表名,相當於先drop再create Where字句:用來從數據表獲取數據的時候,然后進行條件篩選。 數據獲取原理:針對表去對應的磁盤處獲取所有的記錄(一條條),where的作用就是在拿到一條結果就開始進行判斷,判斷是否符合條件:如果符合就保存下來,如果不符合直接舍棄(不放到內存中) Where是通過運算符進行結果比較來判斷數據。 Group by表示分組的含義:根據指定的字段,將數據進行分組:分組的目標是為了統計 基本語法: group by 字段名; Group by是為了分組后進行數據統計的,如果只是想看數據顯示,那么group by沒什么含義:group by將數據按照指定的字段分組之后,只會保留每組的第一條記錄。 利用一些統計函數:(聚合函數) count():統計每組中的數量,如果統計目標是字段,那么不統計為空NULL字段,如果為*那么代表統計記錄 avg():求平均值 sum():求和 max():求最大值 min():求最小值 Group_concat():為了將分組中指定的字段進行合並(字符串拼接) 多分組:將數據按照某個字段進行分組之后,對已經分組的數據進行再次分組 基本語法:group by 字段1,字段2; //先按照字段1進行排序,之后將結果再按照字段2進行排序,以此類推。 Mysql中,分組默認有排序的功能:按照分組字段進行排序,默認是升序 基本語法:group by 字段 [asc|desc],字段 [asc|desc] 回溯統計 當分組進行多分組之后,往上統計的過程中,需要進行層層上報,將這種層層上報統計的過程稱之為回溯統計:每一次分組向上統計的過程都會產生一次新的統計數據,而且當前數據對應的分組字段為NULL。 基本語法:group by 字段 [asc|desc] with rollup; Having的本質和where一樣,是用來進行數據條件篩選。 Having在group by分組之后,可以使用聚合函數或者字段別名(where是從表中取出數據,別名是在數據進入到內存之后才有的) 強調:having是在group by之后,group by是在where之后:where的時候表示將數據從磁盤拿到內存,where之后的所有操作都是內存操作。 Order by排序:根據校對規則對數據進行排序 基本語法:order by 字段 [asc|desc]; //asc升序,默認的 Order by也可以像group by一樣進行多字段排序:先按照第一個字段進行排序,然后再按照第二個字段進行排序。 Order by 字段1 規則,字段2 規則; Limit限制子句:主要是用來限制記錄數量獲取 純粹的限制獲取的數量:從第一條到指定的數量 基本語法: limt 數量; Limit通常在查詢的時候如果限定為一條記錄的時候,使用的比較多:有時候獲取多條記錄並不能解決業務問題,但是會增加服務器的壓力。 分頁 利用limit來限制獲取指定區間的數據。 基本語法:limit offset,length; //offset偏移量:從哪開始,length就是具體的獲取多少條記錄 Mysql中記錄的數量從0開始 Limit 0,2; 表示獲取前兩條記錄 注意:limit后面的length表示最多獲取對應數量,但是如果數量不夠,系統不會強求 運算符------------------------------------------------------------------------------- 算術運算符 +、-、*、/、% 基本算術運算:通常不在條件中使用,而是用於結果運算(select 字段中) 比較運算符 >、>=、<、<=、=、<> 通常是用來在條件中進行限定結果 =:在mysql中,沒有對應的 ==比較符號,就是使用=來進行相等判斷 <=>:相等比較 特殊應用:就是在字段結果中進行比較運算 在mysql中沒有布爾值,1代表true,2代表false 在條件判斷的時候,還有有對應的比較運算符:計算區間 Between 條件1 and 條件2; Between中條件1必須小於條件2,反過來不可以 邏輯運算符 and、or、not and:邏輯與 or:邏輯或 not:邏輯非 In運算符 In:在什么里面,是用來替代=,當結果不是一個值,而是一個結果集的時候 基本語法: in (結果1,結果2,結果3…),只要當前條件在結果集中出現過,那么就成立 Is運算符 Is是專門用來判斷字段是否為NULL的運算符 基本語法:is null / is not null Like運算符 Like運算符:是用來進行模糊匹配(匹配字符串) 基本語法:like ‘匹配模式’; 匹配模式中,有兩種占位符: _:匹配對應的單個字符 %:匹配多個字符 聯合查詢--------------------------------------------------- 聯合查詢是可合並多個相似的選擇查詢的結果集。等同於將一個表追加到另一個表,從而實現將兩個表的查詢組合到一起,使用謂詞為UNION或UNION ALL。 聯合查詢:將多個查詢的結果合並到一起(縱向合並):字段數不變,多個查詢的記錄數合並。 基本語法: Select 語句 Union [union 選項] Select 語句; Union選項:與select選項基本一樣 Distinct:去重,去掉完全重復的數據(默認的) All:保存所有的結果 注意細節:union理論上只要保證字段數一樣,不需要每次拿到的數據對應的字段類型一致。永遠只保留第一個select語句對應的字段名字。 1、 在聯合查詢中,如果要使用order by,那么對應的select語句必須使用括號括起來 2、 orderby在聯合查詢中若要生效,必須配合使用limit:而limit后面必須跟對應的限制數量(通常可以使用一個較大的值:大於對應表的記錄數) 連接查詢------------------------------------------------------------------ 連接查詢:將多張表連到一起進行查詢(會導致記錄數行和字段數列發生改變) 連接查詢的意義: 在關系型數據庫設計過程中,實體(表)與實體之間是存在很多聯系的。在關系型數據庫表的設計過程中, 遵循着關系來設計:一對一,一對多和多對多,通常在實際操作的過程中,需要利用這層關系來保證數據的完整性。 連接查詢一共有以下幾類: 交叉連接 內連接 外連接:左外連接(左連接)和右外連接(右連接) 自然連接 交叉連接:將兩張表的數據與另外一張表彼此交叉 原理: 1、 從第一張表依次取出每一條記錄 2、 取出每一條記錄之后,與另外一張表的全部記錄挨個匹配 3、 沒有任何匹配條件,所有的結果都會進行保留 4、 記錄數 = 第一張表記錄數 * 第二張表記錄數;字段數 = 第一張表字段數 + 第二張表字段數(笛卡爾積) 基本語法:表1 cross join 表2; select * from mytest cross join mystu; 應用 交叉連接產生的結果是笛卡爾積,沒有實際應用。 本質:from 表1,表2; 內連接:inner join,從一張表中取出所有的記錄去另外一張表中匹配:利用匹配條件進行匹配,成功了則保留,失敗了放棄。 原理 1、 從第一張表中取出一條記錄,然后去另外一張表中進行匹配 2、 利用匹配條件進行匹配: 2.1 匹配到:保留,繼續向下匹配 2.2 匹配失敗:向下繼續,如果全表匹配失敗,結束 基本語法:表1 [inner] join 表2 on 匹配條件; 1、 如果內連接沒有條件(允許),那么其實就是交叉連接(避免) 2、 使用匹配條件進行匹配:select * from mystu inner join myclass on mystu.class_id = myclass.id; 3、 因為表的設計通常容易產生同名字段,尤其是ID,所以為了避免重名出現錯誤,通常使用表名.字段名,來確保唯一性 4、 通常,如果條件中使用到對應的表名,而表名通常比較長,所以可以通過表別名來簡化 5、 內連接匹配的時候,必須保證匹配到才會保存 6、 內連接因為不強制必須使用匹配條件(on)因此可以在數據匹配完成之后,使用where條件來限制,效果與on一樣(建議使用on) 應用 內連接通常是在對數據有精確要求的地方使用:必須保證兩種表中都能進行數據匹配。 外連接 外鏈接:outer join,按照某一張表作為主表(表中所有記錄在最后都會保留),根據條件去連接另外一張表,從而得到目標數據。 外連接分為兩種:左外連接(left join),右外連接(right join) 左連接:左表是主表 右連接:右表是主表 原理 1、 確定連接主表:左連接就是left join左邊的表為主表;right join就是右邊為主表 2、 拿主表的每一條記錄,去匹配另外一張表(從表)的每一條記錄 3、 如果滿足匹配條件:保留;不滿足即不保留 4、 如果主表記錄在從表中一條都沒有匹配成功,那么也要保留該記錄:從表對應的字段值都未NULL 基本語法: 左連接:主表 left join 從表 on 連接條件; 右連接:從表 right join 主表 on連接條件; 特點: 1、只要sql查詢時表在左邊,表的字段就在左邊;只要表在右邊,表的字段就在右邊————(左右:以join為界,join左邊為左表,右邊為右表) 2、外連接中主表數據記錄一定會保存:連接之后不會出現記錄數少於主表(內連接可能) 3、左連接和右連接其實可以互相轉換,但是數據對應的位置(表順序)會改變 應用 非常常用的一種獲取的數據方式:作為數據獲取對應主表以及其他數據(關聯) Using關鍵字 是在連接查詢中用來代替對應的on關鍵字的,進行條件匹配。 原理 1、 在連接查詢時,使用on的地方用using代替 2、 使用using的前提是對應的兩張表連接的字段是同名(類似自然連接自動匹配) 3、 如果使用using關鍵字,那么對應的同名字段,最終在結果中只會保留一個。 例如:select * from mystu inner join myclass using(class_id);//此處class_id在mystu和myclass中為同名字段 子查詢----------------------------------------------------------------- 子查詢:sub query 子查詢是一種常用計算機語言SELECT-SQL語言中嵌套查詢下層的程序模塊。當一個查詢是另一個查詢的條件時,稱之為子查詢。 子查詢:指在一條select語句中,嵌入了另外一條select語句,那么被嵌入的select語句稱之為子查詢語句。 主查詢:主要的查詢對象,第一條select語句,確定的用戶所有獲取的數據目標(數據源),以及要具體得到的字段信息。 子查詢和主查詢的關系 1、 子查詢是嵌入到主查詢中的; 2、 子查詢的輔助主查詢的:要么作為條件,要么作為數據源 3、 子查詢其實可以獨立存在:是一條完整的select語句 子查詢分類 按功能分 標量子查詢:子查詢返回的結果是一個數據(一行一列) 列子查詢:返回的結果是一列(一列多行) 行子查詢:返回的結果是一行(一行多列) 表子查詢:返回的結果是多行多列(多行多列) Exists子查詢:返回的結果1或者0(類似布爾操作) 按位置分 Where子查詢:子查詢出現的位置在where條件中 From子查詢:子查詢出現的位置在from數據源中(做數據源) 標量子查詢:子查詢得到結果是一個數據(一行一列) 基本語法:select * from 數據源 where 條件判斷 =/<> (select 字段名 from 數據源 where 條件判斷); //子查詢得到的結果只有一個值 列子查詢:子查詢得到的結果是一列數據(一列多行) 基本語法:主查詢 where 條件 in (列子查詢); 行子查詢:子查詢返回的結果是一行多列 行元素:字段元素是指一個字段對應的值,行元素對應的就是多個字段:多個字段合起來作為一個元素參與運算,把這種情況稱之為行元素。 基本語法: 主查詢 where 條件[(構造一個行元素)] = (行子查詢); 例如:獲取班級上年齡最大,且身高最高的學生 1、求出班級年齡最大值 2、求出班級身高最大值 3、求出對應的學生 select * from my_student where stu_age = max(stu_age) and stu_height = max(stu_height)--錯誤:where后不能使用聚合函數 select * from my_student where (stu_age,stu_height) = (select max(stu_age),max(stu_height) from my_student); 常見的三個子查詢 標量子查詢、列子查詢和行子查詢:都屬於where子查詢 表子查詢:子查詢返回的結果是多行多列,表子查詢與行子查詢非常相似,只是行子查詢需要產生行元素,而表子查詢沒有。 行子查詢是用於where條件判斷:where子查詢 表子查詢是用於from數據源:from子查詢 基本語法: Select 字段表 from (表子查詢) as 別名 [where] [group by] [having] [order by] [limit]; 案例:獲取每個班上最高身高的學生(一個) 1、將每個班最高的學生排在最前面:order by 2、再針對結果進行group by:保留每組第一個 select * from (select * from my_student order by stu_height desc) as temp group by class_id; Exists子查詢:查詢返回的結果只有0或者1,1代表成立,0代表不成立 基本語法:where exists(查詢語句); //exists就是根據查詢得到的結果進行判斷:如果結果存在,那么返回1,否則返回0 Where 1:永遠為真 案例:有學生的所有班級 表:mystu和myclass select * from myclass as c where exists(select stu_id from mystu as s where c.class_id=s.class_id); /*建表語句: DROP TABLE IF EXISTS `myclass`; CREATE TABLE `myclass` ( `class_id` int(10) DEFAULT NULL, `class_name` varchar(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of myclass -- ---------------------------- INSERT INTO `myclass` VALUES ('1', '一班'); INSERT INTO `myclass` VALUES ('2', '二班'); INSERT INTO `myclass` VALUES ('3', '三班'); DROP TABLE IF EXISTS `mystu`; CREATE TABLE `mystu` ( `stu_id` int(11) NOT NULL, `stu_name` varchar(10) DEFAULT NULL, `stu_no` varchar(10) DEFAULT NULL, `class_id` int(10) DEFAULT NULL, PRIMARY KEY (`stu_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of mystu -- ---------------------------- INSERT INTO `mystu` VALUES ('1', '劉飛', '2016081038', '1'); INSERT INTO `mystu` VALUES ('2', '張飛', '2016081036', '1'); INSERT INTO `mystu` VALUES ('3', 'wolf', '2016081037', '2'); INSERT INTO `mystu` VALUES ('4', 'lf', '2016081035', '4'); */ 子查詢中特定關鍵字的使用:如果對應的匹配字段有NULL,那么不參與匹配 in 主查詢 where 條件 in (列子查詢); any任意一個 = any(列子查詢):條件在查詢結果中有任意一個匹配即可,等價於in <>any(列子查詢):條件在查詢結果中不等於任意一個 1 =any(1,2,3) ===== true 1 <>any(1,2,3) ===== true some 與any完全一樣:在國外,some與any的正面含義一致,但是否定就大不相同:not any與not some 開發者為了讓對應的使用者不要在語法上糾結:重新設計了some all = all(列子查詢):等於里面所有 <>all(列子查詢):不等於其中所有 數據庫備份--------------------------------- 整庫數據備份也叫SQL數據備份:備份的結果都是SQL指令 在Mysql中提供了一個專門用於備份SQL的客戶端:mysqldump.exe SQL備份是一種mysql非常常見的備份與還原方式,SQL備份不只是備份數據,還備份對應的SQL指令(表結構):即便是數據庫遭到毀滅性的破壞(數據庫被刪),那么利用SQL備份依然可以實現數據還原。 SQL備份因為需要備份結構,因此產生的備份文件特別大,因此不適合特大型數據備份,也不適合數據變換頻繁型數據庫備份。 SQL備份用到的是專門的備份客戶端,因此還沒與數據庫服務器進行連接。 基本語法:mysqldump/mysqldump.exe -hPup 數據庫名字 [表1 [表2…]] > 備份文件地址 備份可以有三種形式: 1、 整庫備份(只需要提供數據庫名字) mysqldump.exe -hlocalhost -P3306 -utoot -p5445abcd mydatabase > c:/server/temp/mydatabase.sql 2、 單表備份:數據庫后面跟一張表 3、 多表備份:數據庫后跟多張表 mysqldump -hlocalhost -P3306 -utoot -p5445abcd mydatabase mystu myclass > c:/server/temp/stu_class.sql 數據還原 Mysql提供了多種方式來實現:兩種 Mysqldump備份的數據中沒有關於數據庫本身的操作,都是針對表級別的操作:當進行數據(SQL還原),必須指定數據庫 1、 利用mysql.exe客戶端:沒有登錄之前,可以直接用該客戶端進行數據還原 Mysql.exe –hPup 數據庫 < 文件位置 2、 在SQL指令,提供了一種導入SQL指令的方式 Source SQL文件位置; //必須先進入到對應的數據庫 如:source c:/server/temp/stu_class; 3、 人為操作:打開備份文件,復制所有SQL指令,然后到mysql.exe客戶端中去粘貼執行。(不推薦) 用戶管理--------------------------------------------- 創建用戶:理論上講可以采用兩種方式創建用戶: 1、 直接使用root用戶在mysql.user表中插入記錄(不推薦) 2、 專門創建用戶的SQL指令 基本語法:create user 用戶名 identified by ‘明文密碼’; 用戶:用戶名@主機地址 主機地址:’’ / ‘%’ 簡化版創建用戶(誰都可以訪問,不需要密碼):create user 用戶名; 刪除用戶 注意:mysql中user是帶着host本身的(具有唯一性) 基本語法:drop user 用戶名@host; 修改用戶密碼 Mysql中提供了多種修改的方式:基本上都必須使用對應提供的一個系統函數:password(),需要靠該函數對密碼進行加密處理。 1、 使用專門的修改密碼的指令 基本語法:set password for 用戶 = password(‘新的明文密碼’); 2、 使用更新語句update來修改表 基本語法:update mysql.user set password = password(‘新的明文密碼’) where user = ‘’ and host= ‘’; 權限管理-------------------------------------------------------- 在mysql中將權限管理分為三類: 1、 數據權限:增刪改查(select\update\delete\insert) 2、 結構權限:結構操作(create\drop) 3、 管理權限:權限管理(create user\grant\revoke):通常只給管理員如此權限 授予權限:grant 將權限分配給指定的用戶 --基本語法:grant 權限列表 on 數據庫/*.表名/* to 用戶; 權限列表:使用逗號分隔,但是可以使用all privileges代表全部權限 數據庫.表名:可以是單表(數據庫名字.表名),可以是具體某個數據庫(數據庫.*),也可以整庫(*.*) 用戶被分配權限以后不需要退出就可以看到效果 具體權限查看:單表權限只能看到數據庫中的一張表 取消權限:revoke 權限回收:將權限從用戶手中收回 --基本語法:revoke 權限列表/all privileges on 數據庫/*.表/* from 用戶; 權限回收,同樣不需要刷新,用戶馬上就會感受到 刷新權限:flush Flush:刷新,將當前對用戶的權限操作,進行一個刷新,將操作的具體內容同步到對應的表中。 基本語法:flush privileges; ------------------------------------------------------------- 密碼丟失的解決方案 如果忘記了root用戶密碼,就需要去找回或者重置root用戶密碼 1、 停止服務:net stop mysql 2、 重新啟動服務:mysqld.exe --skip-grant-tables //啟動服務器但是跳過權限 3、 當前啟動的服務器沒有權限概念:非常危險,任何客戶端,不需要任何用戶信息都可以直接登錄,而且是root權限:新開客戶端,使用mysql.exe登錄即可 4、 修改root用戶的密碼:指定 用戶名@host update mysql.user set password = password('5445abcd') where user = 'root' and host = 'localhost'; 5、 趕緊關閉服務器(直接結束進程),重啟服務:net start mysql; 外鍵-------------------------------------------------------- 外鍵:foreign key 一張表(A)中有一個字段,保存的值指向另外一張表(B)的主鍵 B:主表 A:從表 增加外鍵 1、 方案1:在創建表的時候增加外鍵(類似主鍵) 基本語法:在字段之后增加一條語句 [constraint `外鍵名`] foreign key(外鍵字段) references 主表(主鍵); MUL:多索引,外鍵本身是一個索引,外鍵要求外鍵字段本身也是一種普通索引 2、 方案2:在創建表后增加外鍵 Alter table 從表 add [constraint `外鍵名`] foreign key(外鍵字段) references 主表(主鍵); 修改&刪除外鍵 外鍵不允許修改,只能先刪除后增加 基本語法:alter table 從表 drop foreign key 外鍵名字; 外鍵不能刪除產生的普通索引,只會刪除外鍵自己;如果想刪除對應的索引:alter table 表名 drop index 索引名字; 外鍵基本要求 1、 外鍵字段需要保證與關聯的主表的主鍵字段類型完全一致; 2、 基本屬性也要相同 3、 如果是在表后增加外鍵,對數據還有一定的要求(從表數據與主表的關聯關系) 4、 外鍵只能使用innodb存儲引擎:myisam不支持 外鍵約束:通過建立外鍵關系之后,對主表和從表都會有一定的數據約束效率。 約束的基本概念 1、 當一個外鍵產生時:外鍵所在的表(從表)會受制於主表數據的存在從而導致數據不能進行某些不符合規范的操作(不能插入主表不存在的數據); 2、 如果一張表被其他表外鍵引入,那么該表的數據操作就不能隨意:必須保證從表數據的有效性(不能隨便刪除一個被從表引入的記錄) 外鍵約束的概念 可以在創建外鍵的時候,對外鍵約束進行選擇性的操作。 基本語法: add foreign key(外鍵字段) references 主表(主鍵) on 約束模式; 約束模式有三種: 1、 district:嚴格模式,默認的,不允許操作 2、 cascade:級聯模式,一起操作,主表變化,從表數據跟着變化 3、 set null:置空模式,主表變化(刪除),從表對應記錄設置為空:前提是從表中對應的外鍵字段允許為空 外鍵約束主要約束的對象是主表操作:從表就是不能插入主表不存在的數據 通常在進行約束時候的時候,需要指定操作:update和delete 常用的約束模式: on update cascade, on delete set null,更新級聯,刪除置空 約束作用 保證數據的完整性:主表與從表的數據要一致 正是因為外鍵有非常強大的數據約束作用,而且可能導致數據在后台變化的不可控。導致程序在進行設計開發邏輯的時候,沒有辦法去很好的把握數據(業務),所以外鍵比較少使用。 視圖-------------------------------------------------------------------------- 創建視圖 視圖的本質是SQL指令(select語句) 基本語法:create view 視圖名字 as select指令; //可以是單表數據,也可以是連接查詢,聯合查詢或者子查詢 查看視圖結構:視圖本身是虛擬表,所以關於表的一些操作都適用於視圖 Show tables/show create table[view]/desc 視圖名字; 視圖是一張虛擬表:可以直接把視圖當做“表”操作,但是視圖本身沒有數據,是臨時執行select語句得到對應的結果。視圖主要用戶查詢操作。 基本語法:select 字段列表 from 視圖名字 [子句]; 修改視圖 修改視圖:本質是修改視圖對應的查詢語句 基本語法:alter view 視圖名字 as 新select指令; 刪除視圖 基本語法:drop view 視圖名字; 事務------------------------------------------- 事務概念:事務(Transaction)是訪問並可能更新數據庫中各種數據項的一個程序執行單元(unit)。 事務通常由高級數據庫操縱語言或編程語言書寫的用戶程序的執行所引起。 事務由事務開始(begin transaction)和事務結束(end transaction)之間執行的全體操作組成。 事務基本原理 基本原理:Mysql允許將事務統一進行管理(存儲引擎INNODB),將用戶所做的操作,暫時保存起來,不直接放到數據表(更新),等到用於確認結果之后再進行操作。 事務在mysql中通常是自動提交的,但是也可以使用手動事務。 自動事務:autocommit,當客戶端發送一條SQL指令(寫操作:增刪改)給服務器的時候,服務器在執行之后,不用等待用戶反饋結果,會自動將結果同步到數據表。 證明:利用兩個客戶端,一個客戶端執行SQL指令,另外一個客戶端查看執行結果 自動事務:系統做了額外的步驟來幫助用戶操作,系統是通過變量來控制的。Autocommit Show variables like ‘autocommit%’; 關閉自動事務:關閉之后系統就不在幫助用戶提交結果了 Set autocommit = Off; 開啟自動事務:set autocommit = on; 一旦自動事務關閉,那么需要用戶提供是否同步的命令 Commit:提交(同步到數據表:事務也會被清空) Rollback:回滾 (commit和rollback只要執行一個,就會清空之前的操作,不要了) 通常,我們不會關閉自動事務:這樣操作太麻煩。因此只會在需要使用事務處理的時候,才會進行操作(手動事務) 手動事務:不管是開始還是過程還是結束都需要用戶(程序員),手動的發送事務操作指令來實現。 手動事務對應的命令: 1、 start transaction; //開啟事務:從這條語句開始,后面的所有語句都不會直接寫入到數據表(保存在事務日志中) 2、 事務處理:多個寫指令構成 3、 事務提交:commit/rollback,到這個時候所有的事務才算結束 回滾點:savepoint,當有一系列事務操作時,而其中的步驟如果成功了,沒有必要重新來過,可以在某個點(成功),設置一個記號(回滾點),然后如果后面有失敗,那么可以回到這個記號位置。 增加回滾點:savepoint 回滾點名字; //字母數字和下划線構成 回到回滾點:rollback to 回滾點名字; //那個記號(回滾點)之后的所有操作沒有了 注意:在一個事務處理中,如果有很多個步驟,那么可以設置多個回滾點。但是如果回到了前面的回滾點,后面的回滾點就失效; 事務特點 事務應該具有4個屬性:原子性、一致性、隔離性、持久性。這四個屬性通常稱為ACID特性。 原子性(atomicity)。一個事務是一個不可分割的工作單位,事務中包括的諸操作要么都做,要么都不做。 事務從start transaction起到提交事務(commit或者rollback),要么所有的操作都成功,要么就是所有的操作都失敗; 一致性(consistency)。事務必須是使數據庫從一個一致性狀態變到另一個一致性狀態。一致性與原子性是密切相關的。 數據表中的數據修改,要么是所有操作一次性修改,要么是根本不懂 隔離性(isolation)。一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的數據對並發的其他事務是隔離的,並發執行的各個事務之間不能互相干擾。 如果一個客戶端在使用事務操作一個數據(可能是一行/整表)的時候,另外一個客戶端不能對該數據進行操作 什么時候是行被隔離?什么時候是整表被隔離? 說明:如果條件中使用了索引(主鍵),那么系統是根據主鍵直接找到某條記錄,這個時候與其他記錄無關,那么只隔離一條記錄;反之,如果說系統是通過全表檢索(每一條記錄都去檢查:沒有索引),
被檢索的所有數據都會被鎖定(整表) 持久性(durability)。持久性也稱永久性(permanence),指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響。 變量------------------------------------------------------------ 變量:系統變量、會話變量、局部變量 Mysql本質是一種編程語言,需要很多變量來保存數據。Mysql中很多的屬性控制都是通過mysql中固有的變量來實現的。 系統內部定義的變量,系統變量針對所有用戶(MySQL客戶端)有效。 查看系統所有變量:show variables [like ‘pattern’]; Mysql允許用戶使用select查詢變量的數據值(系統變量) 基本語法:select @@變量名; 修改系統變量:分為兩種修改方式 1、 局部修改(會話級別):只針對當前自己客戶端當次連接有效 基本語法:set 變量名 = 新值; 2、 全局修改:針對所有的客戶端,“所有時刻”都有效 基本語法:set global 變量名 = 值; || set @@global.變量名 = 值; 全局修改之后:所有連接的客戶端並沒發現改變?全局修改只針對新客戶端生效(正在連着的無效) 注意:如果想要本次連接對應的變量修改有效,那么不能使用全局修改,只能使用會話級別修改(set 變量名 = 值); 會話變量 會話變量也稱之為用戶變量,會話變量跟mysql客戶端是綁定的,設置的變量,只對當前用戶使用的客戶端生效。 定義用戶變量:set @變量名 = 值; 在mysql中因為沒有比較符號==,所以是用=代替比較符號:有時候在賦值的時候,會報錯:mysql為了避免系統分不清是賦值還是比較:特定增加一個變量的賦值符號: := Set @變量名 := 值; Mysql是專門存儲數據的:允許將數據從表中取出存儲到變量中:查詢得到的數據必須只能是一行數據(一個變量對應一個字段值):Mysql沒有數組。 1、 賦值且查看賦值過程:select @變量1 := 字段1,@變量2 := 字段2 from 數據表 where 條件; 2、 只賦值,不看過程:select 字段1,字段2… from 數據源 where條件 into @變量1,@變量2… 查看變量:select @變量名; 局部變量 作用范圍在begin到end語句塊之間。在該語句塊里設置的變量,declare語句專門用於定義局部變量。 1、 局部變量是使用declare關鍵字聲明 2、 局部變量declare語句出現的位置一定是在begin和end之間(beginend是在大型語句塊中使用:函數/存儲過程/觸發器) 3、 聲明語法:declare 變量名 數據類型 [屬性]; 流程結構:代碼的執行順序-------------------------------------------------------------------------- If分支 基本語法 If在Mysql中有兩種基本用法 1、 用在select查詢當中,當做一種條件來進行判斷 基本語法:if(條件,為真結果,為假結果) select *,if(stu_age > 20,'符合','不符合') as judge from my_student; 2、 用在復雜的語句塊中(函數/存儲過程/觸發器) 基本語法 If 條件表達式 then 滿足條件要執行的語句; End if; 復合語法:代碼的判斷存在兩面性,兩面都有對應的代碼執行。 基本語法: If 條件表達式 then 滿足條件要執行的語句; Else 不滿足條件要執行的語句; //如果還有其他分支(細分),可以在里面再使用if If 條件表達式 then //滿足要執行的語句 End if; End if; While循環 基本語法:循環體都是需要在大型代碼塊中使用 基本語法: While 條件 do 要循環執行的代碼; End while; 結構標識符:為某些特定的結構進行命名,然后為的是在某些地方使用名字 基本語法 標識名字:While 條件 do 循環體 End while [標識名字]; 標識符的存在主要是為了循環體中使用循環控制。在mysql中沒有continue和break,有自己的關鍵字替代: Iterate:迭代,就是以下的代碼不執行,重新開始循環(continue) Leave:離開,整個循環終止(break) 語法: 標識名字:While 條件 do If 條件判斷 then 循環控制; Iterate/leave 標識名字; End if; 循環體 End while [標識名字]; 函數---------------------------------------------------------------------------------------- 在mysql中,函數分為兩類:系統函數(內置函數)和自定義函數 不管是內置函數還是用戶自定義函數,都是使用select 函數名(參數列表); 內置函數 字符串函數 Char_length():判斷字符串的字符數 Length():判斷字符串的字節數(與字符集) select char_length('你好中國'),length('你好中國'); Concat():連接字符串 Instr():判斷字符在目標字符串中是否存在,存在返回其位置,不存在返回0 Lcase():全部小寫 Left():從左側開始截取,直到指定位置(位置如果超過長度,截取所有) Ltrim():消除左邊對應的空格 Mid():從中間指定位置開始截取,如果不指定截取長度,直接到最后 時間函數 Now():返回當前時間,日期 時間 Curdate():返回當前日期 Curtime():返回當前時間 Datediff():判斷兩個日期之間的天數差距,參數日期必須使用字符串格式(用引號) Date_add(日期,interval 時間數字 type):進行時間的增加 Type:day/hour/minute/second Unix_timestamp():獲取時間戳 From_unixtime():將指定時間戳轉換成對應的日期時間格式 數學函數 Abs():絕對值 Ceiling():向上取整 Floor():向下取整 Pow():求指數,誰的多少次方 Rand():獲取一個隨機數(0-1之間) Round():四舍五入函數 其他函數 Md5():對數據進行md5加密(mysql中的md5與其他任何地方的md5加密出來的內容是完全相同的) Version():獲取版本號 Databse():顯示當前所在數據庫 UUID():生成一個唯一標識符(自增長):自增長是單表唯一,UUID是整庫(數據唯一同時空間唯一) 自定義函數 自定義函數:用戶自己定義的函數 函數:實現某種功能的語句塊(由多條語句組成) 1、 函數內部的每條指令都是一個獨立的個體:需要符合語句定義規范:需要語句結束符分號; 2、 函數是一個整體,而且函數是在調用的時候才會被執行,那么當設計函數的時候,意味着整體不能被中斷; 3、 Mysql一旦見到語句結束符分號,就會自動開始執行 解決方案:在定義函數之前,嘗試修改臨時的語句結束符 基本語法:delimiter 修改臨時語句結束符:delimiter 新符號[可以使用系統非內置即可$$] 中間為正常SQL指令:使用分號結束(系統不會執行:不認識分號) 使用新符號結束 修改回語句結束符:delimiter ; 創建函數 自定義函數包含幾個要素:function關鍵字,函數名,參數(形參和實參[可選]),確認函數返回值類型,函數體,返回值 函數定義基本語法: 修改語句結束符 Create function 函數名(形參) returns 返回值類型 Begin //函數體 Return 返回值數據; //數據必須與結構中定義的返回值類型一致 End 語句結束符 修改語句結束符(改回來) --創建自定義函數 ① --修改語句結束符 delimiter $$ create function my_fun1() returns int begin return 10; end $$ --修改語句結束符(改回來) delimiter ; ② 並不是所有的函數都需要begin和end:如果函數體本身只有一條指令(return),那么可以省略begin和end 最簡函數 create function my_fun2() returns int return 100; ③ 形參:在mysql中需要為函數的形參指定數據類型(形參本身可以有多個) 基本語法:變量名 字段類型 create function my_fun3(int_1 int,int_2 int) returns int return int_1 + int_2; 查看函數 1、 可以通過查看function狀態,查看所有的函數 Show function status [like ‘pattern’]; 2、 查看函數的創建語句:show create function 函數名字; 調用函數 自定義函數的調用與內置函數的調用是一樣的:select 函數名(實參列表); 刪除函數:drop function 函數名; 注意事項 1、 自定義函數是屬於用戶級別的:只有當前客戶端對應的數據庫中可以使用 2、 可以在不同的數據庫下看到對應的函數,但是不可以調用 3、 自定義函數:通常是為了將多行代碼集合到一起解決一個重復性的問題 4、 函數因為必須規范返回值:那么在函數內部不能使用select指令:select一旦執行就會得到一個結果(result set):select 字段 into @變量;(唯一可用) create function my_sum(end_value int) returns int begin --聲明變量():如果使用declare聲明變量:必須在函數體其他語句之前 declare res int default 0; declare i int default 1; --循環處理 mywhile:while i <= end_value do --判斷當前的數據是否合理 if i % 5 = 0 then --5的倍數不要 set i = i + 1; iterate mywhile; end if; --修改變量:累加結果 set res = res + i; --mysql中沒有++ set i = i + 1; end while mywhile; return res; end; create function my_sum(end_value int) returns int begin declare res int default 0; declare i int default 1; mywhile:while i <= end_value do if i % 5 = 0 then set i = i + 1; iterate mywhile; end if; set res = res + i; set i = i + 1; end while mywhile; return res; end; 變量作用域---------------------------------------------------------------- 局部作用域 使用declare關鍵字聲明(在結構體內:函數/存儲過程/觸發器),而且只能在結構體內部使用 1、 declare關鍵字聲明的變量沒有任何符號修飾,就是普通字符串,如果在外部訪問該變量,系統會自動認為是字段 會話作用域 用戶定義的,使用@符號定義的變量,使用set關鍵字 會話作用域:在當前用戶當次連接有效,只要在本連接之中,任何地方都可以使用(可以在結構內部,也可以跨庫) 會話變量可以在函數內部使用 會話變量可以跨庫 全局作用域 所有的客戶端所有的連接都有效:需要使用全局符號來定義 Set global 變量名 = 值; Set @@global.變量名 = 值; 通常,在SQL編程的時候,不會使用自定義變量來控制全局。一般都是定義會話變量或者在結構中使用局部變量來解決問題。 存儲過程----------------------------------------------------------------------- 存儲過程(Stored Procedure)是在大型數據庫系統中,一組為了完成特定功能的SQL 語句集,存儲在數據庫中, 經過第一次編譯后再次調用不需要再次編譯(效率比較高),用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。 存儲過程是數據庫中的一個重要對象(針對SQL編程而言)。 存儲過程:簡稱過程 存儲過程與函數的區別 相同點 1、 存儲過程和函數目的都是為了可重復地執行操作數據庫的sql語句的集合。 2、 存儲過程函數都是一次編譯,后續執行 不同點 1、標識符不同。函數的標識符為FUNCTION,過程為:PROCEDURE。 2、函數中有返回值,且必須返回,而過程沒有返回值。 3、過程無返回值類型,不能將結果直接賦值給變量;函數有返回值類型,調用時,除在select中,必須將返回值賦給變量。 4、函數可以在select語句中直接使用,而過程不能:函數是使用select調用,過程不是。 創建過程 基本語法 Create procedure 過程名字([參數列表]) Begin 過程體 End 結束符 如果過程體中只有一條指令,那么可以省略begin和end create procedure my_pro1() select * from mystu; 過程基本上也可以完成函數對應的所有功能 --求1到100之間的和 create procedure my_pro2() begin --求1到100之間的和 declare i int default 1; --declare sum int default 0; --局部變量,可以解決 set @sum = 0; --會話變量 --開始循環獲取結果 while i < 100 do --求和 set @sum = @sum + i; set i = i + 1; end while; --顯示結果 select @sum; end; 查看過程 查看過程與查看函數完全一樣:除了關鍵字 查看全部存儲過程:show procedure status [like ‘pattern’]; 查看過程創建語句:show create procedure 過程名字; 調用過程 過程:沒有返回值,select不可能調用 調用過程有專門的語法:call 過程名([實參列表]); 刪除過程 基本語法:drop procedure 過程名字; 存儲過程的形參類型 存儲過程也允許提供參數(形參和實參):存儲的參數也和函數一樣,需要指定其類型。 但是存儲過程對參數還有額外的要求:自己的參數分類in、out、inout In 表示參數從外部傳入到里面使用(過程內部使用):可以是直接數據也可以是保存數據的變量 Out 表示參數是從過程里面把數據保存到變量中,交給外部使用:傳入的必須是變量 如果說傳入的out變量本身在外部有數據,那么在進入過程之后,第一件事就是被清空,設為NULL Inout 數據可以從外部傳入到過程內部使用,同時內部操作之后,又會將數據返還給外部。 參數使用級別語法(形參) 過程類型 變量名 數據類型; //in int_1 int --創建三個外部變量 set @n1 = 1; set @n2 = 2; set @n3 = 3; --創建過程 --修改語句結束符 demiter $$ create procedure my_pro3(in int_1 int,out int_2 int,inout int_3 int) begin --查看三個傳入進來的數據值 select int_1,int_2,int_3; --修改三個變量的值 set int_1 = 10; set int_2 = 100; set int_3 = 1000; select int_1,int_2,int_3; --查看會話變量 select @n1,@n2,@n3; --修改會話變量 set @n1 = 'a'; set @n2 = 'b'; set @n3 = 'c'; select @n1,@n2,@n3; end; --調用過程 call my_pro3(@n1,@n2,@n3); 觸發器-------------------------------------------------------------------- 觸發器概念 基本概念 觸發器是一種特殊類型的存儲過程,它不同於我們前面介紹過的存儲過程。觸發器主要是通過事件進行觸發而被執行的,而存儲過程可以通過存儲過程名字而被直接調用。 觸發器:trigger,是一種非常接近於js中的事件的知識。提前給某張表的所有記錄(行)綁定一段代碼,如果改行的操作滿足條件(觸發),這段提前准備好的代碼就會自動執行。 作用 1、可在寫入數據表前,強制檢驗或轉換數據。(保證數據安全) 2、觸發器發生錯誤時,異動的結果會被撤銷。(如果觸發器執行錯誤,那么前面用戶已經執行成功的操作也會被撤銷:事務安全) 3、部分數據庫管理系統可以針對數據定義語言(DDL)使用觸發器,稱為DDL觸發器。 4、可依照特定的情況,替換異動的指令 (INSTEAD OF)。(mysql不支持) 優點 1、 觸發器可通過數據庫中的相關表實現級聯更改。(如果某張表的數據改變,可以利用觸發器來實現其他表的無痕操作[用戶不知道]) 2、 保證數據安全:進行安全校驗 缺點 1、 對觸發器過分的依賴,勢必影響數據庫的結構,同時增加了維護的復雜程度。 2、 造成數據在程序層面不可控。(PHP層) 創建觸發器 基本語法 Create trigger 觸發器名字 觸發時機 觸發事件 on 表 for each row Begin ..... End 觸發對象:on 表 for each row,觸發器綁定實質是表中的所有行,因此當每一行發生指定的改變的時候,就會觸發觸發器。 觸發時機 觸發時機:每張表中對應的行都會有不同的狀態,當SQL指令發生的時候,都會令行中數據發生改變,每一行總會有兩種狀態:數據操作前和操作后 Before:在表中數據發生改變前的狀態 After:在表中數據已經發生改變后的狀態 觸發事件 觸發事件:mysql中觸發器針對的目標是數據發生改變,對應的操作只有寫操作(增刪改) Insert:插入操作 Update:更新操作 Delete:刪除操作 注意事項 一張表中,每一個觸發時機綁定的觸發事件對應的觸發器類型只能有一個:一張表中只能有一個對應after insert觸發器 因此,一張表中最多的觸發器只能有6個:before insert,before update,before delete,after insert,after update,after delete 需求:有兩張表,一張是商品表,一張是訂單表(保留商品ID),每次訂單生成,商品表中對應的庫存就應該發生變化。 需求:有兩張表,一張是商品表,一張是訂單表(保留商品ID),每次訂單生成,商品表中對應的庫存就應該發生變化。 1、 創建兩張表:商品表和訂單表 create table my_goods( id int primary key auto_increment, name varchar(20) not null, inv int )charset utf8; create table my_orders( id int primary key auto_increment, goods_id int not null, goods_number int not null )charset utf8; insert into my_goods values(null,'手機',1000),(null,'電腦',500),(null,'游戲機',100); 2、 創建觸發器:如果訂單表發生數據插入,對應的商品就應該減少庫存 Create trigger 名字 after insert on my_orders for each row create trigger after_insert_order_t after insert on my_orders for each row begin --更新商品庫存 update my_goods set inv = inv -1 where id = 1; end; 查看觸發器 1、 查看全部觸發器 Show triggers; 2、 查看觸發器的創建語句 Show create trigger 觸發器名字; 觸發觸發器 想辦法讓觸發器執行:讓觸發器指定的表中,對應的時機發生對應的操作即可。 1、 表為my_orders 2、 在插入之后 3、 插入操作 刪除觸發器 基本語法:drop trigger 觸發器名字; 觸發器應用 記錄關鍵字:new、old 觸發器針對的是數據表中的每條記錄(每行),每行在數據操作前后都有一個對應的狀態,觸發器在執行之前就將對應的狀態獲取到了, 將沒有操作之前的狀態(數據)都保存到old關鍵字中,而操作后的狀態都放到new中。 在觸發器中,可以通過old和new來獲取綁定表中對應的記錄數據。 基本語法:關鍵字.字段名 Old和new並不是所有觸發器都有: Insert:插入前全為空,沒有old Delete:清空數據,沒有new 觸發器案例-商品自動扣除庫存----------- create trigger a_i_o_t after insert on my_orders for each row begin --更新商品庫存:new代表着新增的訂單 update my_goods set inv = inv - new.goods_number where id = new.goods_id; end; 如果庫存數量沒有商品訂單多怎么辦? 操作目標:訂單表,操作時機:下單前;操作事件:插入 --判斷庫存 create trigger b_i_o_t before insert on my_orders for each row begin --取出庫存數據進行判斷 select inv from my_goods where id=new.goods_id into @inv; --判斷 if @inv < new.goods_number then --中斷操作:暴力解決,主動出錯 insert into xxx values('xxx'); end if; end;