MySQL中创建表的三种方法汇总

目录
  • CREATE TABLE
  • CREATE TABLE … LIKE
  • CREATE TABLE … SELECT
  • 总结

SQL 标准使用 CREATE TABLE 语句创建数据表;MySQL 则实现了三种创建表的方法,支持自定义表结构或者通过复制已有的表结构来创建新表,本文给大家分别介绍一下这些方法的使用和注意事项。

CREATE TABLE

CREATE TABLE 语句的基本语法如下:

CREATE TABLE [IF NOT EXISTS] table_name
(
  column1 data_type column_constraint,
  column2 data_type,
  ...,
  table_constraint
);

使用该语句时,我们需要手动定义表的结构。以上包含的内容如下:

  • IF NOT EXISTS 表示当该表不存在时创建表,当表已经存在时不执行该语句。
  • table_name 指定了表的名称。
  • 括号内是字段的定义;columnN 是字段的名称,data_type 是它的数据类型;column_constraint 是可选的字段约束;多个字段使用逗号进行分隔。
  • table_constraint 是可选的表级约束。

其中,常见的约束包括主键、外键、唯一、非空、检查约束以及默认值。

举例来说,以下语句用于创建一个新表 department:

CREATE TABLE department
    ( dept_id    INTEGER NOT NULL PRIMARY KEY
    , dept_name  VARCHAR(50) NOT NULL
    ) ;

部门表 department 包含两个字段,部门编号(dept_id)是一个整数类型(INTEGER),不可以为空(NOT NULL),同时它还是这个表的主键(PRIMARY KEY)。

部门名称(dept_name)是一个可变长度的字符串,最长 50 个字符,不允许为空。

如果我们想要创建一个自定义名称的主键约束,可以使用表级约束:

CREATE TABLE department
    ( dept_id    INTEGER NOT NULL
    , dept_name  VARCHAR(50) NOT NULL
    , CONSTRAINT pk_department PRIMARY KEY (dept_id)
    ) ;

表级约束在所有字段之后定义,其中 pk_dept 是自定义的主键名称。

对于数字类型的主键字段,我们可以通过自增长列(auto increment)自动生成一个唯一的数字。

例如:

CREATE TABLE department
    ( dept_id    INTEGER AUTO_INCREMENT PRIMARY KEY
    , dept_name  VARCHAR(50) NOT NULL
    ) ;

此时,我们在插入数据时不再需要为 dept_id 字段提供数据,MySQL 默认会产生一个从 1 开始,每次递增 1 的数字序列。

然后我们再创建两个表:

CREATE TABLE job
    ( job_id         INTEGER NOT NULL PRIMARY KEY
    , job_title      VARCHAR(50) NOT NULL
    ) ;

CREATE TABLE employee
    ( emp_id    INTEGER NOT NULL PRIMARY KEY
    , emp_name  VARCHAR(50) NOT NULL
    , sex       VARCHAR(10) NOT NULL
    , dept_id   INTEGER NOT NULL
    , manager   INTEGER
    , hire_date DATE NOT NULL
    , job_id    INTEGER NOT NULL
    , salary    NUMERIC(8,2) NOT NULL
    , bonus     NUMERIC(8,2)
    , email     VARCHAR(100) NOT NULL
    , CONSTRAINT ck_emp_sex CHECK (sex IN ('男', '女'))
    , CONSTRAINT ck_emp_salary CHECK (salary > 0)
    , CONSTRAINT uk_emp_email UNIQUE (email)
    , CONSTRAINT fk_emp_dept FOREIGN KEY (dept_id) REFERENCES department(dept_id)
    , CONSTRAINT fk_emp_job FOREIGN KEY (job_id) REFERENCES job(job_id)
    , CONSTRAINT fk_emp_manager FOREIGN KEY (manager) REFERENCES employee(emp_id)
    ) ;

job 表用于存储职位信息,和部门表相似,比较简单。

employee 表用于存储员工信息,包含的字段和约束如下:

  • 员工编号(emp_id)是一个整数类型(INTEGER),不可以为空(NOT NULL),同时它还是这个表的主键(PRIMARY KEY)。
  • 员工姓名(emp_name)是一个可变长度的字符串,最长 50 个字符,不允许为空。
  • 性别(sex)是一个可变长度的字符串,最长 10 个字符,不允许为空;另外,我们通过表级约束 ck_emp_sex 限制了性别的取值只能为“男”或者“女”。
  • 部门编号(dept_id)代表了员工所在的部门,因此通过外键约束 fk_emp_dept 引用了部门表的主键字段。
  • 经理编号(manager)代表了员工的直接上级,可能为空。外键约束 fk_emp_manager 表示经理也属于员工。
  • 入职日期(hire_date)是一个 DATE 类型的字段,不能为空。
  • 职位编号(job_id)代表了员工的职位,因此通过外键 fk_emp_job 引用了职位表的主键字段。
  • 月薪(salary)是一个支持两位小数的数字,不能为空。检查约束 ck_emp_salary 要求月薪必须大于零。
  • 奖金(bonus)是一个可选的数字字段。
  • 电子邮箱(email)是一个可变长度的字符串,最长100 个字符,不允许为空。检查约束 uk_emp_email 要求每个员工的电子邮箱都不相同。

