1.創建數據庫表的三種語句
創建一個新表;
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
(create_definition,...)
[table_options]
[partition_options]
創建新表的同時將select的查詢結果數據插入到新表中,但索引和主外鍵信息都不會同步過來;
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
[(create_definition,...)]
[table_options]
[partition_options]
[IGNORE | REPLACE]
[AS] query_expression
基於另外一個表的定義復制一個新的空表,空表上的字段屬性和索引和原表相同;
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
{ LIKE old_tbl_name | (LIKE old_tbl_name) }
(1)TEMPOPARY創建臨時表
(2)默認情況下,表是在默認的數據庫中創建,並使用InnoDB存儲引擎。如果沒有默認數據庫,或者數據庫不存在,則如果表存在,會出現錯誤。
演示:
mysql> create table app01(id int,name varchar(20));
Query OK, 0 rows affected (1.04 sec)
mysql> create table app02 as select * from app01;
Query OK, 0 rows affected (0.72 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> create table app03 like app01;
Query OK, 0 rows affected (0.85 sec)
2.語句屬性解析
(1)tbl_name
表名可以被指定為db_name.tbl_name在特定數據庫中創建表。如果數據庫存在,則不管是否存在默認數據庫,它都工作。如果使用引用標識符,則分別引用數據庫和表名。例如,mydb
.mytbl
,而不是mydb.mytbl
。
(2)IF NOT EXISTS
如果表存在,則防止發生錯誤。但是,沒有驗證現有表的結構與創建表語句所表示的結構是否相同。
(3)Temporary Tables
創建表時可以使用臨時關鍵字。臨時表僅在當前會話中可見,並在會話關閉時自動刪除。
(4)IGNORE和REPLACE
忽略和替換選項指示如何使用SELECT語句復制表時處理重復鍵值的行。
在插入數據的過程中如果新表中碰到違反唯一約束的情況下怎么處理:
- ignore表示不插入
- replace表示替換已有的數據
- 默認兩個關鍵詞都不寫則碰到違反的情況會報錯
3.創建臨時表
mysql> create temporary table temp1(sid int,sname varchar(10));
Query OK, 0 rows affected (0.00 sec)
mysql> insert into temp1 values(1,'aaa');
Query OK, 1 row affected (0.00 sec)
mysql> select * from temp1;
+------+-------+
| sid | sname |
+------+-------+
| 1 | aaa |
+------+-------+
1 row in set (0.00 sec)
mysql> show tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| app01 |
| app02 |
| app03 |
+-----------------+
3 rows in set (0.00 sec)
另起一個會話:
mysql> use test1;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| app01 |
| app02 |
| app03 |
+-----------------+
3 rows in set (0.00 sec)
mysql> select * from temp1;
ERROR 1146 (42S02): Table 'test1.temp1' doesn't exist
退出本次會話:
mysql> use test1;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from temp1;
ERROR 1146 (42S02): Table 'test1.temp1' doesn't exist
(1)臨時表的種類
1)全局臨時表
這種臨時表從數據庫實例啟動后開始生效,在數據庫實例銷毀后失效。在MySQL里面這種臨時表對應的是內存表,即memory引擎。
2)會話級別臨時表
這種臨時表在用戶登錄系統成功后生效,在用戶退出時失效。在MySQL里的臨時表指的就是以create temporary table這樣的關鍵詞創建的表。
3)事務級別臨時表
這種臨時表在事務開始時生效,事務提交或者回滾后失效。 在MySQL里面沒有這種臨時表,必須利用會話級別的臨時表間接實現。
4)檢索級別臨時表
這種臨時表在SQL語句執行之間產生,執行完畢后失效。 在MySQL里面這種臨時表不是很固定,跟隨MySQL默認存儲引擎來變化。
比如默認存儲引擎是MyISAM,臨時表的引擎就是MyISAM,並且文件生成形式以及數據運作形式和MyISAM一樣,只是數據保存在內存里;如果默認引擎是INNODB,那么臨時表的引擎就是INNODB,此時它的所有信息都保存在共享表空間ibdata里面。
(2)MySQL 5.7的臨時表空間優化
1)MySQL 5.7 把臨時表的數據以及回滾信息(僅限於未壓縮表)從共享表空間里面剝離出來,形成自己單獨的表空間,參數為innodb_temp_data_file_path。
2)在MySQL 5.7 中把臨時表的相關檢索信息保存在系統信息表中:information_schema.innodb_temp_table_info. 而MySQL 5.7之前的版本想要查看臨時表的系統信息是沒有太好的辦法。
需要注意的一點就是:
雖然INNODB臨時表有自己的表空間,但是目前還不能自己定義臨時表空間文件的保存路徑,只能是繼承innodb_data_home_dir。此時如果想要拿其他的磁盤,比如內存盤來充當臨時表空間的保存地址,只能用老辦法,做軟鏈。
(3)臨時表使用的幾點建議
- 設置 innodb_temp_data_file_path 選項,設定文件最大上限,超過上限時,需要生成臨時表的SQL無法被執行(一般這種SQL效率也比較低,可借此機會進行優化)。
- 檢查 INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO,找到最大的臨時表對應的線程,kill之即可釋放,但 ibtmp1 文件則不能釋放(除非重啟)。
- 擇機重啟實例,釋放ibtmp1文件,和ibdata1不同,ibtmp1重啟時會被重新初始化而 ibdata1 則不可以。
- 定期檢查運行時長超過N秒(比如N=300)的SQL,考慮干掉,避免垃圾SQL長時間運行影響業務。
4.創建表時的其他參數說明
(1)create_definition
create_definition:
col_name column_definition
| [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)
[index_option] ...
| {INDEX|KEY} [index_name] [index_type] (index_col_name,...)
[index_option] ...
| [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]
[index_name] [index_type] (index_col_name,...)
[index_option] ...
| {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...)
[index_option] ...
| [CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name,...) reference_definition
| CHECK (expr)
1)CONSTRAINT symbol
如果給定了約束符號子句,則使用的符號值在數據庫中必須是唯一的。重復的符號會導致錯誤。如果沒有給出子句,或者在約束關鍵字后面不包含符號,則自動創建約束的名稱。
2)PRIMARY KEY
所有索引列必須定義為非空的唯一索引。如果沒有顯式地聲明它們不是null,那么MySQL會隱式地聲明它們。一個表只能有一個主鍵。主鍵的名稱始終是主鍵,因此不能用作任何其他類型索引的名稱。
如果沒有主鍵,應用程序請求表中的主鍵,則MySQL返回第一個唯一索引,該索引沒有空列作為主鍵。
在創建表,主鍵是放在第一位,其次是所有唯一索引,然后非唯一索引。這有助於MySQL優化器區分使用哪個索引,並更快速地檢測重復的唯一鍵。
如果主鍵只包含一個列有一個整數類型,你也可以在SELECT語句中引用該列為_rowid。
在MySQL中,主鍵的名稱是重要的。其他索引,如果你不指定一個名稱,索引分配相同的名稱作為第一個索引列,一個可選的后綴(_2,_3,…)使它獨特的。你可以看到一個表使用tbl_name顯示索引名稱。
3)INDEX和KEY
KEY是INDEX的同義詞。當列定義中給出主鍵屬性KEY時,也可以將其指定為主鍵。這實現了與其他數據庫系統的兼容性。
4)UNIQUE
惟一索引創建一個約束,使得索引中的所有值必須是明確的。如果試圖添加與現有行匹配的鍵值,則會出現一個錯誤。對於所有引擎,惟一索引允許包含空的列的多個空值。如果在唯一索引中指定列的前綴值,則列值必須在前綴中是唯一的。
如果一個唯一索引只包含一個列有一個整數類型,你也可以在SELECT語句中引用該列為_rowid。
5)FULLTEXT
全文索引是一種特殊類型的用於全文檢索索引。只有InnoDB和MyISAM存儲引擎支持全文索引。他們只能從CHAR、VARCHAR創建文本列。索引總是發生在整個列上,不支持列前綴索引,如果指定的話,任何前綴長度都會被忽略。
6)SPATIAL
可以在空間數據類型上創建空間索引。空間類型僅用於MyISAM和InnoDB表支持,並且索引列必須被聲明為NOT NULL。
7)FOREIGN KEY
MySQL支持外鍵,它允許跨表和外鍵約束交叉引用相關數據,這有助於保持數據一致性。
分區表使用InnoDB存儲引擎不支持外鍵。
8)CHECK
檢查子句被解析,但被所有存儲引擎忽略。
9)index_col_name
- 一個index_col_name規范可以結束與ASC或DESC。這些關鍵詞都是為將來的擴展允許指定升序或降序索引值存儲。當前,它們被解析但被忽略;索引值總是按升序存儲。
- 前綴的長度屬性的定義,可以達到767字節在InnoDB表,如果innodb_large_prefix選項啟用可以達到3072字節長。對於MyISAM表,前綴限制為1000字節。
前綴限制以字節為單位,而前綴長度在創建表、修改表,並創建索引語句被解釋為非二進制字符串類型(char、varchar字符數、文本)和二進制字符串類型的字節數(二進制、varbinary、BLOB)。考慮到這一點時指定前綴長度為非二進制字符串列使用多字節字符集。
index_col_name:
col_name [(length)] [ASC | DESC]
10)index_type
一些存儲引擎允許在創建索引時指定索引類型。
CREATE TABLE lookup
(id INT, INDEX USING BTREE (id))
ENGINE = MEMORY;
11)reference_definition
InnoDB和NDB表支持外鍵約束檢查。引用表的列必須始終顯式命名。支持外鍵上的刪除和更新操作。
reference_definition:
REFERENCES tbl_name (index_col_name,...)
[MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
[ON DELETE reference_option]
[ON UPDATE reference_option]
reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT
12)其他
index_type:
USING {BTREE | HASH}
index_option:
KEY_BLOCK_SIZE [=] value
| index_type
| WITH PARSER parser_name
| COMMENT 'string'
(2)column_definition:
column_definition:
data_type [NOT NULL | NULL] [DEFAULT default_value]
[AUTO_INCREMENT] [UNIQUE [KEY]] [[PRIMARY] KEY]
[COMMENT 'string']
[COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}]
[STORAGE {DISK|MEMORY|DEFAULT}]
[reference_definition]
| data_type [GENERATED ALWAYS] AS (expression)
[VIRTUAL | STORED] [NOT NULL | NULL]
[UNIQUE [KEY]] [[PRIMARY] KEY]
[COMMENT 'string']
1)data_type
data_type:
BIT[(length)]
| TINYINT[(length)] [UNSIGNED] [ZEROFILL]
| SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
| MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
| INT[(length)] [UNSIGNED] [ZEROFILL]
| INTEGER[(length)] [UNSIGNED] [ZEROFILL]
| BIGINT[(length)] [UNSIGNED] [ZEROFILL]
| REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
| DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
| FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
| DECIMAL[(length[,decimals])] [UNSIGNED] [ZEROFILL]
| NUMERIC[(length[,decimals])] [UNSIGNED] [ZEROFILL]
| DATE
| TIME[(fsp)]
| TIMESTAMP[(fsp)]
| DATETIME[(fsp)]
| YEAR
| CHAR[(length)]
[CHARACTER SET charset_name] [COLLATE collation_name]
| VARCHAR(length)
[CHARACTER SET charset_name] [COLLATE collation_name]
| BINARY[(length)]
| VARBINARY(length)
| TINYBLOB
| BLOB[(length)]
| MEDIUMBLOB
| LONGBLOB
| TINYTEXT
[CHARACTER SET charset_name] [COLLATE collation_name]
| TEXT[(length)]
[CHARACTER SET charset_name] [COLLATE collation_name]
| MEDIUMTEXT
[CHARACTER SET charset_name] [COLLATE collation_name]
| LONGTEXT
[CHARACTER SET charset_name] [COLLATE collation_name]
| ENUM(value1,value2,value3,...)
[CHARACTER SET charset_name] [COLLATE collation_name]
| SET(value1,value2,value3,...)
[CHARACTER SET charset_name] [COLLATE collation_name]
| JSON
| spatial_type
data_type代表一個列定義的數據類型。spatial_type表示空間數據類型。所顯示的數據類型語法僅具有代表性。MySQL 5.7.8開始,JSON數據類型在表列中也被支撐;
- 某些屬性不適用於所有數據類型。auto_increment只適用於整型和浮點型。默認值不適用於塊、文本、幾何和JSON類型。
- 字符數據類型(char、varchar、text)可以包括CHARACTER SET和COLLATE屬性所指定的。
- MySQL 5.7將字符列定義中的長度規范解釋為字符。為binary和varbinary長度字節。
- 無法對JSON列進行索引。可以通過在生成的列上從JSON列提取標量值創建索引來解決此限制。
2)NOT NULL和NULL
表示字段是否允許為空,默認為null表示允許為空,not null表示需要對此字段明確數值,或有默認值,否則報錯。
3)DEFAULT
指定列的默認值。
只有一個例外
默認值必須是常量,不能是函數或表達式。這意味着,例如,你不能為一個日期列指定一個函數如now()或current_date值設置默認。例外的是,你可以指定current_timestamp作為默認時間戳或datetime列。
4)AUTO_INCREMENT
一個整數或浮點列可以有額外的屬性auto_increment。當你插入一個空值(推薦)或0到一個索引的auto_increment列,列設置為下一個序列值。通常,這是值+ 1,其中值是當前表中當前列的最大值。auto_increment序列從1開始。
如果no_auto_value_on_zero SQL模式被啟用,您可以存儲0 auto_increment列為0不產生新的序列值。
一個表只允許有一個自增字段,且該字段必須有key屬性,不能含有default屬性,且插入負值會被當成很大的正數。
5)COMMENT
可以用注釋選項指定一個列的注釋,最多1024個字符。注釋由“顯示創建”表顯示,並顯示完整的列語句。
6)COLUMN_FORMAT
在NDB集群,也可以指定一個NDB表使用column_format單個列的數據存儲格式。允許的列格式是固定的、動態的和默認的。固定用於指定固定寬度的列存儲,動態許可是可變的寬度,和違約導致柱使用固定寬度或寬度可變的存儲的列的數據類型決定(可能被row_format說明符)。
MySQL NDB集群7.5.4開始,NDB表,為column_format默認值是固定的。(默認已經切換到MySQL NDB集群7.5.1、動態但這種變化是恢復到維持現有的GA版本系列。向后兼容性)
column_format目前已經在使用存儲引擎以外NDB表列無影響。在MySQL 5.7以后,column_format被忽略。
7)STORAGE
NDB表,可以指定該列是否是存儲在磁盤或內存使用的存儲子句。存儲磁盤使列存儲在磁盤上,而存儲內存將導致內存存儲中使用。使用的創建表語句還必須包含表空間子句。
mysql> CREATE TABLE t1 (
-> c1 INT STORAGE DISK,
-> c2 INT STORAGE MEMORY
-> ) ENGINE NDB;
ERROR 1005 (HY000): Can't create table 'c.t1' (errno: 140)
mysql> CREATE TABLE t1 (
-> c1 INT STORAGE DISK,
-> c2 INT STORAGE MEMORY
-> ) TABLESPACE ts_1 ENGINE NDB;
Query OK, 0 rows affected (1.06 sec)
8)GENERATED ALWAYS
用於指定生成的列表達式。
(3)table_options
table_options:
table_option [[,] table_option] ...
table_option:
AUTO_INCREMENT [=] value
| AVG_ROW_LENGTH [=] value
| [DEFAULT] CHARACTER SET [=] charset_name
| CHECKSUM [=] {0 | 1}
| [DEFAULT] COLLATE [=] collation_name
| COMMENT [=] 'string'
| COMPRESSION [=] {'ZLIB'|'LZ4'|'NONE'}
| CONNECTION [=] 'connect_string'
| {DATA|INDEX} DIRECTORY [=] 'absolute path to directory'
| DELAY_KEY_WRITE [=] {0 | 1}
| ENCRYPTION [=] {'Y' | 'N'}
| ENGINE [=] engine_name
| INSERT_METHOD [=] { NO | FIRST | LAST }
| KEY_BLOCK_SIZE [=] value
| MAX_ROWS [=] value
| MIN_ROWS [=] value
| PACK_KEYS [=] {0 | 1 | DEFAULT}
| PASSWORD [=] 'string'
| ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}
| STATS_AUTO_RECALC [=] {DEFAULT|0|1}
| STATS_PERSISTENT [=] {DEFAULT|0|1}
| STATS_SAMPLE_PAGES [=] value
| TABLESPACE tablespace_name [STORAGE {DISK|MEMORY|DEFAULT}]
| UNION [=] (tbl_name[,tbl_name]...)
表選項用於優化表的行為。在大多數情況下,您不必指定其中任何一個。除非另有說明,這些選項適用於所有存儲引擎。不適用於給定存儲引擎的選項可以作為表定義的一部分被接受和記住。然后,如果以后使用表來轉換表以使用不同的存儲引擎,那么就可以應用這些選項。
1)ENGINE
通常在這種情況下,這是InnoDB,為default_storage_engine系統變量的默認值。
2)[DEFAULT] CHARACTER SET
指定表的默認字符集。CHARACTER是CHARACTER SET的同義詞。如果字符集名稱為默認值,則使用數據庫字符集。
3)COMPRESSION
使用InnoDB表的頁面級壓縮的壓縮算法。
4)DATA DIRECTORY, INDEX DIRECTORY
nnoDB,數據目錄= 'directory”選項允許你創建InnoDB表空間文件每桌外的MySQL數據目錄。在您指定的目錄中,MySQL創建一個與數據庫名稱相對應的子目錄,並在其中為表設置一個IBD文件。innodb_file_per_table配置選項必須啟用數據目錄選項InnoDB。必須指定完整的目錄路徑。
5)ENCRYPTION
設置加密選項“Y”使一個InnoDB表文件中的每個表空間創建的頁面級的數據加密。選項值不區分大小寫。加密選項介紹了InnoDB表空間加密功能;
6)TABLESPACE
用於創建InnoDB表的通用表空間
4.創建分區表
(1)語法
partition_options:
PARTITION BY
{ [LINEAR] HASH(expr)
| [LINEAR] KEY [ALGORITHM={1|2}] (column_list)
| RANGE{(expr) | COLUMNS(column_list)}
| LIST{(expr) | COLUMNS(column_list)} }
[PARTITIONS num]
[SUBPARTITION BY
{ [LINEAR] HASH(expr)
| [LINEAR] KEY [ALGORITHM={1|2}] (column_list) }
[SUBPARTITIONS num]
]
[(partition_definition [, partition_definition] ...)]
partition_definition:
PARTITION partition_name
[VALUES
{LESS THAN {(expr | value_list) | MAXVALUE}
|
IN (value_list)}]
[[STORAGE] ENGINE [=] engine_name]
[COMMENT [=] 'string' ]
[DATA DIRECTORY [=] 'data_dir']
[INDEX DIRECTORY [=] 'index_dir']
[MAX_ROWS [=] max_number_of_rows]
[MIN_ROWS [=] min_number_of_rows]
[TABLESPACE [=] tablespace_name]
[(subpartition_definition [, subpartition_definition] ...)]
subpartition_definition:
SUBPARTITION logical_name
[[STORAGE] ENGINE [=] engine_name]
[COMMENT [=] 'string' ]
[DATA DIRECTORY [=] 'data_dir']
[INDEX DIRECTORY [=] 'index_dir']
[MAX_ROWS [=] max_number_of_rows]
[MIN_ROWS [=] min_number_of_rows]
[TABLESPACE [=] tablespace_name]
(2)創建分區表
待以后單獨講述。
5.查看創建表語句
SHOW CREATE TABLE tbl_name
mysql> SHOW CREATE TABLE t\G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`s` char(60) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1