MySQL详解

一、数据库概述

1、什么是数据库?

  • **定义**:数据库(Database, DB)是按照数据结构来组织、存储和管理数据的仓库,用于高效存储、检索和管理大量结构化或非结构化数据。

  • **核心目标**:解决数据冗余、数据不一致性问题,确保数据的安全性、完整性和可访问性

2、数据库管理系统(DBMS)

  • **定义**:数据库管理系统是用于管理数据库的软件系统,负责数据的存储、查询、更新、删除等操作,并提供事务管理、权限控制、备份恢复等功能。

  • 常见 DBMS:

  • **关系型数据库**:MySQL、PostgreSQL、Oracle、SQL Server。

  • **非关系型数据库(NoSQL)**:MongoDB、Redis、Cassandra。

3、数据库分类

数据库主要分为**关系型数据库**和 ** 非关系型数据库(NoSQL)** 两大类,两者在数据模型、适用场景上有显著差异。

```

姓名 年纪 地址 性别 出生

张三 18 china man 1990

张三

```

**关系型数据库(SQL)**

  • **数据模型**:基于二维表格(关系表),通过行(记录)和列(字段)存储数据,表间通过主键、外键建立关联。

  • 特点:

  • 结构化强,数据一致性高。

  • 支持复杂查询(如 JOIN、子查询),适合事务性场景(如金融交易、订单系统)。

  • 遵循 ACID 特性(原子性、一致性、隔离性、持久性)。

  • **典型应用**:企业 ERP 系统、银行核心系统、电商订单管理。

** 非关系型数据库(NoSQL)**

  • **数据模型**:采用键值对、文档、列族、图结构等非表格模型存储数据。

  • 特点:

  • 灵活可扩展,适合处理海量非结构化数据(如日志、图片、JSON 文档)。

  • 读写性能高,支持分布式架构。

  • 弱化 ACID,强调 BASE 特性(基本可用、软状态、最终一致性)。

  • 细分类型及示例:

  • **键值存储**:Redis(用于缓存、会话管理)。

  • **文档存储**:MongoDB(用于内容管理、用户数据存储)。

  • **列族存储**:HBase(用于海量数据实时查询,如日志分析)。

  • **图存储**:Neo4j(用于社交网络、推荐系统中的关系分析)。

  • **典型应用**:互联网用户行为分析、实时推荐系统、物联网设备数据存储。

4、结构化查询语言(SQL)

结构化查询语言(SQL)是用于管理和操作关系型数据库的标准编程语言,广泛应用于数据存储、查询、更新和管理。以下是对 SQL 的详细解析:

**. 定义与作用**

  • **SQL(Structured Query Language)**:是一种专门设计用于与数据库通信的编程语言,用于执行数据操作(如查询、插入、更新)和数据库管理(如创建表、修改结构、权限控制)。

  • 核心功能:

  • 数据查询(SELECT):从数据库中检索数据。

  • 数据操作(INSERT、UPDATE、DELETE):增删改数据。

  • 数据定义(CREATE、ALTER、DROP):创建、修改、删除数据库对象(如表、索引)。

  • 数据控制(GRANT、REVOKE):管理用户权限。

**SQL 与数据库的关系**

  • SQL 是一种语言标准,而数据库(如 MySQL、PostgreSQL、Oracle)是实现 SQL 标准的软件系统。不同数据库对 SQL 的支持略有差异,但核心语法一致。

二、MySQL入门

```

MySQL是一个c/s架构的软件

c/s: client (客户端)------> server 服务端 代表应用:QQ 迅雷 企业微信

b/s: browser (浏览器) ----> server 服务端

密码:qwe123 输入的时候要是英文状态,然后必须是小写。

```

MySQL 是全球最流行的开源关系型数据库管理系统(RDBMS),由瑞典 MySQL AB 公司开发,后被 Oracle 收购。它以高性能、可靠性和易用性著称,广泛应用于 Web 应用、企业系统和中小型数据存储场景。以下是对 MySQL 的深度解析:

1、核心特性

开源与跨平台

  • **开源许可证**:采用 GPL(通用公共许可证),允许免费使用和修改,但商业应用需购买商业许可证。

  • **跨平台支持**:支持 Linux、Windows、macOS、Solaris 等主流操作系统。

** 存储引擎**

MySQL 支持多种存储引擎,每个引擎有不同特性,最常用的是:

  • **InnoDB**(默认):支持事务、外键、行级锁和崩溃恢复,适合高并发和写密集型场景。

  • **MyISAM**:不支持事务和外键,读写性能高,但不适合高并发事务场景。

  • **Memory**:数据存储在内存中,查询极快,适合临时数据或缓存。

  • **Archive**:只支持 INSERT 和 SELECT,压缩率高,适合历史数据归档。

**高性能与扩展性**

  • **索引优化**:支持 B-Tree、哈希索引,优化查询效率。

  • **复制(Replication)**:主从复制、主主复制,实现读写分离和高可用性。

  • **分区(Partitioning)**:水平分割大表,提升查询性能。

**安全与权限管理**

  • **用户认证**:基于用户名、主机和密码的访问控制。

  • **细粒度权限**:支持 GRANT/REVOKE 对数据库、表、列级别的权限控制。

  • **加密功能**:支持 SSL/TLS 加密传输,以及数据静态加密(TDE)。

2、MySQL链接

安装 MySQL 后,你可以通过以下几种方式连接到 MySQL 服务端:

  • 1、使用命令行客户端连接

  • 2、使用图形化工具连接

常用 MySQL 图形化管理工具:

使用MySQL命令行链接

```

mysql -u your_username -p

```

