MySQL 表结构与数据类型

MySQLBeginner
立即练习

介绍

在本实验中,我们将探索 MySQL 表结构和数据类型的基础知识。理解如何创建、修改和管理表对于任何使用数据库的人来说都至关重要。我们将学习 MySQL 中的不同数据类型,如何根据需求选择合适的数据类型,以及如何执行基本的表操作。通过本实验,你将获得创建表、定义具有适当数据类型的列以及修改表结构的实践经验。

目标

完成本实验后,你将能够:

  • 理解 MySQL 的核心数据类型及其适用场景
  • 创建具有适当列定义的表
  • 修改现有表结构
  • 在不再需要时删除表
  • 查看并理解表的元数据
这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 82%。获得了学习者 99% 的好评率。

理解 MySQL 数据类型

在这一步中,我们将探索最常用的 MySQL 数据类型。理解数据类型至关重要,因为为列选择正确的数据类型会影响数据完整性和数据库性能。

由于这一步涉及许多 SQL 命令,我们建议使用 Web 终端。点击“Terminal”标签页打开它;它的功能与桌面终端相同。

MySQL Web 终端界面

让我们首先连接到 MySQL:

sudo mysql -u root

现在我们已经连接成功,让我们为实验创建一个新的数据库:

CREATE DATABASE store;
USE store;

让我们看看 MySQL 数据类型的主要类别:

  1. 数值类型:

    • INT:用于整数
    • DECIMAL:用于精确的十进制数
    • FLOAT/DOUBLE:用于近似的十进制数
  2. 字符串类型:

    • VARCHAR:用于可变长度的字符串
    • CHAR:用于固定长度的字符串
    • TEXT:用于长文本
  3. 日期和时间类型:

    • DATE:用于日期(YYYY-MM-DD)
    • TIME:用于时间(HH:MM:SS)
    • DATETIME:用于日期和时间

让我们创建一个简单的表来展示这些不同的数据类型:

