mysql 常見的數據對象有哪些:
- DataBase/Schema
- Table
- Index
- View/Trigger/Function/Procedure
多Database用途:
- 業務的隔離
- 資源的隔離
表上的常用數據對象:
- 索引
- 約束
- 視圖,觸發器,函數,存儲過程
索引
什么是數據庫索引:
索引就是數據庫中數據的目錄:
索引和數據時兩個對象
索引主要是用來提高數據庫的查詢效率
數據庫中數據變更同樣需要同步索引數據的變更,
因為索引是按照B+TREE,排好位置的,一旦數據變化,則這個數據的相應位置也要變化,
這樣之后再查找,才能快速索引到,而變化位置就是索引的維護;
查看某個數據庫命令:
mysql> help create index Name: 'CREATE INDEX' Description: Syntax: CREATE [ONLINE|OFFLINE] [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name [index_type] ON tbl_name (index_col_name,...) [index_option] ..
UNIQUE:唯一索引(用戶表的ID,手機號等,唯一信息)
SPATIAL:地理位置索引(搜索周邊有哪些人)
兩種創建索引及查看表中索引的方法
mysql> select * from vc; +------+------+ | v | c | +------+------+ | AB | AB | +------+------+ 1 row in set (0.00 sec) mysql> create index idx_v on vc(v); Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table vc add KEY idx_c (c); Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show index from vc; +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | vc | 1 | idx_v | 1 | v | A | 1 | NULL | NULL | YES | BTREE | | | | vc | 1 | idx_c | 1 | c | A | 1 | NULL | NULL | YES | BTREE | | | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 2 rows in set (0.00 sec) mysql> show create table vc; +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ | vc | CREATE TABLE `vc` ( `v` varchar(5) DEFAULT NULL, `c` char(5) DEFAULT NULL, KEY `idx_v` (`v`), KEY `idx_c` (`c`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 | +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
在mysql中 INDEX 和KEY 都代表了索引;
約束
約束:
唯一約束: unique
外鍵約束: CONSTRAINT
創建唯一約束(唯一索引可以促成唯一約束):
- 唯一約束是一種特殊的索引
- 唯一約束可以是一個或者多個字段
- 位於約束可以在建表的時候建好,也可以后面補上
- 主鍵也是一種唯一約束


索引有哪些:
- 主鍵索引 ID
- 單鍵索引 orderid
- 單鍵索引 bookid
- 組合索引 (userid + orderid)
唯一約束有哪些:
- 主鍵約束 ID
- 單鍵唯一索引 orderid
- 組合唯一索引 userid+orderid
添加唯一約束
添加主鍵索引:
mysql> alter table order add primary key (id) #實際上是給主鍵id增加了一個索引,而這個索引又是唯一的所以就這個索引就變成了唯一約束
添加唯一索引:
mysql>alter table order add unique key idx_uk_orderid(id)
外鍵約束
將兩張表的數據通過某種條件關聯起來
例子:買東西,訂單表,用戶信息表;
如果沒有外鍵約束:可能存在不存在用戶也能下單成功;
而如果使用外鍵約束,則在數據庫層面是的不存在的用戶不能下單成功。
創建外鍵約束:
將用戶表和訂單表通過外鍵關聯起來:
mysql > alter table order add CONSTRAINT constarint_uid FOREIGN KEY (userid) REFERENCES user(userid)
創建外鍵約束的時候,可以指定在刪除,更新父表(被參照的表)時,對子表(做外鍵關聯的表)
進行的相應操作,包括可:restrict(限制),cascade(串聯),set null 和 no action。
其中restrict和 no action 相同,是指限制在子表有關聯記錄的情況下,父表不能更新;
cascade表示父表在更新或刪除時,更新或者刪除子表對應的記錄;
set null 表示父表在更新或者刪除時子表的對應字段被set null。
選擇后兩種方式的時候要謹慎,可能會因為錯誤的操作導致數據的丟失。
在執行LOAD DATA和 ALTER TABLE 操作的時候,為了加快速度,可以暫時關閉外鍵約束: set foreign key_checks =0;等完成之后再開啟:set foreign key_checks =1
mysql > alter table order add CONSTRAINT constarint_uid FOREIGN KEY (userid) REFERENCES user(userid) on delete restrict on update cascade;
on update cascade例子:
mysql> select * from c_A; +----+------+ | id | age | +----+------+ | 1 | 22 | | 2 | 3 | | 3 | 4 | +----+------+ 3 rows in set (0.00 sec) mysql> select * from c_B; +----+------+ | id | age | +----+------+ | 1 | 2 | | 2 | 33 | | 3 | 4 | +----+------+ 3 rows in set (0.00 sec) mysql> update c_B set id=11 where age = 2; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from c_B; +----+------+ | id | age | +----+------+ | 2 | 33 | | 3 | 4 | | 11 | 2 | +----+------+ 3 rows in set (0.00 sec) mysql> select * from c_A; +----+------+ | id | age | +----+------+ | 2 | 3 | | 3 | 4 | | 11 | 22 | +----+------+ 3 rows in set (0.00 sec)
注意:外鍵約束更改的只是約束的那個字段;
on delete cascade
on delete cascade | insert | update | delete |
parent | yes | 只能更改子表中約束字段沒有的值 | yes |
child | 只能插入父表中約束字段有的值; | 只能更改父表中約束字段沒有的值 | yes |
on update cascade
on update cascade | insert | update | delete |
parent | yes | yes | 只能刪子表中約束字段沒有的值; |
child | 只能插入父表中約束字段有的值; | 只能更新父表中約束字段沒有的值 | yes |
可以見child只能刪除,其余都受限余父表的約束字段;
而parent都能插入,但其中一條受限於子表約束字段;
給order表增加了一個約束,(CONSTRAINT,約束的關鍵詞)約束名 constarint_uid;
他是一個外鍵約束且order表中userid是外鍵,把order表中的userid 關聯 到 user表的userid;
使用外鍵的注意事項:
- 必須是innodb表,其他引擎不支持外鍵
- 相互約束的字段類型必須要一樣
- 主表的約束字段要求有索引(上面的例子中,user表就是主表,所以在user表中要userid要求加上索引 )
- 約束名稱必須要唯一,即使不在一張表上(constarint_uid 在整個庫中是唯一的)
刪除一個約束:
mysql> alter table order drop FOREIGN KEY constarint_uid;
視圖view
view作用:
- 視圖將一組查詢語句構成的結果集,是一種虛擬結構,並不是實際數據
- 視圖能簡化數據庫的訪問,能夠將多個查詢語句結構化為一個虛擬結構
- 視圖可以隱藏數據庫后端表結構,提高數據庫的安全性
- 視圖也是一種權限管理,只對用戶提供部分數據
創建一個已完成訂單的視圖:
mysql > create view order_view as select * from order where status = 1
視圖例子:
mysql> CREATE TABLE t (qty INT, price INT); mysql> INSERT INTO t VALUES(3, 50); mysql> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t; mysql> SELECT * FROM v; +------+-------+-------+ | qty | price | value | +------+-------+-------+ | 3 | 50 | 150 | +------+-------+-------+
觸發器
觸發器
是什么:
觸發器是加在表上的特殊程序,當表上出現特定的事件
(insert/update/delete/alter table)時觸發該程序執行。
對一個表的一個事件mysql中只能定義一個觸發器
做什么:
- 數據訂正;
- 遷移表;
- 實現特定的業務邏輯;
觸發器有兩個用戶:
- 執行者
- 調用者
觸發器--基本語法
CREATE [DEFINER = {user | CURRENT_USER}] -- 定義執行着的權限 TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW --涉及的每一行都會執行trigger_body trigger_body t trigger_time:{BEFORE | AFTER} trigger_event:{INSERT | UPDATE | DELETE}
delimiter
結束符的設定,默認是分號。但是在觸發器應為要執行一組SQL,會出現分號所以講結束符 設定一下;


用 NEW,OLD來引用觸發器中發生變化的記錄內容
觸發觸發器的順序:
before 觸發器,行操作,after 觸發器;其中任何一個步驟操作發生錯誤都不會繼續執行剩下的操作。
如果是對事務表進行的操作,那么會整個作為一個事務被回滾(rollback),但是如果是對非事務表進行的操作
,那么已經更新的記錄將無法回滾,這也是設計觸發器的時候需要注意得問題。
觸發器的特點:
- 觸發器對性能有損耗,應慎用
- 同一類事件在一個表中只能創建一次
- 對於事務表,觸發器執行失敗則整個語句回滾
- row格式主從復制,觸發器不會在從屬庫上執行
- 使用觸發器時應該防止遞歸執行
可以協助應用在數據庫端確保數據的完整性。
存儲過程
定義:存儲過程是存儲在數據庫端的一組SQL語句集,用戶可以通過存儲過程名和傳參多次調用的程序模塊。
特點:
- 使用靈活,可以使用流控制語句,自定義變量等完成復雜的業務邏輯
- 提高數據安全性,屏蔽應用程序直接對表的操作,易於進行審計
- 減少網絡傳輸
- 提高代碼維護的復雜度,實際使用中要評估場景是否適合
存儲過程--基本語法
CREATE [ DEFINER = { user | CURRENT_USER } ] --定義執行着的權限 PROCEDURE sp_name ( [ proc_parameter[ ,... ] ] ) [ characteristic .. ] routine_body proc_parameter: [ IN | OUT | INOUT] param_name type type: Any valid MySQL data type
IN:輸入參數,表示該參數值在調用存儲過程中已經指定好了,在調用存儲過程中修改該參數不會返回
OUT:輸出參數,可以在存儲過程內部被改變,可以返回
INOUT:輸入輸出參數;
characteristic:
COMMENT 'string' --注釋
| [NOT] DETERMINISTIC --是否會返回確定值
routine_body:
Valid SQL routine statement --與trigger類似


重點:
- 中間變量定義:DECLARE
- 流控制語句
- 參數傳入
查詢:數據庫中有哪些存儲過程
mysql> show PROCEDURE STATUS ;
查看:某個觸發器的詳情
mysql> SHOW TRIGGER STATUS ;
存儲過程的使用:
1.設置參數值:
mysql> set @total = 5; mysql> set @res = 0;
2.調用存儲過程:
mysql> call proc_test1(@total,@res);
3.查看返回值:
mysql> select @res
刪除存儲過程或者函數:
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name
查看存儲過程或者函數
SHOW {procedure | function} status like ‘file_in_stock’
查看存儲過程或者函數的定義
show create {procedure | function} sp_name
存儲過程-流控制語言


自定義函數
- 自定義函數與存儲過程類似,但是必須帶有返回值
- 自定義函數與sum(),max(),等mysql原生函數使用方法類似: select func(val); select * from tbl where col = func(val)
- 由於自定義函數可能在遍歷數據中使用,要注意性能損耗
自定義函數-基本語法


最終通過RETURN;

調用
mysql> select func_test1(4);
確認權限:
創建存儲過程或者函數需要:create routine
修改或者刪除存儲過程需要:alter routine
執行存儲過程 需要 : execute
可以嵌套使用;
小結
- 觸發器和存儲過程不利於水平擴展,多用於統計和運維操作中;
- 還有代碼管理維護成本比較高;
- 但是:
- 簡化應用開發,減少數據傳輸,提高處理效率;
總結
- 索引的創建於查看
- 約束:
- 唯一約束,
- 外鍵約束:
- alter table order add CONSTRAINT constarint_uid FOREIGN KEY (userid) REFERENCES user(userid);
- 外鍵約束四種模式:restrict,no action,set null,cascade;
- VIEW
- TIGGER:
- 一個表的一個事件只能定義一個觸發器
- delimiter //
- NEW.age OLD.age
- PROCEDURE:
- DECLARE,
- 參數傳入返回
- 流控制語言
- 使用三步驟
- 初始化參數
- 調用存儲過程
- 查看放回值
- function:
- 必須帶有返回值
- 使用select func_test1(14);
- SUBSTRING( goods_name,1,5 ):從位置1截取goods_name5個字符
- A rigth join B on..:B顯示B中null字段;