CREATE TABLE … LIKE

除了手动定义表的结构之外,MySQL 还提供了复制已有表结构的方法:

CREATE TABLE [IF NOT EXISTS] table_name
    { LIKE old_tbl_name | (LIKE old_tbl_name) }

MySQL 的 LIKE 语法只复制表结构,包括字段的属性和索引,但是不复制数据。

例如:

CREATE TABLE emp_copy
  LIKE employee;

以上语句基于 employee 表的结构复制生成一个新的表 emp_copy。

mysql> show create table emp_copy \G
*************************** 1. row ***************************
       Table: emp_copy
Create Table: CREATE TABLE `emp_copy` (
  `emp_id` int NOT NULL,
  `emp_name` varchar(50) NOT NULL,
  `sex` varchar(10) NOT NULL,
  `dept_id` int NOT NULL,
  `manager` int DEFAULT NULL,
  `hire_date` date NOT NULL,
  `job_id` int NOT NULL,
  `salary` decimal(8,2) NOT NULL,
  `bonus` decimal(8,2) DEFAULT NULL,
  `email` varchar(100) NOT NULL,
  PRIMARY KEY (`emp_id`),
  UNIQUE KEY `uk_emp_email` (`email`),
  KEY `fk_emp_dept` (`dept_id`),
  KEY `fk_emp_job` (`job_id`),
  KEY `fk_emp_manager` (`manager`),
  CONSTRAINT `emp_copy_chk_1` CHECK ((`salary` > 0)),
  CONSTRAINT `emp_copy_chk_2` CHECK ((`sex` in (_utf8mb4'男',_utf8mb4'女')))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.01 sec)

对于 CREATE TABLE … LIKE 命令,目标表会保留原始表中的主键、唯一约束、非空约束、表达式默认值、检查约束(自动生成约束名),同时还会保留原始表中的计算列定义。

CREATE TABLE … LIKE 命令不会保留外键约束(但是会保留外键索引),以及任何 DATA DIRECTORY 或者 INDEX DIRECTORY 表属性选项。

如果原始表是一个 TEMPORARY 表,CREATE TABLE … LIKE 不会保留 TEMPORARY 关键字。如果想要创建一个临时表,可以使用 CREATE TEMPORARY TABLE … LIKE。

使用 mysql 表空间、InnoDB 系统表空间(innodb_system)或者通用表空间创建的表包含一个 TABLESPACE 属性,表示该表所在的表空间。目前,无论 innodb_file_per_table 设置为什么参数,CREATE TABLE … LIKE 都会保留 TABLESPACE 属性。为了避免复制新表时使用原始表的 TABLESPACE 属性,可以使用下面介绍的第三种方法。例如:

CREATE TABLE new_tbl SELECT * FROM orig_tbl LIMIT 0;

以上语句会基于 orig_tbl 创建一个新的空表 new_tbl,具体参考下一节内容。

CREATE TABLE … LIKE 使用原始表的所有 ENGINE_ATTRIBUTE 和 SECONDARY_ENGINE_ATTRIBUTE 值创建目标表。

另外,LIKE 只能基于表进行复制,而不能复制视图。

CREATE TABLE … SELECT

在 MySQL 中复制表结构的另一种方法就是利用查询语句的结果定义字段和复制的数据:

CREATE TABLE table_name
  [AS] SELECT ...;

其中的 SELECT 语句定义了新表的结构和数据。

以下示例基于查询的结果创建了一个新表:emp_devp,表中包含了研发部的所有员工。

CREATE TABLE emp_devp
    AS
SELECT e.*
  FROM employee e
  JOIN department d
    ON (d.dept_id = e.dept_id AND d.dept_name = '研发部');

对于这种语法,MySQL 实际上是在已有目标表中增加新的字段。

例如:

CREATE TABLE t1(col1 INTEGER, col2 INTEGER);
INSERT INTO t1(col1, col2) VALUES(1, 1), (2, 4);

CREATE TABLE t2(id INTEGER AUTO_INCREMENT PRIMARY KEY)
       ENGINE=InnoDB
    AS SELECT col1, col2 FROM t1;

