一、数据库概述
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、核心特性
开源与跨平台
** 存储引擎**
MySQL 支持多种存储引擎,每个引擎有不同特性,最常用的是:
-
**InnoDB**(默认):支持事务、外键、行级锁和崩溃恢复,适合高并发和写密集型场景。
-
**MyISAM**:不支持事务和外键,读写性能高,但不适合高并发事务场景。
-
**Memory**:数据存储在内存中,查询极快,适合临时数据或缓存。
-
**Archive**:只支持 INSERT 和 SELECT,压缩率高,适合历史数据归档。
**高性能与扩展性**
-
**索引优化**:支持 B-Tree、哈希索引,优化查询效率。
-
**复制(Replication)**:主从复制、主主复制,实现读写分离和高可用性。
-
**分区(Partitioning)**:水平分割大表,提升查询性能。
**安全与权限管理**
-
**用户认证**:基于用户名、主机和密码的访问控制。
-
**细粒度权限**:支持 GRANT/REVOKE 对数据库、表、列级别的权限控制。
-
**加密功能**:支持 SSL/TLS 加密传输,以及数据静态加密(TDE)。
2、MySQL链接
安装 MySQL 后,你可以通过以下几种方式连接到 MySQL 服务端:
常用 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 \; -- 直接删除数据库,不检查是否存在
或
DROP DATABASE \[IF EXISTS\] \;
\`\`\`
\*\*参数说明:\*\*
- \`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);
\`\`\`
2. 删除列
\`\`\`
ALTER TABLE 表名
DROP COLUMN 列名;
\`\`\`
示例:
\`\`\`
ALTER TABLE users
DROP COLUMN age;
\`\`\`
3. 修改列定义
\`\`\`
ALTER TABLE 表名
MODIFY COLUMN 列名 新数据类型 \[新约束条件\];
\`\`\`
示例:
\`\`\`
-- 修改username长度并添加唯一约束
ALTER TABLE users
MODIFY COLUMN username VARCHAR(50) UNIQUE;
-- 修改列默认值
ALTER TABLE users
MODIFY COLUMN status TINYINT DEFAULT 1;
\`\`\`
4. 重命名列
\`\`\`
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:查询未删除男生信息,按学号降序
```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;
```
最大值
例2:查询女生的编号最大值
```sql
select max(id) from students where gender=2;
```
最小值
例3:查询未删除的学生最小编号
```sql
select min(id) from students where is_delete=0;
```
求和
例4:查询男生的总年龄
```sql
select sum(age) from students where gender=1;
-- 平均年龄
select sum(age)/count(*) from students where gender=1;
```
平均值
例5:查询未删除女生的编号平均值
```sql
select avg(id) from students where is_delete=0 and gender=2;
```
4. 分组
group by
-
group by的含义:将查询结果按照1个或多个字段进行分组,字段值相同的为一组
-
group by可用于单个字段分组,也可用于多个字段分组
```
gender count members
1 20 小红,小花,小紫....
0 30 大明,二明
```
group by + group_concat()
-
group_concat(字段名)可以作为一个输出字段来使用,
-
表示分组之后,根据分组结果,使用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 + 集合函数
- 通过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
-
having 条件表达式:用来分组查询后指定一些条件来输出查询结果
-
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
```
说明
例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支持三种类型的连接查询,分别为:
```
需求:查询数据库获取小红的工资和部门信息。
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:使用左连接查询班级表与学生表
```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;
```