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 tG
*************************** 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