我们首先为 t2 指定了一个自增 id,然后将 t1 的查询结果添加到该字段的后面。其中,ENGINE 选项属于 CREATE TABLE 语句,因此需要位于 SELECT 语句之前。

查询 t2 可以看到以上语句不仅复制了表结构,同时还复制了 t1 中的数据:

TABLE t2;

+----+------+------+
| id | col1 | col2 |
+----+------+------+
|  1 |    1 |    1 |
|  2 |    2 |    4 |
+----+------+------+
2 rows in set (0.00 sec)

如果只想复制结构,不需要复制数据,可以在查询语句中增加 LIMIT 0 或者 WHERE 1=0 条件。

如果在 SELECT 语句前面增加 IGNORE 或者 REPLACE 关键字,可以处理复制数据时导致唯一键冲突的数据行。对于 IGNORE,源数据中和目标表重复的数据行就会被丢弃;对于 REPLACE,使用新数据行替换目标表中的已有数据行。如果没有指定任何选项,唯一键冲突将会返回错误。

CREATE TABLE … SELECT 命令不会自动创建任何索引,这样可以使得该语句尽量灵活。如果想要创建索引,可以在 SELECT 语句之前指定。

例如:

CREATE TABLE t3(id INTEGER PRIMARY KEY)
AS SELECT col1 as id, col2 FROM t1;

CREATE TABLE … SELECT 命令不会保留计算列的定义,也不会保留默认值定义。同时某些数据类型可能产生转换。例如,AUTO_INCREMENT 属性不会被保留,VARCHAR 类型被转换为 CHAR 类型。保留的属性包括 NULL(NOT NULL)以及 CHARACTER SET、COLLATION、COMMENT 和 DEFAULT 子句。

使用 CREATE TABLE … SELECT 命令创建表时,需要为查询语句中的函数和表达式指定一个别名,否则该命令可能失败或者创建意料之外的字段名:

CREATE TABLE artists_and_works
SELECT artist.name, COUNT(work.artist_id) AS number_of_works
FROM artist LEFT JOIN work ON artist.id = work.artist_id
GROUP BY artist.id;

对于 CREATE TABLE … SELECT 命令,如果我们指定了 IF NOT EXISTS 并且目标表已经存在,不会将数据复制到目标表,同时该语句不会写入日志文件。

CREATE TABLE … SELECT 命令不支持 FOR UPDATE 选项。

CREATE TABLE … SELECT 命令只会应用字段的 ENGINE_ATTRIBUTE 和 SECONDARY_ENGINE_ATTRIBUTE 属性。表和索引的 ENGINE_ATTRIBUTE 和 SECONDARY_ENGINE_ATTRIBUTE 属性不会被应用,除非为目标表明确指定这些选项。

总结

本文通过一些案例介绍了 MySQL 中三种创建表的方法和注意事项。