**参数说明:**

  • `-u` 参数用于指定用户名。

  • `-p` 参数表示需要输入密码。

指定主机和端口连接(适用于远程连接):

```

mysql -h 主机名或IP地址 -P 端口号 -u 用户名 -p

```

例如:

```

mysql -h 127.0.0.1 -P 3306 -u root -p

```

3、简单的SQL语句

列出所有可用的数据库:

```

SHOW DATABASES;

```

选择要使用的数据库:

```

USE your_database;

```

列出所选数据库中的所有表:

```

SHOW TABLES;

```

退出 **mysql>** 命令提示窗口可以使用 **exit** 命令,如下所示:

```

mysql> EXIT;

Bye

```

或者使用:

```

mysql> QUIT;

```

或者按下 **Ctrl + D**(在 Unix/Linux 系统中)。

4、创建数据库

我们可以在登陆 MySQL 服务后,使用 **create** 命令创建数据库,语法如下:

```

CREATE DATABASE 数据库名;

```

以下命令简单的演示了创建数据库的过程,数据名为 helloworld:

```

root@host# mysql -u root -p

Enter password:****** # 登录后进入终端

mysql> create DATABASE helloworld;

```

建数据库的基本语法如下:

```

CREATE DATABASE IF NOT EXISTS database_name

CHARACTER SET charset_name

COLLATE collation_name;

```

如果你希望在创建数据库时指定一些选项,可以使用 CREATE DATABASE 语句的其他参数,例如,你可以指定字符集和排序规则:

```

CREATE DATABASE mydatabase

CHARACTER SET utf8mb4

COLLATE utf8mb4_general_ci;

```

如果数据库已经存在,执行 CREATE DATABASE 将导致错误。

为了避免这种情况,你可以在 CREATE DATABASE 语句中添加 IF NOT EXISTS 子句:

```

CREATE DATABASE IF NOT EXISTS mydatabase;

```

5、删除数据库

使用普通用户登陆 MySQL 服务器,你可能需要特定的权限来创建或者删除 MySQL 数据库,所以我们这边使用 root 用户登录,root 用户拥有最高权限。

在删除数据库过程中,务必要十分谨慎,因为在执行删除命令后,所有数据将会消失。

**drop 命令删除数据库**

drop 命令格式:

```

DROP DATABASE <database_name>; -- 直接删除数据库,不检查是否存在

DROP DATABASE IF EXISTS <database_name>;

```

**参数说明:**

  • `IF EXISTS` 是一个可选的子句,表示如果数据库存在才执行删除操作,避免因为数据库不存在而引发错误。

  • `database_name` 是你要删除的数据库的名称。

例如删除名为 helloworld 的数据库:

```

-- 直接删除数据库,不检查是否存在

mysql> DROP DATABASE helloworld;

-- 删除数据库,如果存在的话

DROP DATABASE IF EXISTS helloworld;

```

**注意:** 在执行删除数据库操作前,请确保你确实想要删除数据库及其所有数据,因为该操作是不可逆的。为了避免误操作,通常建议在执行删除之前备份数据库。

**6、创建数据表**

**语法**

以下为创建 MySQL 数据表的 SQL 通用语法:

```

CREATE TABLE table_name (

column1 datatype,

column2 datatype,

...

);

create table goods(

name varchar(50),

price decimal(10, 2),

description varchar(500),

address varchar(100)

)charset=utf8;

create table goods()charset=utf8;

添加数据:

INSERT INTO table_name (column1, column2, column3, ...)

VALUES (value1, value2, value3, ...);

insert into goods(name,price,description,address) values("小米 suv7", 10000.01, "are you ok", "beijing");

insert into goods(name,price,description,address) values("小米 Ultra", 100000.01, "are you ok", "beijing");

```

**参数说明:**

  • `table_name` 是你要创建的表的名称。

  • `column1`, `column2`, ... 是表中的列名。

  • `datatype` 是每个列的数据类型。

以下是一个具体的实例,创建一个用户表 **users**:

```

CREATE TABLE users (

id INT AUTO_INCREMENT PRIMARY KEY,

username VARCHAR(50) NOT NULL,

email VARCHAR(100) NOT NULL,

birthdate DATE,

is_active BOOLEAN DEFAULT TRUE

);

```

实例解析:

  • `id`: 用户 id,整数类型,自增长,作为主键。

  • `username`: 用户名,变长字符串,不允许为空。

  • `email`: 用户邮箱,变长字符串,不允许为空。

  • `birthdate`: 用户的生日,日期类型。

  • `is_active`: 用户是否已经激活,布尔类型,默认值为 true。

7、删除数据表

语法

以下为删除 MySQL 数据表的通用语法:

```

DROP TABLE table_name; -- 直接删除表,不检查是否存在

```

```

DROP TABLE IF EXISTS table_name; -- 会检查是否存在,如果存在则删除

```

**参数说明:**

  • `table_name` 是要删除的表的名称。

  • `IF EXISTS` 是一个可选的子句,表示如果表存在才执行删除操作,避免因为表不存在而引发错误。

```

-- 删除表,如果存在的话

DROP TABLE IF EXISTS mytable;

-- 直接删除表,不检查是否存在

DROP TABLE mytable;

```

8、插入数据

语法

以下为向MySQL数据表插入数据通用的 **INSERT INTO** SQL语法:

```

INSERT INTO table_name (column1, column2, column3, ...)

VALUES (value1, value2, value3, ...);

```

**参数说明:**

  • `table_name` 是你要插入数据的表的名称。

  • `column1`, `column2`, `column3`, ... 是表中的列名。

  • `value1`, `value2`, `value3`, ... 是要插入的具体数值。

