python 之 數據庫(字段的約束條件,表之間的關係)

10.6 約束條件

10.61 not null 、default

create table t15(
    id int,
    name char(16) not null,
    sex enum('male','female','other') not null default "male"
);
#alter table t15 modify name char(16) not null;
insert into t15(id,name) values
(1,'egon1'),
(2,'egon2'),
(3,'egon3');
​
mysql> desc t15;
+-------+-------------------------------+------+-----+---------+-------+
| Field | Type                          | Null | Key | Default | Extra |
+-------+-------------------------------+------+-----+---------+-------+
| id    | int(11)                       | YES  |     | NULL    |       |
| name  | char(16)                      | NO   |     | NULL    |       |
| sex   | enum('male','female','other') | NO   |     | male    |       |
+-------+-------------------------------+------+-----+---------+-------+
​
mysql> select * from t15;
+------+-------+------+
| id   | name  | sex  |
+------+-------+------+
|    1 | egon1 | male |
|    2 | egon2 | male |
|    3 | egon3 | male |
+------+-------+------+

10.62 unique

mysql中存在一種專門的數據結構,叫 key,又稱為索引,通過該數據結構可以減少 i/o 次數,從而加速查詢效率 index key : 只有加速查詢的效果,沒有約束的功能 unique key:不僅有加速查詢的效果,還附加了一種約束的功能 primary key:不僅有加速查詢的效果,還附加了一種約束的功能,並且innodb存儲引擎會按照主鍵字段的值 來組織表中所有的數據,所以一種inndob表中必須有、而且只能有一個主鍵,通常為該表的id字段

unique:限制字段的值的唯一性,單從約束角度去看:唯一性約束

#單列唯一
create table t16(
    id int unique,
    name char(16)
);
​
# 聯合唯一(不能完全相同)
create table server(
    id int unique,
    ip char(15),
    port int,
    unique(ip,port)
);
mysql> desc server;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id    | int(11)  | YES  | UNI | NULL    |       |
| ip    | char(15) | YES  | MUL | NULL    |       |
| port  | int(11)  | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
insert into server values(1,'1.1.1.1',3306),(2,'1.1.1.1',3307),(3,'1.1.1.2',3306);
mysql> select * from server;
+------+---------+------+
| id   | ip      | port |
+------+---------+------+
|    1 | 1.1.1.1 | 3306 |
|    2 | 1.1.1.1 | 3307 |
|    3 | 1.1.1.2 | 3306 |
+------+---------+------+

10.63 primary key

primary key:單單從約束角度去看,primary key就等同於 not null + unique 強調: 1、一張表中必須有,並且只能有一個主鍵 2、一張表中都應該有一個id字段,而且應該把id字段做成主鍵

create table t17(
    id int primary key,
    name char(16),
    age int,
    sex char(6)
)engine=innodb;
​
​
#聯合主鍵(不完全相同,但不能為空)
create table t19(
    ip char(15),
    port int,
    primary key(ip,port)
);
mysql> desc t19;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| ip    | char(15) | NO   | PRI |         |       |
| port  | int(11)  | NO   | PRI | 0       |       |
+-------+----------+------+-----+---------+-------+

10.64 auto_increment

只能給被約束成key的字段加自增屬性,默認起始位置是1,步長也為1

# primary key auto_increment
create table t20(
    id int primary key auto_increment,
    name char(16)
)engine=innodb;
​
mysql> insert t20(name) values('egon1');
mysql> insert t20(name) values('egon2');
mysql> select * from t20;
+----+-------+
| id | name  |
+----+-------+
|  1 | egon1 |
|  2 | egon2 |
+----+-------+

10.7 表關係

10.71 多對一(foreign key)

1、把所有數據都存放於一張表的弊端:

  • 表的組織結構複雜不清晰

  • 浪費空間

  • 擴展性極差

    2、尋找表與表之間的關係的方法: 舉例:emp表 dep表 步驟一: part1: 1、先站在左表emp的角度 2、去找左表emp的多條記錄能否對應右表dep的一條記錄

    part2: 1、站在右表dep的角度 2、去找右表dep的多條記錄能否對應左表emp的一條記錄 3、如何實現? 在emp表中新增一個dep_id字段,該字段指向dep表的id字段

    4、foreign key會帶來什麼樣的效果?

約束1:在創建表時,先建被關聯的表dep,才能建關聯表emp