仅为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • MySQL创建、修改和删除表操作指南

    目录 前言 一.创建表 1.创建表的语法形式 2.设置表的主键 1.单字段主键 2.多字段主键 3.设置表的外键 4.设置表的非空约束 5.设置表的唯一性约束 6.设置表的属性值自动增加 7.设置表的属性的默认值 二.查看表结构 1.查看表基本结构语句DESCRIBE 2.查看表详细结构语句SHOW CREATE TABLE 三.修改表 1.修改表名 2.修改字段的数据类型 3.修改字段名 1.只修改字段名 2.修改字段名称和字段数据类型 4.增加字段 1.增加无完整性约束条件的字段 2.增加有

  • MySQL创建表操作命令分享

    目录 一.表命令 1.查看所有表 2.创建表 3.创建一个用户表 二.MySQL支持的常用数据类型 1.数字型 2.字符串 3.日期 三.MySQL支持的常用约束 四.存储引擎 五.表命令(crud) 1.查看表结构 2.查看表的创建语句 3.更改表名称 4.修改表 5.删除表 六.更新约束 1.先创建一个表,除了主键,不加其他约束. 2.给手机号添加唯一约束 3.删除唯一约束 4.给名字添加非空约束 5.删除非空约束 6.给生日添加默认约束 7.删除默认约束 一.表命令 1.查看所有表 sho

  • MySQL之存储过程按月创建表的方法步骤

    具体不多说,直接上代码.欢迎一起交流和学习. 创建一个按月创建表的存储过程,SQL语句如下: DELIMITER // DROP PROCEDURE IF EXISTS create_table_by_month // CREATE PROCEDURE `create_table_by_month`() BEGIN #--提前申明变量,后面会用到 DECLARE nextMonth varchar(20); DECLARE nextTABLE varchar(20); DECLARE csql

  • MySQL中创建表的三种方法汇总

    目录 CREATE TABLE CREATE TABLE … LIKE CREATE TABLE … SELECT 总结 SQL 标准使用 CREATE TABLE 语句创建数据表:MySQL 则实现了三种创建表的方法,支持自定义表结构或者通过复制已有的表结构来创建新表,本文给大家分别介绍一下这些方法的使用和注意事项. CREATE TABLE CREATE TABLE 语句的基本语法如下: CREATE TABLE [IF NOT EXISTS] table_name ( column1 da

  • JS中动态创建元素的三种方法总结(推荐)

    1.动态创建元素一 document.write() 例如向页面中输出一个 li 标签 <pre class="html" name="code"><span style="font-size:12px;"><script> document.write("<li>123</li>"); </script></span> body标签中就会插入

  • 防止MySQL重复插入数据的三种方法

    新建表格 CREATE TABLE `person` ( `id` int NOT NULL COMMENT '主键', `name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '姓名', `age` int NULL DEFAULT NULL COMMENT '年龄', `address` varchar(512) CHARACTER SET utf8 COLLATE utf8_bin N

  • 在python中创建表格的两种方法实例

    目录 日常拉呱: 创建表格一般有两种方法: 一:通过导入xlwt创建 二:通过导入csv库来创建 1.写入数据 2.读取数据 总结 日常拉呱: 最近在学习爬虫模拟登陆各个软件,老师留有作业,模拟登录京东并爬取系列物品,可惜我还是个小白菜鸟,还是处于迷迷糊糊的状态,只能先了解一下边缘知识.爬取完数据,你是否在纠结这些数据放在哪呢?建一个表格或许会帮助到你! 创建表格一般有两种方法: 一:通过导入xlwt来创建,这种方法我比较喜欢,因为它够直观够容易理解,但是相对而言比较麻烦. 二:通过导入csv库

  • Python中创建字典的几种方法总结(推荐)

    1.传统的文字表达式: >>> d={'name':'Allen','age':21,'gender':'male'} >>> d {'age': 21, 'name': 'Allen', 'gender': 'male'} 如果你可以事先拼出整个字典,这种方式是很方便的. 2.动态分配键值: >>> d={} >>> d['name']='Allen' >>> d['age']=21 >>> d[

  • JS创建事件的三种方法(实例代码)

    1.普通的定义方式 <input type="button" name="Button" value="确定" onclick="Sfont=prompt('请在文本框中输入红色','红色',' 提示框 '); if(Sfont=='红色'){ form1.style.fontFamily='黑体'; form1.style.color='red'; }" /> 这是最常见的一种定义方式,直接将JS事件定义在需要的

  • jQuery中each遍历的三种方法实例分析

    本文实例讲述了jQuery中each遍历的三种方法.分享给大家供大家参考,具体如下: 1.选择器+遍历 $('div').each(function (i){ //i就是索引值 //this 表示获取遍历每一个dom对象 }); 2.选择器+遍历 $('div').each(function (index,domEle){ //index就是索引值 //domEle 表示获取遍历每一个dom对象 }); 3.更适用的遍历方法 1)先获取某个集合对象 2)遍历集合对象的每一个元素 var d=$(

  • MySQL导入sql文件的三种方法小结

    目录 一.使用工具Navicat for MySQL导入 1.打开localhost_3306,选中右击“新建数据库” 2.指定数据库名和字符集(可根据sql文件的字符集类型自行选择) 3.选中数据库下的表运行SQL文件 4.选中路径导入 二.使用官方工具MySQL Workbench导入 1.第一种方法 2.第二种方法 三.使用命令行导入 总结 一.使用工具Navicat for MySQL导入 工具的具体下载及使用方法推荐的一篇文章:https://www.jb51.net/article/

  • 关于C++中定义比较函数的三种方法小结

    C++编程优与Pascal的原因之一是C++中存在STL(标准模板库).STL存在很多有用的方法. C++模板库中的许多方法都需要相关参数有序,例如Sort().显然,如果你想对一个集合进行排序,你必须要知道集合中的对象,那个在前那个在后.因此,学会如何定义比较方法是非常重要的. C++模板库的许多容器需要相关类型有序,例如set<T> 和priority_queue<T>. 这篇文章旨在告诉大家如何为一个类定义一个排序方法,以便在STL容器或者方法中使用. 作为一个C++程序员,

  • Android中使用定时器的三种方法

    本文实例为大家分享了Android中使用定时器的三种方法,供大家参考,具体内容如下 图示: 因为都比较简单,所以就直接贴代码(虑去再次点击停止的操作),有个全局的Handler负责接收消息更新UI 第一种方法:Thread.sleep();方法 Runnable runnable = new Runnable() { @Override public void run() { while (true) { mHandler.sendEmptyMessage(0); try { Thread.sl

随机推荐