如果数据是字符型,必须使用单引号 **'** 或者双引号 **"**,如: 'value1', "value1"。

一个简单的实例,插入了一行数据到名为 users 的表中:

```

INSERT INTO users (username, email, birthdate, is_active)

VALUES ('test', 'test@google.com', '1990-01-01', true);

```

  • `username`: 用户名,字符串类型。

  • `email`: 邮箱地址,字符串类型。

  • `birthdate`: 用户生日, 日期类型。

  • `is_active`: 是否已激活,布尔类型。

如果你要插入所有列的数据,可以省略列名:

```

INSERT INTO users

VALUES (NULL,'test', 'test@google.com', '1990-01-01', true);

```

这里,**NULL** 是用于自增长列的占位符,表示系统将为 **id** 列生成一个唯一的值。

如果你要插入多行数据,可以在 VALUES 子句中指定多组数值:

```

INSERT INTO users (username, email, birthdate, is_active)

VALUES

('test1', 'test1@google.com', '1985-07-10', true),

('test2', 'test2@google.com', '1988-11-25', false),

('test3', 'test3@google.com', '1993-05-03', true);

```

以上代码将在 users 表中插入三行数据。

查询数据:

语法:

```

SELECT COLUMN1,COLUMN2...... FROM TABLE_NAME; 显示指定字段

SELECT * FROM TABLE_NAME; 显示所有字段

```

修改数据:

语法:

```

UPDATE TABLE_NAME SET COLUMN=VALUE; 将某一列里面的所有数据都更新

UPDATE TABLE_NAME SET COLUMN=VALUE WHERE 条件;

```

9、表结构修改
  1. 添加列

```

ALTER TABLE 表名

ADD COLUMN 列名 数据类型 约束条件 AFTER 现有列名\|FIRST;

```

示例:

```

-- 在users表的email列后添加age列

ALTER TABLE users

ADD COLUMN age INT NOT NULL DEFAULT 0 AFTER email;

-- 添加多列

ALTER TABLE users

ADD COLUMN phone VARCHAR(20),

ADD COLUMN address VARCHAR(100);

```

  1. 删除列

```

ALTER TABLE 表名

DROP COLUMN 列名;

```

示例:

```

ALTER TABLE users

DROP COLUMN age;

```

  1. 修改列定义

```

ALTER TABLE 表名

MODIFY COLUMN 列名 新数据类型 新约束条件;

```

示例:

```

-- 修改username长度并添加唯一约束

ALTER TABLE users

MODIFY COLUMN username VARCHAR(50) UNIQUE;

-- 修改列默认值

ALTER TABLE users

MODIFY COLUMN status TINYINT DEFAULT 1;

```

  1. 重命名列

```

ALTER TABLE 表名

CHANGE COLUMN 旧列名 新列名 数据类型 约束条件;

```

示例:

```

ALTER TABLE users

CHANGE COLUMN reg_date register_date DATETIME;

```

三、MySQL数据类型

MySQL 中定义数据字段的类型对你数据库的优化是非常重要的。

MySQL 支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。

1、数值类型

MySQL 支持所有标准 SQL 数值数据类型。

这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL 和 NUMERIC),以及近似数值数据类型(FLOAT、REAL 和 DOUBLE PRECISION)。

关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。

BIT数据类型保存位字段值,并且支持 MyISAM、MEMORY、InnoDB 和 BDB表。

作为 SQL 标准的扩展,MySQL 也支持整数类型 TINYINT、MEDIUMINT 和 BIGINT。下面的表显示了需要的每个整数类型的存储和范围。

| 类型 | 大小 | 范围(有符号) | 范围(无符号) | 用途 |

| :----------- | :--------------------------------------- | :----------------------------------------------------------- | :----------------------------------------------------------- | :-------------- |

| TINYINT | 1 Bytes | (-128,127) | (0,255) | 小整数值 |

| SMALLINT | 2 Bytes | (-32 768,32 767) | (0,65 535) | 大整数值 |

| MEDIUMINT | 3 Bytes | (-8 388 608,8 388 607) | (0,16 777 215) | 大整数值 |

| INT或INTEGER | 4 Bytes | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | 大整数值 |

| BIGINT | 8 Bytes | (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) | 极大整数值 |

| FLOAT | 4 Bytes | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 单精度 浮点数值 |

| DOUBLE | 8 Bytes | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 双精度 浮点数值 |

| DECIMAL | 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 | 依赖于M和D的值 | 依赖于M和D的值 | 小数值 |

```

create table demo1(

name varchar(50),

age tinyint unsigned

);

create table demo2(

name varchar(50),

age int

);

create table demo3(

goods_name varchar(50),

price decimal(10, 2)

);

```

2、日期和时间类型

表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。

每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。

TIMESTAMP类型有专有的自动更新特性,将在后面描述。

| 类型 | 大小 ( bytes) | 范围 | 格式 | 用途 |

| :-------- | :------------ | :----------------------------------------------------------- | :------------------ | :----------------------- |

| DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |

| TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS | 时间值或持续时间 |

| YEAR | 1 | 1901/2155 | YYYY | 年份值 |

| DATETIME | 8 | '1000-01-01 00:00:00' 到 '9999-12-31 23:59:59' | YYYY-MM-DD hh:mm:ss | 混合日期和时间值 |

| TIMESTAMP | 4 | '1970-01-01 00:00:01' UTC 到 '2038-01-19 03:14:07' UTC结束时间是第 **2147483647** 秒,北京时间 **2038-1-19 11:14:07**,格林尼治时间 2038年1月19日 凌晨 03:14:07 | YYYY-MM-DD hh:mm:ss | 混合日期和时间值,时间戳 |