create table dep(
    id int primary key auto_increment,
    dep_name char(10),
    dep_comment char(60)
);
mysql> desc dep;
+-------------+----------+------+-----+---------+----------------+
| Field       | Type     | Null | Key | Default | Extra          |
+-------------+----------+------+-----+---------+----------------+
| id          | int(11)  | NO   | PRI | NULL    | auto_increment |
| dep_name    | char(10) | YES  |     | NULL    |                |
| dep_comment | char(60) | YES  |     | NULL    |                |
+-------------+----------+------+-----+---------+----------------+
create table emp(
    id int primary key auto_increment,
    name char(16),
    gender enum('male','female') not null default 'male',
    dep_id int,
    foreign key(dep_id) references dep(id)
);
mysql> desc emp;
+--------+-----------------------+------+-----+---------+----------------+
| Field  | Type                  | Null | Key | Default | Extra          |
+--------+-----------------------+------+-----+---------+----------------+
| id     | int(11)               | NO   | PRI | NULL    | auto_increment |
| name   | char(16)              | YES  |     | NULL    |                |
| gender | enum('male','female') | NO   |     | male    |                |
| dep_id | int(11)               | YES  | MUL | NULL    |                |
+--------+-----------------------+------+-----+---------+----------------+

約束2:在插入記錄時,必須先插被關聯的表dep,才能插關聯表emp

insert into dep(dep_name,dep_comment) values
('sb教學部','sb輔導學生學習,教授python課程'),
('外交部','形象大使'),
('nb技術部','nb技術能力有限部門');
mysql> select * from dep;
+----+-------------+-------------------------------------------+
| id | dep_name    | dep_comment                               |
+----+-------------+-------------------------------------------+
|  1 | sb教學部    | sb輔導學生學習,教授python課程            |
|  2 | 外交部      | 形象大使                                  |
|  3 | nb技術部    | nb技術能力有限部門                        |
+----+-------------+-------------------------------------------+
insert into emp(name,gender,dep_id)  values
('alex','male',1),
('egon','male',2),
('lxx','male',1),
('wxx','male',1),
('wenzhou','female',3);
mysql> select * from emp;
+----+---------+--------+--------+
| id | name    | gender | dep_id |
+----+---------+--------+--------+
|  1 | alex    | male   |      1 |
|  2 | egon    | male   |      2 |
|  3 | lxx     | male   |      1 |
|  4 | wxx     | male   |      1 |
|  5 | wenzhou | female |      3 |
+----+---------+--------+--------+

約束3:更新與刪除都需要考慮到關聯與被關聯的關係(不能直接改變dep表的id) 解決方案:

《python 之 數據庫(字段的約束條件,表之間的關係)》
《python 之 數據庫(字段的約束條件,表之間的關係)》

1、先刪除關聯表emp,再刪除被關聯表dep,準備重建
mysql> drop table emp;
mysql> drop table dep;
2、重建:新增功能:同步更新,同步刪除
create table dep(                       #先建被參照的表
    id int primary key auto_increment,
    dep_name char(10),
    dep_comment char(60));
create table emp(
    id int primary key auto_increment,
    name char(16),
    gender enum('male','female') not null default 'male',
    dep_id int,
    foreign key(dep_id) references dep(id) on update cascade on delete cascade);
insert into dep(dep_name,dep_comment) values
('sb教學部','sb輔導學生學習,教授python課程'),
('外交部','形象大使'),
('nb技術部','nb技術能力有限部門');
mysql> select * from dep;
+----+------------------+------------------------------
| id | dep_name         | dep_comment                  |
+----+------------------+------------------------------
|  1 | sb教學部         | sb輔導學生學習,教授python課程 |
|  2 | 外交部           | 形象大使                      |
|  3 | nb技術部         | nb技術能力有限部門             |
+----+------------------+-------------------------------
insert into emp(name,gender,dep_id)  values
('alex','male',1),
('egon','male',2),
('lxx','male',1),
('wxx','male',1),
('wenzhou','female',3);
mysql> select * from emp;
+----+------------------+--------+--------+
| id | name             | gender | dep_id |
+----+------------------+--------+--------+
|  1 | alex             | male   |      1 |
|  2 | egon             | male   |      2 |
|  3 | lxx              | male   |      1 |
|  4 | wxx              | male   |      1 |
|  5 | wenzhou          | female |      3 |
+----+------------------+--------+--------+
​
# 同步刪除
mysql> delete from dep where id=1;
mysql> select * from dep;
+----+------------------+------------------
| id | dep_name         | dep_comment     |
+----+------------------+------------------
|  2 | 外交部           | 形象大使          |
|  3 | nb技術部         | nb技術能力有限部門 |
+----+------------------+------------------
mysql> select * from emp;
+----+------------------+--------+--------+
| id | name             | gender | dep_id |
+----+------------------+--------+--------+
|  2 | egon             | male   |      2 |
|  5 | wenzhou          | female |      3 |
+----+------------------+--------+--------+
​
#同步更新
mysql> update dep set id=200 where id =2;
mysql> select * from dep;
+-----+------------------+----------------
| id  | dep_name         | dep_comment   |
+-----+------------------+----------------
|   3 | nb技術部         | nb技術能力有限部|
| 200 | 外交部           | 形象大使        |
+-----+------------------+----------------
mysql> select * from emp;
+----+------------------+--------+--------+
| id | name             | gender | dep_id |
+----+------------------+--------+--------+
|  2 | egon             | male   |    200 |
|  5 | wenzhou          | female |      3 |
+----+------------------+--------+--------+