CREATE TABLE products (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    price DECIMAL(10,2) NOT NULL,
    description TEXT,
    weight FLOAT,
    in_stock BOOLEAN,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

让我们分解一下这个表结构:

  • id:一个自增的整数,作为主键
  • name:一个可变长度的字符串,不能为 NULL
  • price:一个精确的十进制数,总共有 10 位数字,其中 2 位是小数
  • description:一个用于较长描述的文本字段
  • weight:一个用于近似十进制值的浮点数
  • in_stock:一个布尔字段(TRUE/FALSE)
  • created_at:自动存储创建时间戳
  • last_updated:在记录更改时自动更新

要查看我们表的结构:

DESCRIBE products;

你应该会看到类似以下的输出:

+--------------+---------------+------+-----+---------------------+-------------------------------+
| Field        | Type          | Null | Key | Default             | Extra                         |
+--------------+---------------+------+-----+---------------------+-------------------------------+
| id           | int(11)       | NO   | PRI | NULL                | auto_increment                |
| name         | varchar(100)  | NO   |     | NULL                |                               |
| price        | decimal(10,2) | NO   |     | NULL                |                               |
| description  | text          | YES  |     | NULL                |                               |
| weight       | float         | YES  |     | NULL                |                               |
| in_stock     | tinyint(1)    | YES  |     | NULL                |                               |
| created_at   | datetime      | YES  |     | current_timestamp() |                               |
| last_updated | timestamp     | NO   |     | current_timestamp() | on update current_timestamp() |
+--------------+---------------+------+-----+---------------------+-------------------------------+
8 rows in set (0.001 sec)

创建带约束的表

在这一步中,我们将学习表约束以及它们如何帮助维护数据完整性。我们将创建一个更复杂的表结构,以展示各种类型的约束。

让我们创建两个相关的表来理解关系和约束:

CREATE TABLE categories (
    category_id INT AUTO_INCREMENT PRIMARY KEY,
    category_name VARCHAR(50) NOT NULL UNIQUE,
    description VARCHAR(200),
    active BOOLEAN DEFAULT TRUE
);

CREATE TABLE inventory_items (
    item_id INT AUTO_INCREMENT PRIMARY KEY,
    category_id INT,
    sku VARCHAR(20) NOT NULL UNIQUE,
    item_name VARCHAR(100) NOT NULL,
    quantity INT NOT NULL CHECK (quantity >= 0),
    unit_price DECIMAL(10,2) NOT NULL,
    FOREIGN KEY (category_id) REFERENCES categories(category_id)
);

让我们看看我们使用的约束:

  1. PRIMARY KEY:确保每条记录的唯一标识
  2. UNIQUE:防止列中出现重复值
  3. NOT NULL:确保列不能包含 NULL 值
  4. CHECK:在插入数据之前验证数据
  5. FOREIGN KEY:确保表之间的引用完整性
  6. DEFAULT:如果未指定值,则提供默认值

要查看带约束的表结构:

SHOW CREATE TABLE inventory_items;

这将显示完整的 CREATE TABLE 语句,包括所有约束:

MariaDB [store]> SHOW CREATE TABLE inventory_items;

<!-- 示例输出 -->

CREATE TABLE `inventory_items` (
  `item_id` int(11) NOT NULL AUTO_INCREMENT,
  `category_id` int(11) DEFAULT NULL,
  `sku` varchar(20) NOT NULL,
  `item_name` varchar(100) NOT NULL,
  `quantity` int(11) NOT NULL CHECK (`quantity` >= 0),
  `unit_price` decimal(10,2) NOT NULL,
  PRIMARY KEY (`item_id`),
  UNIQUE KEY `sku` (`sku`),
  KEY `category_id` (`category_id`),
  CONSTRAINT `inventory_items_ibfk_1` FOREIGN KEY (`category_id`) REFERENCES `categories` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci

修改表结构

在这一步中,我们将学习如何使用 ALTER TABLE 命令修改现有表。当你的数据需求随时间变化时,这是一项常见任务。

让我们修改 products 表,添加一些新列并修改现有列:

  1. 添加新列:
ALTER TABLE products
ADD COLUMN manufacturer VARCHAR(100) AFTER name;

此命令在 name 列之后添加一个名为 manufacturer 的新列。

  1. 修改现有列:
ALTER TABLE products
MODIFY COLUMN description VARCHAR(500) NOT NULL DEFAULT 'No description available';

此命令将 description 列更改为最大长度为 500 个字符的可变长度字符串,并为新行设置默认值 'No description available'

  1. 重命名列:
ALTER TABLE products
CHANGE COLUMN weight product_weight DECIMAL(8,2);

此命令将 weight 列重命名为 product_weight,并将其数据类型更改为总共有 8 位数字,其中 2 位是小数的十进制数。

  1. 删除列:
ALTER TABLE products
DROP COLUMN in_stock;

此命令从表中删除 in_stock 列。

让我们添加一个复合索引以提高查询性能:

ALTER TABLE products
ADD INDEX idx_name_manufacturer (name, manufacturer);

此命令在 namemanufacturer 列上创建一个复合索引。

要查看我们所做的所有更改:

DESCRIBE products;
SHOW INDEX FROM products;

你应该会看到更新后的表结构和索引:

MariaDB [store]> DESCRIBE products;
+----------------+---------------+------+-----+--------------------------+-------------------------------+
| Field          | Type          | Null | Key | Default                  | Extra                         |
+----------------+---------------+------+-----+--------------------------+-------------------------------+
| id             | int(11)       | NO   | PRI | NULL                     | auto_increment                |
| name           | varchar(100)  | NO   | MUL | NULL                     |                               |
| manufacturer   | varchar(100)  | YES  |     | NULL                     |                               |
| price          | decimal(10,2) | NO   |     | NULL                     |                               |
| description    | varchar(500)  | NO   |     | No description available |                               |
| product_weight | decimal(8,2)  | YES  |     | NULL                     |                               |
| created_at     | datetime      | YES  |     | current_timestamp()      |                               |
| last_updated   | timestamp     | NO   |     | current_timestamp()      | on update current_timestamp() |
+----------------+---------------+------+-----+--------------------------+-------------------------------+
8 rows in set (0.001 sec)

MariaDB [store]> SHOW INDEX FROM products;
+----------+------------+-----------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
| Table    | Non_unique | Key_name              | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Ignored |
+----------+------------+-----------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
| products |          0 | PRIMARY               |            1 | id           | A         |           0 |     NULL | NULL   |      | BTREE      |         |               | NO      |
| products |          1 | idx_name_manufacturer |            1 | name         | A         |           0 |     NULL | NULL   |      | BTREE      |         |               | NO      |
| products |          1 | idx_name_manufacturer |            2 | manufacturer | A         |           0 |     NULL | NULL   | YES  | BTREE      |         |               | NO      |
+----------+------------+-----------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
3 rows in set (0.000 sec)

处理表信息

在这一步中,我们将探索检索表及其结构信息的各种方法。

首先,让我们查看表的状态信息:

SHOW TABLE STATUS FROM store;

此命令显示数据库中每个表的信息,包括:

  • 存储引擎
  • 行格式
  • 行数
  • 平均行长度
  • 数据长度
  • 索引长度

要查看数据库中的所有表:

SHOW TABLES;

要查看特定列的详细信息:

SHOW FULL COLUMNS FROM products;

这提供了有关每列的附加信息,包括:

  • 列类型
  • 排序规则
  • 权限
  • 注释

要查看表上的所有索引:

SHOW INDEX FROM products;

我们还可以从 INFORMATION_SCHEMA 数据库中获取表的信息:

SELECT
    TABLE_NAME,
    ENGINE,
    TABLE_ROWS,
    AVG_ROW_LENGTH,
    DATA_LENGTH,
    INDEX_LENGTH
FROM
    INFORMATION_SCHEMA.TABLES
WHERE
    TABLE_SCHEMA = 'store';

删除表与清理

在这最后一步中,我们将学习如何在不再需要时安全地删除表。这是一项重要的技能,但应谨慎使用,因为删除表会永久删除其所有数据。

在删除表之前,建议执行以下操作:

  1. 确认你处于正确的数据库中
  2. 检查表是否存在
  3. 如果需要,确保你有备份

让我们首先检查当前数据库和表:

SELECT DATABASE();
SHOW TABLES;

为了安全地删除表,我们可以使用 IF EXISTS 子句:

DROP TABLE IF EXISTS inventory_items;

请注意,我们需要先删除具有外键约束的表。如果我们尝试先删除 categories 表,将会出现错误,因为 inventory_items 引用了它。

现在我们可以删除剩余的表:

DROP TABLE IF EXISTS categories;
DROP TABLE IF EXISTS products;

要验证表是否已删除:

SHOW TABLES;

你应该会看到一个空集,表示所有表都已被删除。

总结

在本实验中,我们涵盖了使用 MySQL 表和数据类型的核心内容:

  1. 理解并使用不同的 MySQL 数据类型
  2. 创建带有适当约束的表
  3. 使用 ALTER TABLE 修改表结构
  4. 检索表元数据和信息
  5. 在不再需要时安全地删除表

这些技能是有效使用 MySQL 数据库的基础。