1. 程式人生 > >資料庫3 待改

資料庫3 待改

1.多表關聯
在日常開發中 如果效能要求比較高 不應該使用外來鍵
1.效率降低
2,耦合問題 關聯起來後管理麻煩
這個時候 關係只是邏輯關係 很有可能產生錯誤資料

為什麼要分表?
1.有重複資料 浪費空間
2.資料結構混亂
3.擴充套件性、維護性差
需要分表:
create table dept(id int primary key auto_increment,name char(20),job char(20));
create table emp(id int primary key auto_increment,name char(20),gendr char,age int,salary float,d_id int)

以上程式碼 可以建立關聯關係 但是這個關係是邏輯上的 不實際存在
需要為他建立物理上的關聯
通過外來鍵 約束
create table 表名(欄位名 型別(長度),foreign key(外來鍵的欄位名稱) references 對方表名(對方主鍵名))
使用外來鍵關係時 必須分清主從關係
1.外來鍵的第一種約束:
先建主表
再建從表

2.外來鍵的第二個約束:
先插入主表
再插入從表

3.外來鍵的第三個約束:
刪除記錄時
先刪除從表記錄
再刪除主表記錄

4.外來鍵的第四個約束:
從表更新外來鍵時 必須保證主表是存在的

5.外來鍵的第五個約束:
更新主表的id時
必須先刪除從表關聯的資料
或者把關聯的資料 關聯到其他的主表id

6.外來鍵的第六個約束:
刪除主表時
先刪除從表
再刪除主表

有了這幾個約束後 主表和從表的資料必然是完整的

相應的受到外來鍵的約束 主表的刪除更新操作收到限制
很多情況下就是要刪除一個部門 然而需要至少兩條sql語句 繁瑣
可以使用級聯
create table emp(
id int primary key auto_increment,
name char(20),
d_id int,
foreign key(d_id) references dept(id)
on delete cascade #當主表刪除記錄時 從表關聯記錄同步刪除
on update cascade #當主表id更新是 從表相關關聯的記錄同步更新
);
注意是單項的 主表變化是級聯操作從表 從表變化是不會關聯到主表的



多對多 其實就是雙向的多對一
只要遇到多對多關係 就建立一個專門存放關係的中間表

例子:
老師和學生
一個老師可以教多個學生
一個學生可以被多個老師教

如何知道? 1號老師教過哪些學生
1號學生被哪些老師教過

老師表和學生表
需要一箇中間表 專門儲存關聯關係

create table teacher(id int primary key auto_increment,name char(15));
create table student(id int primary key auto_increment,name char(15));
中間表:
create table tsr(
id int primary key auto_increment,
t_id int,s_id int,
foreign key(t_id) references teacher(id),
foreign key(s_id) references student(id)
);

現在老師和學生都是主表 關係表是從表
先插入老師和學生資料
insert into teacher values(1,"高跟"),(2,"艾根");
insert into student values(1,"張三"),(2,"李四");
#插入對應關係
insert into student values(null,1,1),(null,1,2),(null,2,2);



一對一關係加個外來鍵即可:
注意 :一對一中外來鍵的值不允許重複
夫妻關係確實是一對一的 但是在表中欄位完全相同 沒有必要分表
強行舉例:
客戶 和 學生
一個客戶產生一個學生
一個學生只能對應一個客戶
這樣的關係是一對一
使用外來鍵來關聯 但是需要給外來鍵加上唯一的約束
客戶和學生有主從關係 需要先建立客戶 再建學生
create table customer(
c_id int primary key auto_increment,
name char(20),
phonenum char(11),
addr char(20)
);

create table student(
s_id int primary key auto_increment,
name char(20),
class char(11),
number char(20),
housenum char(20),
foreign key(c_id) references ccustomer(c_id),
);

一對一的另一種使用場景
當一個表這種欄位太多 而查用欄位不多時 可以採用垂直分表的方式來提高效率
原有的person表
身份證號 姓名 性別 年齡 地址 民族 身高 血型 體重 學歷 政治面貌 聯絡方式

拆分為:
st_info
姓名 性別 年齡

details_info
身份證號 地址 民族 身高 血型 體重 學歷 政治面貌 聯絡方式



也有另一種提升效率的方式 水平分表
當一個表中資料記錄太多時 效率會降低 可以採取水平分表 欄位完全相同
stu 中有十萬資料
stu1 五萬
stu2 五萬


什麼時候要分表?
當一條記錄中的資料 不屬於同一類時

分表後產生的問題:
員工表中可以儲存一個不存在的部門編號,這樣的資料是不完整的 無效資料
必須找到一種方法,可以在物理層面建立關聯關係。
解決方案:外來鍵約束。

外來鍵是維護表與表之間的關係
表之間的關係到底是什麼樣的:
1.要站先站在員工的角度思考 多個員工是否可以屬於同一個部門 可以 員工對部門(多對一)
2.然後站在部門的角度來思考 多個部門能否同時包含一個員工 不可以 站在部門的角度 一個
員工只能屬於一個部門 所以一對一的關係
3.最後 綜合兩個表之間的關係 如果兩邊都是多對一 則稱之為雙向多對一 其實就是多對多
如果兩邊只有一方是多對一 則稱之為單項多對一

表之間的關係
一對多
多對多
一對一

外來鍵的使用
FOREING KEY

級聯操作
CASCADE





表的操作:

1.修改表
add 新增欄位 adter|first
after 新增欄位到哪個欄位後面
first 新增欄位到最前面
modify 修改欄位型別
change 修改欄位名稱 或 型別
drop 刪除欄位
rename 改表名



2.複製表
create table 新的表名 select *from 原表名;
資料
結構
約束 不能複製
當條件不成立時 只複製表結構
create table 新的表名 select *from 原表名 where 1=2;
select *from 原表名 where 1=2



3.蠕蟲複製
自我複製:
insert into 表名稱 select *from 表明名;
如果有主鍵 避開主鍵欄位
insert into 表名稱(其他欄位)select name from 表名;

sql注入攻擊
一個瞭解sq語法的攻擊者 可以在輸入框輸入sql語句
例如: 使用者名稱22345678765432 密碼12345
正常狀態:select *from user where account = "22345678765432"and pwd ="12345";
被攻擊:select *from user where account = ":"drop database mysql"and pwd ="12345";