View Code

10.72 多對多(foreign key)

1、什麼是多對多 兩張表之間是一個雙向的多對一關係,稱之為多對多 2、如何實現? 建立第三張表,該表中有一個字段是fk左表的id,還有一個字段是fk右表的id

create table author(
    id int primary key auto_increment,
    name char(16));
create table book(
    id int primary key auto_increment,
    bname char(16),
    price int);
insert into author(name) values
('egon'),
('alex'),
('wxx');
mysql> select * from author;
+----+------+
| id | name |
+----+------+
|  1 | egon |
|  2 | alex |
|  3 | wxx  |
+----+------+
insert into book(bname,price) values
('python從入門到入土',200),
('葵花寶典切割到精通',800),
('九陰真經',500),
('九陽神功',100);
mysql> select * from book;
+----+-----------------------------+-------+
| id | bname                       | price |
+----+-----------------------------+-------+
|  1 | python從入門到入土          |   200 |
|  2 | 葵花寶典切割到精通           |   800 |
|  3 | 九陰真經                    |   500 |
|  4 | 九陽神功                    |   100 |
+----+-----------------------------+-------+
create table author2book(
    id int primary key auto_increment,
    author_id int,
    book_id int,
    foreign key(author_id) references author(id) on update cascade on delete cascade,
    foreign key(book_id) references book(id) on update cascade on delete cascade);
insert into author2book(author_id,book_id) values
(1,3),(1,4),(2,2),(2,4),(3,1),(3,2),(3,3),(3,4);
mysql> select * from author2book;
+----+-----------+---------+
| id | author_id | book_id |
+----+-----------+---------+
|  1 |         1 |       3 |
|  2 |         1 |       4 |
|  3 |         2 |       2 |
|  4 |         2 |       4 |
|  5 |         3 |       1 |
|  6 |         3 |       2 |
|  7 |         3 |       3 |
|  8 |         3 |       4 |
+----+-----------+---------+

10.73 一對一(unique+foreign key)

一對一:左表的一條記錄唯一對應右表的一條記錄,反之也一樣

create table customer(                              #先建被參照的表
    id int primary key auto_increment,
    name char(20) not null,
    qq char(10) not null,
    phone char(16) not null);
create table student(
    id int primary key auto_increment,
    class_name char(20) not null,
    customer_id int unique,                        #該字段一定要是唯一的,一對一
    foreign key(customer_id) references customer(id) #外鍵的字段一定要保證unique
    on delete cascade on update cascade);
insert into customer(name,qq,phone) values
('李飛機','31811231',13811341220),
('王大炮','123123123',15213146809),
('守榴彈','283818181',1867141331),
('吳坦克','283818181',1851143312),
('贏火箭','888818181',1861243314),
('戰地雷','112312312',18811431230);
mysql> select * from customer;
+----+-----------+-----------+-------------+
| id | name      | qq        | phone       |
+----+-----------+-----------+-------------+
|  1 | 李飛機    | 31811231  | 13811341220 |
|  2 | 王大炮    | 123123123 | 15213146809 |
|  3 | 守榴彈    | 283818181 | 1867141331  |
|  4 | 吳坦克    | 283818181 | 1851143312  |
|  5 | 贏火箭    | 888818181 | 1861243314  |
|  6 | 戰地雷    | 112312312 | 18811431230 |
+----+-----------+-----------+-------------+
insert into student(class_name,customer_id) values
('python',3),('java',4),('c++',5);
mysql> select * from student;
+----+-------------+-------------+
| id | class_name  | customer_id |
+----+-------------+-------------+
|  1 | python     |           3 |
|  2 | java       |           4 |
|  3 | c++        |           5 |
+----+-------------+-------------+
点赞

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *