一 什麼是存儲引擎css
mysql中創建的庫===>文件夾node
庫中創建的表===>文件mysql
現實生活中咱們用來存儲數據的文件有不一樣的類型,每種文件類型對應各自不一樣的處理機制:好比處理文本用txt類型,處理表格用excel,處理圖片用png等nginx
數據庫中的表也應該有不一樣的類型,表的類型不一樣,會對應mysql不一樣的存取機制,表類型又稱爲存儲引擎。sql
存儲引擎說白了就是如何存儲數據、如何爲存儲的數據創建索引和如何更新、查詢數據等技術的實現方
法。由於在關係數據庫中數據的存儲是以表的形式存儲的,因此存儲引擎也能夠稱爲表類型(即存儲和
操做此表的類型)數據庫
在Oracle 和SQL Server等數據庫中只有一種存儲引擎,全部數據存儲管理機制都是同樣的。而MySql
數據庫提供了多種存儲引擎。用戶能夠根據不一樣的需求爲數據表選擇不一樣的存儲引擎,用戶也能夠根據
本身的須要編寫本身的存儲引擎緩存
SQL 解析器、SQL 優化器、緩衝池、存儲引擎等組件在每一個數據庫中都存在,但不是每 個數據庫都有這麼多存儲引擎。MySQL 的插件式存儲引擎可讓存儲引擎層的開發人員設 計他們但願的存儲層,例如,有的應用須要知足事務的要求,有的應用則不須要對事務有這 麼強的要求 ;有的但願數據能持久存儲,有的只但願放在內存中,臨時並快速地提供對數據 的查詢。 session
MariaDB [(none)]> show engines\G #查看全部支持的存儲引擎 MariaDB [(none)]> show variables like 'storage_engine%'; #查看正在使用的存儲引擎
MySQL存儲引擎介紹架構
#InnoDB 存儲引擎 支持事務,其設計目標主要面向聯機事務處理(OLTP)的應用。其 特色是行鎖設計、支持外鍵,並支持相似 Oracle 的非鎖定讀,即默認讀取操做不會產生鎖。 從 MySQL 5.5.8 版本開始是默認的存儲引擎。 InnoDB 存儲引擎將數據放在一個邏輯的表空間中,這個表空間就像黑盒同樣由 InnoDB 存儲引擎自身來管理。從 MySQL 4.1(包括 4.1)版本開始,能夠將每一個 InnoDB 存儲引擎的 表單獨存放到一個獨立的 ibd 文件中。此外,InnoDB 存儲引擎支持將裸設備(row disk)用 於創建其表空間。 InnoDB 經過使用多版本併發控制(MVCC)來得到高併發性,而且實現了 SQL 標準 的 4 種隔離級別,默認爲 REPEATABLE 級別,同時使用一種稱爲 netx-key locking 的策略來 避免幻讀(phantom)現象的產生。除此以外,InnoDB 存儲引擎還提供了插入緩衝(insert buffer)、二次寫(double write)、自適應哈希索引(adaptive hash index)、預讀(read ahead) 等高性能和高可用的功能。 對於表中數據的存儲,InnoDB 存儲引擎採用了彙集(clustered)的方式,每張表都是按 主鍵的順序進行存儲的,若是沒有顯式地在表定義時指定主鍵,InnoDB 存儲引擎會爲每一 行生成一個 6 字節的 ROWID,並以此做爲主鍵。 InnoDB 存儲引擎是 MySQL 數據庫最爲經常使用的一種引擎,Facebook、Google、Yahoo 等 公司的成功應用已經證實了 InnoDB 存儲引擎具有高可用性、高性能以及高可擴展性。對其 底層實現的掌握和理解也須要時間和技術的積累。若是想深刻了解 InnoDB 存儲引擎的工做 原理、實現和應用,能夠參考《MySQL 技術內幕:InnoDB 存儲引擎》一書。 #MyISAM 存儲引擎 不支持事務、表鎖設計、支持全文索引,主要面向一些 OLAP 數 據庫應用,在 MySQL 5.5.8 版本以前是默認的存儲引擎(除 Windows 版本外)。數據庫系統 與文件系統一個很大的不一樣在於對事務的支持,MyISAM 存儲引擎是不支持事務的。究其根 本,這也並不難理解。用戶在全部的應用中是否都須要事務呢?在數據倉庫中,若是沒有 ETL 這些操做,只是簡單地經過報表查詢還須要事務的支持嗎?此外,MyISAM 存儲引擎的 另外一個不同凡響的地方是,它的緩衝池只緩存(cache)索引文件,而不緩存數據文件,這與 大多數的數據庫都不相同。 #NDB 存儲引擎 年,MySQL AB 公司從 Sony Ericsson 公司收購了 NDB 存儲引擎。 NDB 存儲引擎是一個集羣存儲引擎,相似於 Oracle 的 RAC 集羣,不過與 Oracle RAC 的 share everything 結構不一樣的是,其結構是 share nothing 的集羣架構,所以能提供更高級別的 高可用性。NDB 存儲引擎的特色是數據所有放在內存中(從 5.1 版本開始,能夠將非索引數 據放在磁盤上),所以主鍵查找(primary key lookups)的速度極快,而且可以在線添加 NDB 數據存儲節點(data node)以便線性地提升數據庫性能。因而可知,NDB 存儲引擎是高可用、 高性能、高可擴展性的數據庫集羣系統,其面向的也是 OLTP 的數據庫應用類型。 #Memory 存儲引擎 正如其名,Memory 存儲引擎中的數據都存放在內存中,數據庫重 啓或發生崩潰,表中的數據都將消失。它很是適合於存儲 OLTP 數據庫應用中臨時數據的臨時表,也能夠做爲 OLAP 數據庫應用中數據倉庫的維度表。Memory 存儲引擎默認使用哈希 索引,而不是一般熟悉的 B+ 樹索引。 #Infobright 存儲引擎 第三方的存儲引擎。其特色是存儲是按照列而非行的,所以很是 適合 OLAP 的數據庫應用。其官方網站是 http://www.infobright.org/,上面有很多成功的數據 倉庫案例可供分析。 #NTSE 存儲引擎 網易公司開發的面向其內部使用的存儲引擎。目前的版本不支持事務, 但提供壓縮、行級緩存等特性,不久的未來會實現面向內存的事務支持。 #BLACKHOLE 黑洞存儲引擎,能夠應用於主備複製中的分發主庫。 MySQL 數據庫還有不少其餘存儲引擎,上述只是列舉了最爲經常使用的一些引擎。若是 你喜歡,徹底能夠編寫專屬於本身的引擎,這就是開源賦予咱們的能力,也是開源的魅 力所在。
方法1:建表時指定併發
MariaDB [db1]> create table innodb_t1(id int,name char)engine=innodb; MariaDB [db1]> create table innodb_t2(id int)engine=innodb; MariaDB [db1]> show create table innodb_t1; MariaDB [db1]> show create table innodb_t2;
方法2:在配置文件中指定默認的存儲引擎
/etc/my.cnf [mysqld] default-storage-engine=INNODB innodb_file_per_table=1
查看
[root@egon db1]# cd /var/lib/mysql/db1/ [root@egon db1]# ls db.opt innodb_t1.frm innodb_t1.ibd innodb_t2.frm innodb_t2.ibd
練習
建立四個表,分別使用innodb,myisam,memory,blackhole存儲引擎,進行插入數據測試
MariaDB [db1]> create table t1(id int)engine=innodb; MariaDB [db1]> create table t2(id int)engine=myisam; MariaDB [db1]> create table t3(id int)engine=memory; MariaDB [db1]> create table t4(id int)engine=blackhole; MariaDB [db1]> quit [root@egon db1]# ls /var/lib/mysql/db1/ #發現後兩種存儲引擎只有表結構,無數據 db.opt t1.frm t1.ibd t2.MYD t2.MYI t2.frm t3.frm t4.frm #memory,在重啓mysql或者重啓機器後,表內數據清空 #blackhole,往表內插入任何數據,都至關於丟入黑洞,表內永遠不存記錄
建立表的約束
約束條件與數據類型的寬度同樣,都是可選參數
做用:用於保證數據的完整性和一致性
主要分爲:
PRIMARY KEY (PK) 標識該字段爲該表的主鍵,能夠惟一的標識記錄 FOREIGN KEY (FK) 標識該字段爲該表的外鍵 NOT NULL 標識該字段不能爲空 UNIQUE KEY (UK) 標識該字段的值是惟一的 AUTO_INCREMENT 標識該字段的值自動增加(整數類型,並且爲主鍵) DEFAULT 爲該字段設置默認值 UNSIGNED 無符號 ZEROFILL 使用0填充
說明:
1. 是否容許爲空,默認NULL,可設置NOT NULL,字段不容許爲空,必須賦值 2. 字段是否有默認值,缺省的默認值是NULL,若是插入記錄時不給字段賦值,此字段使用默認值 sex enum('male','female') not null default 'male' age int unsigned NOT NULL default 20 必須爲正值(無符號) 不容許爲空 默認是20 3. 是不是key 主鍵 primary key 外鍵 foreign key 索引 (index,unique...)
是否可空,null表示空,非字符串
not null - 不可空
null - 可空
默認值,建立列時能夠指定默認值,當插入數據時若是未主動設置,則自動添加默認值
create table tb1(
nid int not null defalut 2,
num int not null
)
==================not null==================== mysql> create table t1(id int); #id字段默承認以插入空 mysql> desc t1; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ mysql> insert into t1 values(); #能夠插入空 mysql> create table t2(id int not null); #設置字段id不爲空 mysql> desc t2; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | NO | | NULL | | +-------+---------+------+-----+---------+-------+ mysql> insert into t2 values(); #不能插入空 ERROR 1364 (HY000): Field 'id' doesn't have a default value ==================default==================== #設置id字段有默認值後,則不管id字段是null仍是not null,均可以插入空,插入空默認填入default指定的默認值 mysql> create table t3(id int default 1); mysql> alter table t3 modify id int not null default 1; ==================綜合練習==================== mysql> create table student( -> name varchar(20) not null, -> age int(3) unsigned not null default 18, -> sex enum('male','female') default 'male', -> hobby set('play','study','read','music') default 'play,music' -> ); mysql> desc student; +-------+------------------------------------+------+-----+------------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------------------------+------+-----+------------+-------+ | name | varchar(20) | NO | | NULL | | | age | int(3) unsigned | NO | | 18 | | | sex | enum('male','female') | YES | | male | | | hobby | set('play','study','read','music') | YES | | play,music | | +-------+------------------------------------+------+-----+------------+-------+ mysql> insert into student(name) values('egon'); mysql> select * from student; +------+-----+------+------------+ | name | age | sex | hobby | +------+-----+------+------------+ | egon | 18 | male | play,music | +------+-----+------+------------+
============設置惟一約束 UNIQUE=============== 方法一: create table department1( id int, name varchar(20) unique, comment varchar(100) ); 方法二: create table department2( id int, name varchar(20), comment varchar(100), constraint uk_name unique(name) ); mysql> insert into department1 values(1,'IT','技術'); Query OK, 1 row affected (0.00 sec) mysql> insert into department1 values(1,'IT','技術'); ERROR 1062 (23000): Duplicate entry 'IT' for key 'name'
mysql> create table t1(id int not null unique); Query OK, 0 rows affected (0.02 sec) mysql> desc t1; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | +-------+---------+------+-----+---------+-------+ row in set (0.00 sec)
create table service( id int primary key auto_increment, name varchar(20), host varchar(15) not null, port int not null, unique(host,port) #聯合惟一 ); mysql> insert into service values -> (1,'nginx','192.168.0.10',80), -> (2,'haproxy','192.168.0.20',80), -> (3,'mysql','192.168.0.30',3306) -> ; Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> insert into service(name,host,port) values('nginx','192.168.0.10',80); ERROR 1062 (23000): Duplicate entry '192.168.0.10-80' for key 'host'
從約束角度看primary key字段的值不爲空且惟一,那咱們直接使用not null+unique不就能夠了嗎,要它幹什麼?
主鍵primary key是innodb存儲引擎組織數據的依據,innodb稱之爲索引組織表,一張表中必須有且只有一個主鍵。
一個表中能夠:
單列作主鍵
多列作主鍵(複合主鍵)
============單列作主鍵=============== #方法一:not null+unique create table department1( id int not null unique, #主鍵 name varchar(20) not null unique, comment varchar(100) ); mysql> desc department1; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | NO | UNI | NULL | | | comment | varchar(100) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ rows in set (0.01 sec) #方法二:在某一個字段後用primary key create table department2( id int primary key, #主鍵 name varchar(20), comment varchar(100) ); mysql> desc department2; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | YES | | NULL | | | comment | varchar(100) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ rows in set (0.00 sec) #方法三:在全部字段後單獨定義primary key create table department3( id int, name varchar(20), comment varchar(100), constraint pk_name primary key(id); #建立主鍵併爲其命名pk_name mysql> desc department3; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | YES | | NULL | | | comment | varchar(100) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ rows in set (0.01 sec)
==================多列作主鍵================ create table service( ip varchar(15), port char(5), service_name varchar(10) not null, primary key(ip,port) ); mysql> desc service; +--------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------+-------------+------+-----+---------+-------+ | ip | varchar(15) | NO | PRI | NULL | | | port | char(5) | NO | PRI | NULL | | | service_name | varchar(10) | NO | | NULL | | +--------------+-------------+------+-----+---------+-------+ rows in set (0.00 sec) mysql> insert into service values -> ('172.16.45.10','3306','mysqld'), -> ('172.16.45.11','3306','mariadb') -> ; Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into service values ('172.16.45.10','3306','nginx'); ERROR 1062 (23000): Duplicate entry '172.16.45.10-3306' for key 'PRIMARY'
約束字段爲自動增加,被約束的字段必須同時被key約束
#不指定id,則自動增加 create table student( id int primary key auto_increment, name varchar(20), sex enum('male','female') default 'male' ); mysql> desc student; +-------+-----------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-----------------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | | sex | enum('male','female') | YES | | male | | +-------+-----------------------+------+-----+---------+----------------+ mysql> insert into student(name) values -> ('egon'), -> ('alex') -> ; mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 1 | egon | male | | 2 | alex | male | +----+------+------+ #也能夠指定id mysql> insert into student values(4,'asb','female'); Query OK, 1 row affected (0.00 sec) mysql> insert into student values(7,'wsb','female'); Query OK, 1 row affected (0.00 sec) mysql> select * from student; +----+------+--------+ | id | name | sex | +----+------+--------+ | 1 | egon | male | | 2 | alex | male | | 4 | asb | female | | 7 | wsb | female | +----+------+--------+ #對於自增的字段,在用delete刪除後,再插入值,該字段仍按照刪除前的位置繼續增加 mysql> delete from student; Query OK, 4 rows affected (0.00 sec) mysql> select * from student; Empty set (0.00 sec) mysql> insert into student(name) values('ysb'); mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 8 | ysb | male | +----+------+------+ #應該用truncate清空表,比起delete一條一條地刪除記錄,truncate是直接清空表,在刪除大表時用它 mysql> truncate student; Query OK, 0 rows affected (0.01 sec) mysql> insert into student(name) values('egon'); Query OK, 1 row affected (0.01 sec) mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 1 | egon | male | +----+------+------+ row in set (0.00 sec)
瞭解知識
#在建立完表後,修改自增字段的起始值 mysql> create table student( -> id int primary key auto_increment, -> name varchar(20), -> sex enum('male','female') default 'male' -> ); mysql> alter table student auto_increment=3; mysql> show create table student; ....... ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 mysql> insert into student(name) values('egon'); Query OK, 1 row affected (0.01 sec) mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 3 | egon | male | +----+------+------+ row in set (0.00 sec) mysql> show create table student; ....... ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 #也能夠建立表時指定auto_increment的初始值,注意初始值的設置爲表選項,應該放到括號外 create table student( id int primary key auto_increment, name varchar(20), sex enum('male','female') default 'male' )auto_increment=3; #設置步長 sqlserver:自增步長 基於表級別 create table t1( id int。。。 )engine=innodb,auto_increment=2 步長=2 default charset=utf8 mysql自增的步長: show session variables like 'auto_inc%'; #基於會話級別 set session auth_increment_increment=2 #修改會話級別的步長 #基於全局級別的 set global auth_increment_increment=2 #修改全局級別的步長(全部會話都生效) #!!!注意了注意了注意了!!! If the value of auto_increment_offset is greater than that of auto_increment_increment, the value of auto_increment_offset is ignored. 翻譯:若是auto_increment_offset的值大於auto_increment_increment的值,則auto_increment_offset的值會被忽略 ,這至關於第一步步子就邁大了,扯着了蛋 好比:設置auto_increment_offset=3,auto_increment_increment=2 mysql> set global auto_increment_increment=5; Query OK, 0 rows affected (0.00 sec) mysql> set global auto_increment_offset=3; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'auto_incre%'; #須要退出從新登陸 +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | auto_increment_increment | 1 | | auto_increment_offset | 1 | +--------------------------+-------+ create table student( id int primary key auto_increment, name varchar(20), sex enum('male','female') default 'male' ); mysql> insert into student(name) values('egon1'),('egon2'),('egon3'); mysql> select * from student; +----+-------+------+ | id | name | sex | +----+-------+------+ | 3 | egon1 | male | | 8 | egon2 | male | | 13 | egon3 | male | +----+-------+------+
一 快速理解foreign key
員工信息表有三個字段:工號 姓名 部門
公司有3個部門,可是有1個億的員工,那意味着部門這個字段須要重複存儲,部門名字越長,越浪費
解決方法:
咱們徹底能夠定義一個部門表
而後讓員工信息表關聯該表,如何關聯,即foreign key
#表類型必須是innodb存儲引擎,且被關聯的字段,即references指定的另一個表的字段,必須保證惟一 create table department( id int primary key, name varchar(20) not null )engine=innodb; #dpt_id外鍵,關聯父表(department主鍵id),同步更新,同步刪除 create table employee( id int primary key, name varchar(20) not null, dpt_id int, constraint fk_name foreign key(dpt_id) references department(id) on delete cascade on update cascade )engine=innodb; #先往父表department中插入記錄 insert into department values (1,'歐德博愛技術有限事業部'), (2,'艾利克斯人力資源部'), (3,'銷售部'); #再往子表employee中插入記錄 insert into employee values (1,'egon',1), (2,'alex1',2), (3,'alex2',2), (4,'alex3',2), (5,'李坦克',3), (6,'劉飛機',3), (7,'張火箭',3), (8,'林子彈',3), (9,'加特林',3) ; #刪父表department,子表employee中對應的記錄跟着刪 mysql> delete from department where id=3; mysql> select * from employee; +----+-------+--------+ | id | name | dpt_id | +----+-------+--------+ | 1 | egon | 1 | | 2 | alex1 | 2 | | 3 | alex2 | 2 | | 4 | alex3 | 2 | +----+-------+--------+ #更新父表department,子表employee中對應的記錄跟着改 mysql> update department set id=22222 where id=2; mysql> select * from employee; +----+-------+--------+ | id | name | dpt_id | +----+-------+--------+ | 1 | egon | 1 | | 3 | alex2 | 22222 | | 4 | alex3 | 22222 | | 5 | alex1 | 22222 | +----+-------+--------+
二 如何找出兩張表之間的關係
分析步驟: #一、先站在左表的角度去找 是否左表的多條記錄能夠對應右表的一條記錄,若是是,則證實左表的一個字段foreign key 右表一個字段(一般是id) #二、再站在右表的角度去找 是否右表的多條記錄能夠對應左表的一條記錄,若是是,則證實右表的一個字段foreign key 左表一個字段(一般是id) #三、總結: #多對一: 若是隻有步驟1成立,則是左表多對一右表 若是隻有步驟2成立,則是右表多對一左表 #多對多 若是步驟1和2同時成立,則證實這兩張表時一個雙向的多對一,即多對多,須要定義一個這兩張表的關係表來專門存放兩者的關係 #一對一: 若是1和2都不成立,而是左表的一條記錄惟一對應右表的一條記錄,反之亦然。這種狀況很簡單,就是在左表foreign key右表的基礎上,將左表的外鍵字段設置成unique便可
三 創建表之間的關係
#一對多或稱爲多對一 三張表:出版社,做者信息,書 一對多(或多對一):一個出版社能夠出版多本書 關聯方式:foreign key
=====================多對一===================== create table press( id int primary key auto_increment, name varchar(20) ); create table book( id int primary key auto_increment, name varchar(20), press_id int not null, foreign key(press_id) references press(id) on delete cascade on update cascade ); insert into press(name) values ('北京工業地雷出版社'), ('人民音樂很差聽出版社'), ('知識產權沒有用出版社') ; insert into book(name,press_id) values ('九陽神功',1), ('九陰真經',2), ('九陰白骨爪',2), ('獨孤九劍',3), ('降龍十巴掌',2), ('葵花寶典',3) ;
一夫多妻制 #妻子表的丈夫id外鍵到丈夫表的id
=====================多對多===================== create table author( id int primary key auto_increment, name varchar(20) ); #這張表就存放做者表與書表的關係,即查詢兩者的關係查這表就能夠了 create table author2book( id int not null unique auto_increment, author_id int not null, book_id int not null, constraint fk_author foreign key(author_id) references author(id) on delete cascade on update cascade, constraint fk_book foreign key(book_id) references book(id) on delete cascade on update cascade, primary key(author_id,book_id) ); #插入四個做者,id依次排開 insert into author(name) values('egon'),('alex'),('yuanhao'),('wpq'); #每一個做者與本身的表明做以下 egon: 九陽神功 九陰真經 九陰白骨爪 獨孤九劍 降龍十巴掌 葵花寶典 alex: 九陽神功 葵花寶典 yuanhao: 獨孤九劍 降龍十巴掌 葵花寶典 wpq: 九陽神功 insert into author2book(author_id,book_id) values (1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (2,1), (2,6), (3,4), (3,5), (3,6), (4,1) ;
單張表:用戶表+相親關係表,至關於:用戶表+相親關係表+用戶表 多張表:用戶表+用戶與主機關係表+主機表 中間那一張存放關係的表,對外關聯的字段能夠聯合惟一
#一對一 兩張表:學生表和客戶表 一對一:一個學生是一個客戶,一個客戶有可能變成一個學校,即一對一的關係 關聯方式:foreign key+unique
#必定是student來foreign key表customer,這樣就保證了: #1 學生必定是一個客戶, #2 客戶不必定是學生,但有可能成爲一個學生 create table customer( id int primary key auto_increment, name varchar(20) not null, qq varchar(10) not null, phone char(16) not null ); create table student( id int primary key auto_increment, class_name varchar(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) ; #增長學生 insert into student(class_name,customer_id) values ('脫產3班',3), ('週末19期',4), ('週末19期',5) ;
例一:一個用戶只有一個博客 用戶表: id name egon alex wupeiqi 博客表 fk+unique id url name_id xxxx 1 yyyy 3 zzz 2 例二:一個管理員惟一對應一個用戶 用戶表: id user password egon xxxx alex yyyy 管理員表: fk+unique id user_id password 1 xxxxx 2 yyyyy
練習:帳號信息表,用戶組,主機表,主機組
#用戶表 create table user( id int not null unique auto_increment, username varchar(20) not null, password varchar(50) not null, primary key(username,password) ); insert into user(username,password) values ('root','123'), ('egon','456'), ('alex','alex3714') ; #用戶組表 create table usergroup( id int primary key auto_increment, groupname varchar(20) not null unique ); insert into usergroup(groupname) values ('IT'), ('Sale'), ('Finance'), ('boss') ; #主機表 create table host( id int primary key auto_increment, ip char(15) not null unique default '127.0.0.1' ); insert into host(ip) values ('172.16.45.2'), ('172.16.31.10'), ('172.16.45.3'), ('172.16.31.11'), ('172.10.45.3'), ('172.10.45.4'), ('172.10.45.5'), ('192.168.1.20'), ('192.168.1.21'), ('192.168.1.22'), ('192.168.2.23'), ('192.168.2.223'), ('192.168.2.24'), ('192.168.3.22'), ('192.168.3.23'), ('192.168.3.24') ; #業務線表 create table business( id int primary key auto_increment, business varchar(20) not null unique ); insert into business(business) values ('輕鬆貸'), ('隨便花'), ('大富翁'), ('窮一輩子') ; #建關係:user與usergroup create table user2usergroup( id int not null unique auto_increment, user_id int not null, group_id int not null, primary key(user_id,group_id), foreign key(user_id) references user(id), foreign key(group_id) references usergroup(id) ); insert into user2usergroup(user_id,group_id) values (1,1), (1,2), (1,3), (1,4), (2,3), (2,4), (3,4) ; #建關係:host與business create table host2business( id int not null unique auto_increment, host_id int not null, business_id int not null, primary key(host_id,business_id), foreign key(host_id) references host(id), foreign key(business_id) references business(id) ); insert into host2business(host_id,business_id) values (1,1), (1,2), (1,3), (2,2), (2,3), (3,4) ; #建關係:user與host create table user2host( id int not null unique auto_increment, user_id int not null, host_id int not null, primary key(user_id,host_id), foreign key(user_id) references user(id), foreign key(host_id) references host(id) ); insert into user2host(user_id,host_id) values (1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14), (1,15), (1,16), (2,2), (2,3), (2,4), (2,5), (3,10), (3,11), (3,12) ;
語法: 1. 修改表名 ALTER TABLE 表名 RENAME 新表名; 2. 增長字段 ALTER TABLE 表名 ADD 字段名 數據類型 [完整性約束條件…], ADD 字段名 數據類型 [完整性約束條件…]; ALTER TABLE 表名 ADD 字段名 數據類型 [完整性約束條件…] FIRST; ALTER TABLE 表名 ADD 字段名 數據類型 [完整性約束條件…] AFTER 字段名; 3. 刪除字段 ALTER TABLE 表名 DROP 字段名; 4. 修改字段 ALTER TABLE 表名 MODIFY 字段名 數據類型 [完整性約束條件…]; ALTER TABLE 表名 CHANGE 舊字段名 新字段名 舊數據類型 [完整性約束條件…]; ALTER TABLE 表名 CHANGE 舊字段名 新字段名 新數據類型 [完整性約束條件…];
示例: 1. 修改存儲引擎 mysql> alter table service -> engine=innodb; 2. 添加字段 mysql> alter table student10 -> add name varchar(20) not null, -> add age int(3) not null default 22; mysql> alter table student10 -> add stu_num varchar(10) not null after name; //添加name字段以後 mysql> alter table student10 -> add sex enum('male','female') default 'male' first; //添加到最前面 3. 刪除字段 mysql> alter table student10 -> drop sex; mysql> alter table service -> drop mac; 4. 修改字段類型modify mysql> alter table student10 -> modify age int(3); mysql> alter table student10 -> modify id int(11) not null primary key auto_increment; //修改成主鍵 5. 增長約束(針對已有的主鍵增長auto_increment) mysql> alter table student10 modify id int(11) not null primary key auto_increment; ERROR 1068 (42000): Multiple primary key defined mysql> alter table student10 modify id int(11) not null auto_increment; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 6. 對已經存在的表增長複合主鍵 mysql> alter table service2 -> add primary key(host_ip,port); 7. 增長主鍵 mysql> alter table student1 -> modify name varchar(10) not null primary key; 8. 增長主鍵和自動增加 mysql> alter table student1 -> modify id int not null primary key auto_increment; 9. 刪除主鍵 a. 刪除自增約束 mysql> alter table student10 modify id int(11) not null; b. 刪除主鍵 mysql> alter table student10 -> drop primary key;
複製表結構+記錄 (key不會複製: 主鍵、外鍵和索引) mysql> create table new_service select * from service; 只複製表結構 mysql> select * from service where 1=2; //條件爲假,查不到任何記錄 Empty set (0.00 sec) mysql> create table new1_service select * from service where 1=2; Query OK, 0 rows affected (0.00 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> create table t4 like employees;
DROP TABLE 表名;