```

create table demo4(

title varchar(100),

add_time DATE

);

create table demo5(

title varchar(100),

add_time year

);

```

3、字符串类型

字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。

| 类型 | 大小 | 用途 |

| :--------- | :-------------------- | :------------------------------ |

| CHAR | 0-255 bytes | 定长字符串 |

| VARCHAR | 0-65535 bytes | 变长字符串 |

| TINYBLOB | 0-255 bytes | 不超过 255 个字符的二进制字符串 |

| TINYTEXT | 0-255 bytes | 短文本字符串 |

| BLOB | 0-65 535 bytes | 二进制形式的长文本数据 |

| TEXT | 0-65 535 bytes | 长文本数据 |

| MEDIUMBLOB | 0-16 777 215 bytes | 二进制形式的中等长度文本数据 |

| MEDIUMTEXT | 0-16 777 215 bytes | 中等长度文本数据 |

| LONGBLOB | 0-4 294 967 295 bytes | 二进制形式的极大文本数据 |

| LONGTEXT | 0-4 294 967 295 bytes | 极大文本数据 |

**注意**:char(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字节个数,比如 CHAR(30) 就可以存储 30 个字符。

CHAR 和 VARCHAR 类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。

BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。

BLOB 是一个二进制大对象,可以容纳可变数量的数据。有 4 种 BLOB 类型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它们区别在于可容纳存储范围不同。

有 4 种 TEXT 类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。对应的这 4 种 BLOB 类型,可存储的最大长度不同,可根据实际情况选择。

```

create table demo1(

name char(10)

);

create table demo2(

title varchar(100)

);

create table demo3(

content LONGTEXT

);

```

四、字段约束

在数据库中,字段约束(也称为列约束)是一种规则,用于限制可以存储在表字段中的数据类型、范围或格式。它们确保数据的完整性和一致性,防止无效或不符合业务规则的数据进入数据库。

1、非空约束(not null)

**作用**:字段必须包含值,插入 `NULL` 会报错。

示例:

```

CREATE TABLE users (

name VARCHAR(50) NOT NULL, -- 姓名不能为空

email VARCHAR(50),

);

```

2、唯一约束(**UNIQUE**)

作用:字段值必须唯一,但可以为 `NULL`(多个 `NULL` 被视为相同)。

示例:

```

CREATE TABLE users2 (

email VARCHAR(50) UNIQUE -- 邮箱不能重复

);

```

3、主键约束(**PRIMARY KEY**)

作用:唯一标识表中的记录,隐含 `NOT NULL + UNIQUE`。

示例:

```

CREATE TABLE products (

product_id INT PRIMARY KEY, -- 单字段主键

name VARCHAR(50)

);

-- 复合主键(多个字段组合唯一)

CREATE TABLE order_items (

order_id INT,

product_id INT,

PRIMARY KEY (order_id, product_id)

);

create table wenzhang2(

id int AUTO_INCREMENT primary key,

title varchar(200) UNIQUE not null,

author varchar(50) not null,

address varchar(100) not null,

add_time datetime not null,

content longtext not null

);

insert into wenzhang(id,title, author,address,add_time,content)

values(1, "python 从入门到精通", "zhangsan", "beijing", "2025-5-23 20:59:01", "python nice!")

insert into wenzhang2(title,author,address,add_time,content)

values("python 从入门到精通", "zhangsan", "beijing", "2025-5-23 20:59:01", "python nice!");

```

4、默认约束(**DEFAULT**)

作用:当插入数据未提供值时,自动使用默认值。

```

CREATE TABLE logs (

id INT PRIMARY KEY,

created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 默认当前时间

);

create table demo5(

name varchar(50) not null,

age int not null

);

```

5、自动增长(AUTO_INCREMENT)

在 MySQL 中,`AUTO_INCREMENT` 是一种特殊的字段属性,用于为表中的记录生成唯一的自增数值。它通常与主键(PRIMARY KEY)一起使用,确保每条记录都有一个唯一标识.

**创建表时指定 `AUTO_INCREMENT`**

```

CREATE TABLE users (

id INT PRIMARY KEY AUTO_INCREMENT, -- 自增主键

name VARCHAR(50) NOT NULL,

email VARCHAR(50) UNIQUE

);

```

  • 无需手动插入 `id` 值,MySQL 会自动生成下一个可用的整数。

  • 初始值默认为 `1`,每次插入新记录时递增 `1`。

**起始值与步长**

  • **起始值**:默认从 `1` 开始,可通过 `ALTER TABLE` 修改:

```

ALTER TABLE users AUTO_INCREMENT = 100; -- 下一个插入的id为100

```

  • **步长**:通常为 `1`,不支持直接设置步长(由 MySQL 内部控制)。

**处理删除操作**

若删除某条记录,自增序列不会回退。例如:

```

DELETE FROM users WHERE id = 2; -- 删除id=2的记录

INSERT INTO users (name, email) VALUES ('Charlie', 'charlie@example.com');

-- 新记录的id=3(而非2)

```

**手动插入自增字段**

可以手动指定 `id` 值,但需确保不与现有值冲突:

```

INSERT INTO users (id, name, email) VALUES (10, 'David', 'david@example.com');

-- 强制使用id=10,下一个自动生成的id为11

```

6、注释(comment)

在 MySQL 中,注释(**COMMENT**)是一种用于为表、列(字段)、存储过程等数据库对象添加说明文字的机制。它不会影响数据库的功能,但能帮助开发者理解表结构和数据含义。

**列(字段)注释**

为表中的字段添加描述性信息,便于后续维护。

```

CREATE TABLE usersss (

id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID,自增主键',

name VARCHAR(50) NOT NULL COMMENT '用户姓名',

email VARCHAR(50) UNIQUE COMMENT '用户邮箱,唯一标识'

);

```

查看列注释:

```

SHOW FULL COLUMNS FROM users;

```

**表注释**

为整个表添加说明,解释其用途和数据范围。

```

CREATE TABLE products (

product_id INT PRIMARY KEY,

name VARCHAR(50)

) COMMENT = '存储所有商品的基础信息,包括名称、价格等';

```

查看表注释:

```

SHOW CREATE TABLE products;

```

五、数据表关系

在 MySQL 中,表关系(Table Relationships)用于建立不同数据表之间的关联,使数据能够以结构化方式组织和查询。常见的表关系包括**一对一**、**一对多**和**多对多**,这些关系通过外键实现。

1、 **一对一关系(One-to-One)**

**特点**

  • **一个记录仅对应另一个表中的一个记录**:例如,一个用户(User)只有一个详细资料(Profile)。

  • **实现方式**:在任意一方添加唯一外键,指向另一方的主键。

```sql

-- 用户表

CREATE TABLE users (

user_id INT PRIMARY KEY,

username VARCHAR(50)

);

-- 资料表

CREATE TABLE profiles (

profile_id INT PRIMARY KEY,

address VARCHAR(100),

user_id INT UNIQUE, -- 唯一外键,关联users表的user_id

);

create table student(

id int unsigned auto_increment comment "主键",

name varchar(50) not null comment "学生的名字",

age tinyint unsigned not null comment "学生的年纪",

sex tinyint unsigned not null default 1 comment "1代表男,0代表女",

primary key(id)

);

create table student_profile(

height tinyint unsigned not null comment "学生的身高",

id_num char(18) unique not null comment "学生的身份证号码",

student_id int unsigned not null comment "存储学生的id"

);

张三 18 1 182 23412341234123412341234

```

2、**一对多关系(One-to-Many)**

**特点**

  • **一个记录对应多个记录**:例如,一个部门(Department)可以有多个员工(Employee)。

  • **实现方式**:在 "多" 的一方表中添加外键,指向 "一" 的一方的主键。

```sql

-- 部门表(一)

CREATE TABLE departments (

dept_id INT PRIMARY KEY,

dept_name VARCHAR(50)

);

-- 员工表(多)

CREATE TABLE employees (

emp_id INT PRIMARY KEY,

emp_name VARCHAR(50),

dept_id INT, -- 外键,关联departments表的dept_id

);


create table department(

id int unsigned auto_increment comment "主键",

dept_name varchar(50) not null comment "部门的名称",

leader varchar(50) not null comment "部门领导",

information text not null comment "部门介绍",

primary key(id)

);

insert into department(dept_name, leader, information) values("人事部", "zhangsan", "adfadsadfadsfsaddf");

insert into department(dept_name, leader, information) values("财务部", "lisi", "adfadsadfadsfsaddf");

create table employees(

id int unsigned auto_increment comment "主键",

name varchar(50) not null comment "员工的名称",

salary int unsigned not null comment "员工的工资",

department_id int unsigned not null comment "部门的id",

primary key(id)

);

insert into employees(name, salary, department_id) values("小红", 8000, 1);

insert into employees(name, salary, department_id) values("小花", 9000, 1);

```

3、**多对多关系(Many-to-Many)**

**特点**

  • **多个记录对应多个记录**:例如,一个学生(Student)可以选修多门课程(Course),一门课程也可以被多个学生选修。

  • **实现方式**:通过创建中间表(关联表),将多对多拆分为两个一对多关系。

```sql

-- 学生表

CREATE TABLE students (

student_id INT PRIMARY KEY,

student_name VARCHAR(50)

);

-- 课程表

CREATE TABLE courses (

course_id INT PRIMARY KEY,

course_name VARCHAR(50)

);

-- 中间表(关联表)

CREATE TABLE student_courses (

student_id INT,

course_id INT,

);

学生管理系统:

create table student2(

id int unsigned auto_increment comment "主键",

name varchar(50) not null comment "学生的名称",

age tinyint unsigned not null comment "学生的年纪",

sex tinyint unsigned not null default 1 comment "1代表男,0代表女",

courses varchar(500) not null comment "学习选择的课程",

primary key(id)

);

insert into student2(name,age,sex, courses) values(

"小红", 18, 1, "1|2|3"

);

================================== 优化版 =======================================

create table student3(

id int unsigned auto_increment comment "主键",

name varchar(50) not null comment "学生的名称",

age tinyint unsigned not null comment "学生的年纪",

sex tinyint unsigned not null default 1 comment "1代表男,0代表女",

primary key(id)

);

insert into student3(name,age,sex, courses) values(

"小红", 18, 1

);

insert into student3(name,age,sex, courses) values(

"小花", 18, 0

);

小红id: 1

小花id: 2

create table student_course(

student_id int unsigned not null comment "学生id",

course_id int unsigned not null comment "课程id",

);

insert into student_course(student_id, course_id) values(1, 1); 小红 计算机组成原理

insert into student_course(student_id, course_id) values(1, 2); 小红 操作系统

insert into student_course(student_id, course_id) values(1, 3); 小红 数据库理论

insert into student_course(student_id, course_id) values(2, 2); 小花 操作系统

insert into student_course(student_id, course_id) values(2, 3); 小花 数据库理论

create table course(

id int unsigned auto_increment comment "主键",

course_name varchar(50) not null comment "课程的名称",

course_count int unsigned not null comment "课时",

primary key(id)

);

insert into course(course_name, course_count) values("计算机组成原理", 150); 1

insert into course(course_name, course_count) values("操作系统", 140); 2

insert into course(course_name, course_count) values("数据库理论", 30); 3

```

六、查询

1. 条件

使用where子句对表中的数据筛选,结果为true的行会出现在结果集中

  • 语法如下:

```sql

select * from 表名 where 条件;

例:

select * from students where id=1;

create table student(

id int unsigned auto_increment comment "主键",

name varchar(50) not null comment "学生的名称",

age tinyint unsigned not null comment "学生的年纪",

gender tinyint unsigned not null default 1 comment "学生的性别,1代表男,0代表女",

height tinyint unsigned not null comment "学生的身高",

address varchar(500) not null comment "地址",

primary key(id)

);

insert into student(name,age,gender,height,address) values("小红", 18, 0, 182, "北京");

insert into student(name,age,gender,height,address) values("小花", 19, 0, 170, "长沙");

insert into student(name,age,gender,height,address) values("小绿", 20, 1, 160, "深圳");

insert into student(name,age,gender,height,address) values("小明", 30, 0, 182, "上海");

insert into student(name,age,gender,height,address) values("大明", 40, 1, 190, "新疆");

insert into student(name,age,gender,height,address) values("二明", 35, 1, 187, "西藏");

insert into student(name,age,gender,height,address) values("小蓝", 16, 0, 150, "长沙");

insert into student(name,age,gender,height,address) values("小紫", 16, 0, 150, "长沙");

insert into student(name,age,gender,height,address) values("大牛", 16, 1, 150, "上海");

insert into student(name,age,gender,height,address) values("如花", 16, 3, 150, "上海");

insert into student(name,age,gender,height,address) values("凤姐", 25, 0, 150, "上海");

```

  • where后面支持多种运算符,进行条件的处理

  • 比较运算符

  • 逻辑运算符

  • 模糊查询

  • 范围查询

  • 空判断

比较运算符

  • 等于: =

  • 大于: >

  • 大于等于: >=

  • 小于: <

  • 小于等于: <=

  • 不等于: != 或 <>

例1:查询编号大于3的学生

```sql

select * from students where id > 3;

```

例2:查询编号不大于4的学生

```sql

select * from students where id <= 4;

```

例3:查询姓名不是"黄蓉"的学生

```sql

select * from students where name != '黄蓉';

```

例4:查询没被删除的学生

```sql

select * from students where is_delete=0;

```

逻辑运算符

  • and

  • or

  • not

例5:查询编号大于3的女同学

```sql

select * from students where id > 3 and gender=0;

```

例6:查询编号小于4或没被删除的学生

```sql

select * from students where id < 4 or is_delete=0;

```

模糊查询

  • like

  • %表示任意多个任意字符

  • %

  • _表示一个任意字符

例7:查询姓黄的学生

```sql

select * from students where name like '黄%';

```

例8:查询姓黄并且"名"是一个字的学生

```sql

select * from students where name like '黄_';

```

例9:查询姓黄或叫靖的学生

```sql

select * from students where name like '黄%' or name like '%靖';

```

范围查询

  • in表示在一个非连续的范围内

例10:查询编号是1或3或8的学生

```sql

select * from students where id in(1,3,8);

```

  • between ... and ...表示在一个连续的范围内

例11:查询编号为3至8的学生

```sql

select * from students where id between 3 and 8;

```

例12:查询编号是3至8的男生

```sql

select * from students where (id between 3 and 8) and gender=1;

```

空判断

  • 注意:null与''是不同的

  • 判空is null

例13:查询没有填写身高的学生

```sql

select * from students where height is null;

```

  • 判非空is not null

例14:查询填写了身高的学生

```sql

select * from students where height is not null;

```

例15:查询填写了身高的男生

```sql

select * from students where height is not null and gender=1;

```

优先级

  • 优先级由高到低的顺序为:小括号,not,比较运算符,逻辑运算符

  • and比or先运算,如果同时出现并希望先算or,需要结合()使用

2. 排序

为了方便查看数据,可以对数据进行排序

语法:

```sql

select * from 表名 order by 列1 asc|desc ,列2 asc\|desc,...

```

说明

  • 将行数据按照列1进行排序,如果某些行列1的值相同时,则按照列2排序,以此类推

  • 默认按照列值从小到大排列(asc)

  • asc从小到大排列,即升序

  • desc从大到小排序,即降序

例1:查询未删除男生信息,按学号降序

```sql

select * from students where gender=1 and is_delete=0 order by id desc;

```

例2:显示所有的学生信息,先按照年龄从大-->小排序,当年龄相同时 按照身高从高-->矮排序

```sql

select * from students order by age desc,height desc;

```

3. 聚合函数

为了快速得到统计数据,经常会用到如下5个聚合函数

总数

  • count(*)表示计算总行数,括号中写星与列名,结果是相同的

例1:查询学生总数

```sql

select count(*) from students;

```

最大值

  • max(列)表示求此列的最大值

例2:查询女生的编号最大值

```sql

select max(id) from students where gender=2;

```

最小值

  • min(列)表示求此列的最小值

例3:查询未删除的学生最小编号

```sql

select min(id) from students where is_delete=0;

```

求和

  • sum(列)表示求此列的和

例4:查询男生的总年龄

```sql

select sum(age) from students where gender=1;

-- 平均年龄

select sum(age)/count(*) from students where gender=1;

```

平均值

  • avg(列)表示求此列的平均值

例5:查询未删除女生的编号平均值

```sql

select avg(id) from students where is_delete=0 and gender=2;

```

4. 分组

group by

  1. group by的含义:将查询结果按照1个或多个字段进行分组,字段值相同的为一组

  2. group by可用于单个字段分组,也可用于多个字段分组

```

gender count members

1 20 小红,小花,小紫....

0 30 大明,二明

```

group by + group_concat()

  1. group_concat(字段名)可以作为一个输出字段来使用,

  2. 表示分组之后,根据分组结果,使用group_concat()来放置每一组的某字段的值的集合

```sql

select gender from students group by gender;

+--------+

| gender |

+--------+

| 男 |

| 女 |

| 中性 |

| 保密 |

+--------+

select gender,group_concat(name) from students group by gender;

+--------+-----------------------------------------------------------+

| gender | group_concat(name) |

+--------+-----------------------------------------------------------+

| 男 | 彭于晏,刘德华,周杰伦,程坤,郭靖 |

| 女 | 小明,小月月,黄蓉,王祖贤,刘亦菲,静香,周杰 |

| 中性 | 金星 |

| 保密 | 凤姐 |

+--------+-----------------------------------------------------------+

select gender,group_concat(id) from students group by gender;

+--------+------------------+

| gender | group_concat(id) |

+--------+------------------+

| 男 | 3,4,8,9,14 |

| 女 | 1,2,5,7,10,12,13 |

| 中性 | 11 |

| 保密 | 6 |

+--------+------------------+

```

group by + 集合函数

  1. 通过group_concat()的启发,我们既然可以统计出每个分组的某字段的值的集合,那么我们也可以通过集合函数来对这个`值的集合`做一些操作

```sql

select gender,group_concat(age) from students group by gender;

+--------+----------------------+

| gender | group_concat(age) |

+--------+----------------------+

| 男 | 29,59,36,27,12 |

| 女 | 18,18,38,18,25,12,34 |

| 中性 | 33 |

| 保密 | 28 |

+--------+----------------------+

分别统计性别为男/女的人年龄平均值

select gender,avg(age) from students group by gender;

+--------+----------+

| gender | avg(age) |

+--------+----------+

| 男 | 32.6000 |

| 女 | 23.2857 |

| 中性 | 33.0000 |

| 保密 | 28.0000 |

+--------+----------+

分别统计性别为男/女的人的个数

select gender,count(*) from students group by gender;

+--------+----------+

| gender | count(*) |

+--------+----------+

| 男 | 5 |

| 女 | 7 |

| 中性 | 1 |

| 保密 | 1 |

+--------+----------+

gender avg_age

1 20

0 18

```

group by + having

  1. having 条件表达式:用来分组查询后指定一些条件来输出查询结果

  2. having作用和where一样,但having只能用于group by

```sql

select gender,count(*) from students group by gender having count(*)>2;

+--------+----------+

| gender | count(*) |

+--------+----------+

| 男 | 5 |

| 女 | 7 |

+--------+----------+

```

5. 获取部分行

当数据量过大时,在一页中查看数据是一件非常麻烦的事情

语法

```sql

select * from 表名 limit start,count

```

说明

  • 从start开始,获取count条数据

例1:查询前3行男生信息

```sql

select * from students where gender=1 limit 0,3;

```

示例:分页

  • 已知:每页显示m条数据,当前显示第n页

  • 求总页数:此段逻辑后面会在python中实现

  • 查询总条数p1

  • 使用p1除以m得到p2

  • 如果整除则p2为总数页

  • 如果不整除则p2+1为总页数

  • 求第n页的数据

```sql

select * from students where is_delete=0 limit (n-1)*m,m

```

6. 连接查询

当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回

mysql支持三种类型的连接查询,分别为:

  • 内连接查询:查询的结果为两个表匹配到的数据

  • 右连接查询:查询的结果为两个表匹配到的数据,右表特有的数据,对于左表中不存在的数据使用null填充

  • 左连接查询:查询的结果为两个表匹配到的数据,左表特有的数据,对于右表中不存在的数据使用null填充

```

需求:查询数据库获取小红的工资和部门信息。

select * from employees where id = 1;

select employees.id,employees.name,employees.salary,department.dept_name from employees

join department

on department.id = employees.department_id

where employees.id = 1;

select employees.id,employees.name,employees.salary,department.dept_name from employees

right join department

on department.id = employees.department_id

where employees.id = 1;

select employees.id,employees.name,employees.salary,department.dept_name from employees

left join department

on department.id = employees.department_id

where employees.id = 1;

select employees.id,employees.name,employees.salary,department.dept_name from employees join department

on department.id = employees.department_id

where employees.id = 3;

```

语法

```sql

select * from 表1 inner或left或right join 表2 on 表1.列 = 表2.列

```

例1:使用内连接查询班级表与学生表

```sql

select * from students inner join classes on students.cls_id = classes.id;

```

例2:使用左连接查询班级表与学生表

  • 此处使用了as为表起别名,目的是编写简单

```sql

select * from students as s left join classes as c on s.cls_id = c.id;

```

例3:使用右连接查询班级表与学生表

```sql

select * from students as s right join classes as c on s.cls_id = c.id;

```

例4:查询学生姓名及班级名称

```sql

select s.name,c.name from students as s inner join classes as c on s.cls_id = c.id;

```

七、Python操作MySQL

1. 安装 pymysql

```bash

pip install pymysql

```

2. 连接数据库

```python

import pymysql

连接数据库

conn = pymysql.connect(

host='localhost', # 主机名

user='your_username', # 用户名

password='your_password', # 密码

database='your_database', # 数据库名

charset='utf8mb4', # 字符集

cursorclass=pymysql.cursors.DictCursor # 返回字典格式的结果

)

try:

创建游标对象

with conn.cursor() as cursor:

执行 SQL 查询

sql = "SELECT VERSION()"

cursor.execute(sql)

获取单条数据

result = cursor.fetchone()

print(f"数据库版本: {result}")

finally:

关闭数据库连接

conn.close()

```

3. 创建表

```python

try:

with conn.cursor() as cursor:

创建 users 表

sql = """

CREATE TABLE IF NOT EXISTS users (

id INT PRIMARY KEY AUTO_INCREMENT,

name VARCHAR(50) NOT NULL,

age INT,

email VARCHAR(100) UNIQUE

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

"""

cursor.execute(sql)

提交事务

conn.commit()

print("表创建成功")

except Exception as e:

print(f"表创建失败: {e}")

回滚事务

conn.rollback()

```

4. 插入数据

```python

try:

with conn.cursor() as cursor:

插入单条数据

sql = "INSERT INTO users (name, age, email) VALUES (%s, %s, %s)"

cursor.execute(sql, ('Alice', 25, 'alice@example.com'))

插入多条数据

users = [

('Bob', 30, 'bob@example.com'),

('Charlie', 22, 'charlie@example.com')

]

sql = "INSERT INTO users (name, age, email) VALUES (%s, %s, %s)"

cursor.executemany(sql, users)

提交事务

conn.commit()

print(f"成功插入 {cursor.rowcount} 条数据")

except Exception as e:

print(f"数据插入失败: {e}")

conn.rollback()

```

5. 查询数据

```python

查询所有数据

try:

with conn.cursor() as cursor:

sql = "SELECT * FROM users"

cursor.execute(sql)

results = cursor.fetchall() # 获取所有记录

for row in results:

print(f"ID: {row'id'}, 姓名: {row'name'}, 年龄: {row'age'}, 邮箱: {row'email'}")

except Exception as e:

print(f"查询失败: {e}")

查询单条数据

try:

with conn.cursor() as cursor:

sql = "SELECT * FROM users WHERE id = %s"

cursor.execute(sql, (1,))

result = cursor.fetchone() # 获取单条记录

print(f"ID为1的用户: {result}")

except Exception as e:

print(f"查询失败: {e}")

```

6. 更新数据

```python

try:

with conn.cursor() as cursor:

sql = "UPDATE users SET age = age + 1 WHERE name = %s"

cursor.execute(sql, ('Alice',))

提交事务

conn.commit()

print(f"成功更新 {cursor.rowcount} 条数据")

except Exception as e:

print(f"数据更新失败: {e}")

conn.rollback()

```

7. 删除数据

```python

try:

with conn.cursor() as cursor:

sql = "DELETE FROM users WHERE age < %s"

cursor.execute(sql, (25,))

提交事务

conn.commit()

print(f"成功删除 {cursor.rowcount} 条数据")

except Exception as e:

print(f"数据删除失败: {e}")

conn.rollback()

```

8. 使用上下文管理器管理连接

为了简化资源管理,可以将数据库连接封装成上下文管理器:

```python

class MySQLConnection:

def init(self, host, user, password, database):

self.host = host

self.user = user

self.password = password

self.database = database

self.conn = None

def enter(self):

self.conn = pymysql.connect(

host=self.host,

user=self.user,

password=self.password,

database=self.database,

cursorclass=pymysql.cursors.DictCursor

)

return self.conn

def exit(self, exc_type, exc_val, exc_tb):

if self.conn:

self.conn.close()

使用示例

with MySQLConnection('localhost', 'user', 'password', 'dbname') as conn:

with conn.cursor() as cursor:

cursor.execute("SELECT * FROM users")

results = cursor.fetchall()

for row in results:

print(row)

```

9. 处理数据库事务

```python

try:

with conn.cursor() as cursor:

开始事务

conn.begin()

执行多个操作

cursor.execute("INSERT INTO users (name, age) VALUES (%s, %s)", ('David', 28))

cursor.execute("UPDATE users SET age = age + 1 WHERE name = 'Bob'")

提交事务

conn.commit()

print("事务提交成功")

except Exception as e:

回滚事务

conn.rollback()

print(f"事务回滚: {e}")

```

```

create table blog(

id int unsigned not null auto_increment comment "主键",

title varchar(200) not null comment "文章标题",

authoer varchar(50) not null comment "文章作者",

description varchar(500) not null comment "文章摘要",

content text not null comment "内容",

primary key(id)

)charset=utf8;

```

相关推荐
kisdiem11 小时前
RAG ENGINEERING · 中文教程从文档到可靠答案
数据库
SilentSamsara12 小时前
向量数据库实战:Chroma/Milvus/Qdrant 选型与语义搜索应用
开发语言·数据库·人工智能·python·青少年编程·milvus
沪漂阿龙12 小时前
LangChain 系列之Agent:从固定流程到模型自主决策
服务器·数据库·langchain
zh_xuan12 小时前
PC端操作SQLite数据库
数据库·c++·sqlite
MXsoft61812 小时前
**采集节点主备模:保障监控系统自身高可用**
数据库
yyuuuzz13 小时前
独立站运营的几个技术层面常见问题
大数据·运维·服务器·网络·数据库·aws
IT策士13 小时前
Redis 从入门到精通:Redis Stream —— 可靠消息队列
数据库·redis·缓存
北风toto13 小时前
深度拆解:本体与智能体协同生成SQL的底层逻辑与工程实践
数据库·sql·microsoft
倒流时光三十年13 小时前
PostgreSQL NULLIF 条件表达式函数详解
数据库·sql·postgresql
代码小库13 小时前
【2026前端转 AI 全栈指南】第 2 章(下):NestJS 项目创建 · MongoDB 配置 · 项目启动与调试
前端·数据库·mongodb