MySQL数据库(基础)

学习SQL语句的必要性

在可视化工具中(如Navicat)许多基本的数据库操作可以通过图形用户界面(GUI)完成,而无需手动编写SQL语句。例如,你可以通过点击按钮来创建表、插入数据、查询记录等。这种方式对于不熟悉SQL的用户非常友好。 

不过,虽然可视化工具可以简化操作,了解基本的SQL语句仍然很重要,因为:

  • 灵活性:有时你可能需要执行更复杂的查询或操作,GUI可能无法满足所有需求。
  • 性能优化:编写高效的SQL语句能够提高查询性能,尤其在处理大数据集时。
  • 故障排除:当遇到问题时,查看SQL语句可以帮助你更好地理解发生了什么。

1. MySQL数据库基本特点

1.1 表格结构

  • 是数据库的基本结构,所有数据都以表的形式存储。表由组成。

    • 行(记录):每一行表示一条独立的数据记录。对于“学生”表而言,每一行都代表一个学生的具体信息,例如姓名、年龄等。
    • 列(字段):每一列存储数据的特定属性。例如,列可以包括姓名、学号、年龄等,每列的数据类型决定了可以存储什么类型的信息(如整数、字符串等)。

    例如,学生表的结构可以如下:

    CREATE TABLE 学生 (
        学号 INT PRIMARY KEY,
        姓名 VARCHAR(50) NOT NULL,
        年龄 INT CHECK (年龄 >= 0),
        性别 ENUM('M', 'F') NOT NULL
    );
    

    这里,学号是主键,确保每个学生的唯一性。年龄字段使用了检查约束,确保值为非负数,性别字段限制为特定值(男或女)。

1.2 数据完整性

  • 完整性约束确保数据的准确性和一致性,主要包括:

    • 主键:每个表必须有一个主键,用于唯一标识每条记录。主键不能为NULL,并且值必须唯一。例如,学生表中的学号
    • 外键:用于创建表与表之间的关系,确保引用的有效性。外键指向其他表的主键,例如在“订单”表中引用“客户”表的客户ID,确保每个订单都关联一个有效的客户。
    • 唯一性约束:确保某列的值是唯一的,防止重复数据。例如,电子邮件地址字段通常会设置为唯一,以确保没有两个用户使用相同的电子邮件。

1.3 关系性

  • 数据关系是关系型数据库的核心,允许通过外键在表之间建立关系。关系的类型主要包括:

    • 一对一:一个实体对应一个实体。例如,一个学生可能只拥有一个学号,反之亦然。
    • 一对多:一个客户可以有多个订单。这种情况下,客户ID在订单表中作为外键引用客户表的主键。
    • 多对多:学生与课程之间的关系,通常需要通过中间表实现。中间表记录学生和课程之间的关系,如学生ID课程ID

1.4 使用SQL

  • 结构化查询语言(SQL)是与关系型数据库交互的主要语言,包括多个子语言:

    • 数据定义语言(DDL):用于创建和修改数据库结构,如创建表、删除表等。常用命令有CREATEALTERDROP
    • 数据操作语言(DML):用于对数据进行操作,包括插入、更新和删除。常用命令有INSERTUPDATEDELETE
    • 数据查询语言(DQL):用于从数据库中查询数据,主要命令是SELECT,可以结合WHEREJOIN等进行复杂查询。

1.5 数据冗余和一致性

  • 数据冗余:通过合理设计数据库结构,关系型数据库可以减少数据冗余。例如,通过使用外键关联表,而不是在每个表中重复存储相同的数据,减少数据存储的冗余。
  • 数据一致性:数据库管理系统通过事务处理来确保数据的一致性。事务是一组操作,要么全部成功,要么全部失败,这样可以避免数据不一致的情况。例如,在更新账户余额时,必须同时更新交易记录,确保两个操作一致。

1.6 事务管理

  • ACID特性确保事务的可靠性:
    • 原子性(Atomicity):事务要么成功完成所有操作,要么不执行任何操作。例如,如果在转账过程中扣款成功但存款失败,则整个事务回滚。
    • 一致性(Consistency):事务开始和结束时,数据库的状态必须保持一致,遵循所有定义的约束。
    • 隔离性(Isolation):并发事务执行时,彼此之间的影响被隔离,确保一个事务的操作不会影响其他事务的结果。
    • 持久性(Durability):一旦事务提交,结果就会被保存,即使系统崩溃也不会丢失。

2. 数据库与表的管理

2.1 创建和删除数据库

  • 创建数据库

    • 使用 CREATE DATABASE 语句可以创建新的数据库。数据库是存储表和其他对象的容器。
CREATE DATABASE 数据库名;
  • 注意事项
    • 创建数据库后,可以使用USE命令切换到该数据库进行后续操作。
    • 数据库名必须唯一,且遵循命名规则(如不能包含特殊字符)。
  • 查看数据库

    • 使用 SHOW DATABASE 命令列出所有已创建的数据库。
  • 删除数据库

    • 使用 DROP DATABASE 语句删除指定数据库。此操作将永久删除数据库及其所有表和数据。
DROP DATABASE 数据库名;
  • 注意事项
    • 删除数据库时需谨慎,确保不再需要数据库中的数据。

2.2 创建和删除表

创建表的语法

CREATE TABLE 表名 (
    列名1 数据类型 [约束],
    列名2 数据类型 [约束],
    ...
);

数据类型

数据类型定义了每列可以存储的数据的类型。常见的数据类型包括:

分类MySQL 数据类型Java 数据类型特殊说明
数值类型TINYINTbyte, Byte适用于存储小范围的整数,byte 占 1 字节,范围为 -128 到 127。
SMALLINTshort, Short适用于存储中小范围整数,short 占 2 字节,范围为 -32,768 到 32,767。
MEDIUMINTint, Integer占 3 字节,适用于存储中等范围整数,范围为 -8,388,608 到 8,388,607。
INT / INTEGERint, Integer常用整数类型,占 4 字节,范围为 -2,147,483,648 到 2,147,483,647。
BIGINTlong, Long占 8 字节,适用于存储大范围整数,范围为 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807。
FLOATfloat, Float存储单精度浮动小数,占 4 字节,适用于精度要求不高的数值。
DOUBLEdouble, Double存储双精度浮动小数,占 8 字节,适用于精度要求较高的数值。
DECIMAL / NUMERICBigDecimal用于高精度存储,如财务计算。Java 中使用 BigDecimal 来避免精度丢失。
日期和时间类型DATEjava.sql.Date, java.time.LocalDate用于存储日期,不包含时间,Java 使用 LocalDateDate
DATETIMEjava.sql.Timestamp, java.time.LocalDateTime存储日期和时间,Java 使用 LocalDateTimeTimestamp
TIMESTAMPjava.sql.Timestamp, java.time.Instant记录从 1970-01-01 00:00:00 UTC 开始的时间戳,适用于时间计算。
TIMEjava.sql.Time, java.time.LocalTime用于存储时间,不包含日期,Java 使用 LocalTimeTime
YEARjava.sql.Date, java.time.LocalDate用于存储年份,通常为四位数字,例如 2025。
字符和文本类型CHAR(n)String定长字符串,n 是指定的长度,不足时会填充空格。
VARCHAR(n)String变长字符串,n 是最大字符长度,不会填充空格。
TEXTString存储较大文本数据,最大长度 65,535 字符,适合大段文本。
TINYTEXTString存储较小文本数据,最大长度 255 字符。
MEDIUMTEXTString存储中等大小文本,最大长度 16,777,215 字符。
LONGTEXTString存储非常大的文本,最大长度为 4,294,967,295 字符。
二进制类型BINARY(n)byte[]定长二进制数据,适用于存储固定长度的二进制数据。
VARBINARY(n)byte[]变长二进制数据,适用于存储变长的二进制数据。
BLOBbyte[]存储二进制大对象,通常用于存储图像、音频、视频等大文件。

约束

约束用于限制列中可以存储的数据类型,确保数据的完整性和一致性。常见的约束包括:

约束描述
PRIMARY KEY唯一标识每条记录,值必须唯一且不为空。
FOREIGN KEY定义表之间的关系,确保引用的有效性。
NOT NULL确保列的值不能为空,强制要求提供该列的值。
UNIQUE确保列中的每个值都是唯一的,不允许重复。
CHECK确保列中的值满足特定条件。
DEFAULT为列指定默认值,如果插入时未提供该列的值,则使用默认值。

完整示例

CREATE TABLE customers (
    customer_id INT AUTO_INCREMENT PRIMARY KEY,  -- 主键,唯一标识每条记录
    first_name VARCHAR(50) NOT NULL,             -- 姓名,不能为空
    last_name VARCHAR(50) NOT NULL,              -- 姓氏,不能为空
    email VARCHAR(100) UNIQUE,                    -- 电子邮件,必须唯一
    age INT CHECK (age >= 0),                     -- 年龄,必须大于或等于0
    signup_date DATE DEFAULT CURRENT_DATE,        -- 注册日期,默认值为当前日期
    status ENUM('active', 'inactive') DEFAULT 'active',  -- 状态,取值为 'active' 或 'inactive',默认值为 'active'
    country_id INT,                               -- 国家ID,用于外键约束
    FOREIGN KEY (country_id) REFERENCES countries(country_id)  -- 外键,引用国家表的主键
);

约束说明

  • 主键 (PRIMARY KEY)

    • customer_id INT AUTO_INCREMENT PRIMARY KEY
    • 该列是主键,确保每条记录的 customer_id 是唯一的,并且不能为NULL。AUTO_INCREMENT表示每次插入新记录时,该值会自动增加。
  • 非空约束 (NOT NULL)

    • first_name VARCHAR(50) NOT NULL
    • 该列存储客户的名字,不能为空,确保用户在插入数据时提供此信息。
  • 唯一约束 (UNIQUE)

    • email VARCHAR(100) UNIQUE
    • 确保每个客户的电子邮件地址是唯一的,防止重复的电子邮件。
  • 检查约束 (CHECK)

    • age INT CHECK (age >= 0)
    • 确保客户的年龄必须大于或等于0,以防止输入不合理的数据。
  • 默认值约束 (DEFAULT)

    • signup_date DATE DEFAULT CURRENT_DATE
    • 如果在插入时未指定注册日期,则自动使用当前日期作为默认值。
  • 枚举约束 (ENUM)

    • status ENUM('active', 'inactive') DEFAULT 'active'
    • 状态列只能取两个值之一('active' 或 'inactive'),默认值为 'active'。
  • 外键约束 (FOREIGN KEY)

    • FOREIGN KEY (country_id) REFERENCES countries(country_id)
    • 该列用于引用其他表(如 countries 表)的主键 country_id,确保引用的有效性,防止孤立记录。

查看表结构

使用 DESCRIBE 表名;  或    SHOW COLUMNS FROM; 表名;  命令查看表的结构。

DESCRIBE 表名;

SHOW COLUMNS FROM 表名;

 删除表

使用 DROP TABLE 表名; 语句删除指定的表。此操作将永久删除表及其所有数据。

DROP TABLE 表名;

2.3 其他表管理操作

添加列

ALTER TABLE 表名 ADD 列名 数据类型;

删除列

ALTER TABLE 表名 DROP 列名;

修改列

ALTER TABLE 表名 MODIFY 列名 新数据类型;

查看所有表

使用 SHOW TABLES 命令可以列出当前数据库中的所有表。

3. 数据操作语言(DML)

DML用于在数据库中操作数据,包括插入、查询、更新和删除记录。

3.1 数据的插入(INSERT INTO 

INSERT INTO 语句用于向表中添加新记录。可以指定插入的列,也可以省略列名,默认插入所有列。

基本语法

INSERT INTO 表名 (列1, 列2, ...) VALUES (值1, 值2, ...);

省略列名: 如果插入的值与表中的所有列顺序一致,可以省略列名。

INSERT INTO customers 
VALUES (NULL, 'Jane', 'Smith', 'jane.smith@example.com', 25, CURRENT_DATE, 'active', NULL);

批量插入: 可以一次插入多条记录。

INSERT INTO customers (first_name, last_name, email) 
VALUES ('Alice', 'Johnson', 'alice.johnson@example.com'), 
       ('Bob', 'Brown', 'bob.brown@example.com');

示例

INSERT INTO customers (first_name, last_name, email, age) 
VALUES ('John', 'Doe', 'john.doe@example.com', 30);

3.2 数据查询

SELECT 语句

SELECT语句用于从表中查询数据。可以选择特定的列,也可以选择所有列。

基本语法

SELECT 列1, 列2, ... FROM 表名;

选择所有列: 使用*表示选择所有列。

SELECT * FROM customers;

示例

SELECT first_name, last_name FROM customers;

使用 WHERE 进行条件查询

WHERE子句用于过滤结果集,根据指定条件返回满足条件的记录。

基本语法

SELECT 列1, 列2, ... FROM 表名 WHERE 条件;

多条件查询: 可以使用逻辑运算符ANDOR连接多个条件。

SELECT * FROM customers WHERE age >= 30 AND status = 'active';

示例

SELECT * FROM customers WHERE age > 25;

3.3 数据更新与删除

UPDATE 的使用

UPDATE语句用于修改表中已有的记录。使用SET指定要修改的列及其新值。

基本语法

UPDATE 表名 SET 列1 = 新值1, 列2 = 新值2 WHERE 条件;

不带 WHERE 的更新: 如果省略WHERE子句,则所有记录都会被更新,这通常是不建议的操作。

UPDATE customers SET status = 'inactive';

示例

UPDATE customers SET age = 31 WHERE first_name = 'John' AND last_name = 'Doe';

DELETE 的使用

DELETE语句用于从表中删除记录。也可以使用WHERE子句来指定删除的条件。

基本语法

DELETE FROM 表名 WHERE 条件;

不带 WHERE 的删除: 如果省略WHERE子句,则会删除表中的所有记录。

DELETE FROM customers;

示例

DELETE FROM customers WHERE customer_id = 1;

3.4 条件判断语句 

CASE 语句

CASE 语句允许在查询中进行条件判断,根据不同条件返回不同的结果。

示例

SELECT first_name,
       CASE 
           WHEN age < 18 THEN '未成年'
           WHEN age BETWEEN 18 AND 65 THEN '成年'
           ELSE '老年'
       END AS age_group
FROM customers;

IF 语句

在存储过程或函数中,可以使用 IF 语句进行条件判断。

示例

IF (条件) THEN
    -- 执行某些操作
ELSE
    -- 执行其他操作
END IF;

WHERE 子句

在查询中,WHERE 子句用于筛选符合特定条件的记录。

示例

SELECT * FROM orders WHERE order_status = '已完成';

4. 查询进阶

查询进阶主要涉及连接(JOIN)操作和子查询。这些技术使得从多个表中获取数据变得更加灵活和高效。

字符串连接操作

通过 字段1||字段2||字段3(假设这三个字段都为字符串类型)可以将这三个字段合为一个字符串字段,一般用在SELECT语句之后。

4.1 连接(JOIN)操作

  • 连接查询的本质其实是是查询到连接的表中相关联的记录,可能一个表中的记录关联到另一个表中的多条记录,所以这个时候查询到的就是多条记录。
  • 连接查询COUNT(*) 统计的是连接结果中的记录数,即符合连接条件的总记录数。
  • 单表查询COUNT(*) 统计的是整个表的总记录数。

  • 当联接多个表时,得这三个表中各自记录的字段相互关联上,才会将这条记录筛选出来。
  • 对于连接查询操作,可以在最后使用WHERE将筛选完的记录再进行一次筛选。

内连接(INNER JOIN)

只返回两个表中匹配的记录。适用于需要基于共同字段进行数据比较的情况。

基本语法

SELECT 列1, 列2, ... 
FROM 表1 
INNER JOIN 表2 ON 表1.列名 = 表2.列名;
  • 选择字段

    • SELECT 列1, 列2, ... 指定了要返回的字段(不一定要是表1中的字段,也可以是表一中的记录所对应表二中的字段),这些字段是基于查询结果中的记录而选择的。
    • 这一步并不涉及与表2的比较,而是决定最终结果中要展示哪些表1的字段。
  • 连接条件

    • ON 表1.列名 = 表2.列名 定义了如何比较表1和表2中的记录。
    • 只有当表1和表2中对应字段的值相等时,才会将这些匹配的记录包括在最终结果中。
  • 结果展示

    • 最终展示的内容由 SELECT 指定的字段决定,展示的是符合连接条件的表1中的记录及其相关字段。

示例

SELECT customers.first_name, orders.order_id 
FROM customers 
INNER JOIN orders ON customers.customer_id = orders.customer_id;

这里会首先去将表customers中的每一条记录的customer_id字段与表orders中的每一条记录的customer_id字段去比较,当两个表中的某两个记录的这两个字段相等了之后,就会将表customers的first_name字段与表orders的order_id字段记录下来,并将这一条记录的这两个字段显示在一行之中。

外连接(OUTER JOIN)

返回两个表中匹配的记录及不匹配的记录。外联接分为左外联接、右外联接和全外联接。

左外连接(LEFT JOIN)

返回左表的所有记录以及右表中匹配的记录。如果右表没有匹配,则返回NULL。

SELECT customers.first_name, orders.order_id 
FROM customers 
LEFT JOIN orders ON customers.customer_id = orders.customer_id;

这种外连接跟上面内连接的唯一区别就是:

内连接所返回的字段是只有二者匹配上的记录的相应字段才会返回,而外连接则不管有没有匹配上,就比如说左外连接,左边的表customers的所有记录都会返回,只不过有些记录不存在所匹配的orders.order_id,会显示NULL。 

first_nameorder_id
John101
Jane103
AliceNULL

 加入最后返回了以上的结果,就证明以上三条记录都在表customers之中,但是记录一和二中的相应字段由表orders中的相应字段与之匹配,找到了匹配,但是记录三Alice的customer_id字段没有在表orders中找到匹配上的customer_id,故也就没有对应的表orders中的order_id字段,所以最后显示NULL

右外连接(RIGHT JOIN)

返回右表的所有记录以及左表中匹配的记录。如果左表没有匹配,则返回NULL。

SELECT customers.first_name, orders.order_id 
FROM customers 
RIGHT JOIN orders ON customers.customer_id = orders.customer_id;

全外连接(FULL JOIN)

返回两个表中的所有记录,包括不匹配的记录。如果一边没有匹配,返回NULL。

MySQL不直接支持FULL JOIN,可以通过UNION实现。

SELECT customers.first_name, orders.order_id 
FROM customers 
LEFT JOIN orders ON customers.customer_id = orders.customer_id
UNION
SELECT customers.first_name, orders.order_id 
FROM customers 
RIGHT JOIN orders ON customers.customer_id = orders.customer_id;

4.2 子查询

子查询是指在一个查询中嵌套另一个查询。可以用在SELECT、INSERT、UPDATE和DELETE语句中。

基本语法

SELECT 列1, 列2 
FROM 表名 
WHERE 列名 = (SELECT 列名 FROM 另一表 WHERE 条件);

示例

假设我们有两个表,customersorders,我们想查找下过订单的客户的名字。

SELECT first_name, last_name 
FROM customers 
WHERE customer_id IN (SELECT customer_id FROM orders);

 这个查询会选择所有在 customers 表中 customer_id 存在于 orders 表中的客户。(会在表orders中去检查每一条记录的customer_id,然后去检查这些customer_id是否在表customers的某一条记录的customer_id字段中出现过,一旦出现过,就锁定表customers中的这些记录,然后把这些记录的first_name字段、last_name字段在一行中显示。

使用子查询的更新: 例如,更新所有下过订单的客户的状态为“active”。

UPDATE customers 
SET status = 'active' 
WHERE customer_id IN (SELECT customer_id FROM orders);

使用子查询的删除: 删除没有下过订单的客户。

DELETE FROM customers 
WHERE customer_id NOT IN (SELECT customer_id FROM orders);

5. 事务管理

5.1 事务的基本概念

  • 事务:一个事务是一个逻辑操作单元,由一组 SQL 语句组成,这些语句要么全部执行成功,要么全部不执行。事务通常用于确保数据库操作的完整性和一致性。
  • 特点:事务在处理过程中涉及多个操作,可能包括插入、更新或删除等。当这些操作要么成功完成,要么在遇到错误时完全回滚。

5.2 ACID特性

ACID 是确保数据库事务可靠性的重要特性,包含以下四个方面:

  • 原子性 (Atomicity)

    • 事务中的所有操作要么全部完成,要么全部不执行。即使出现错误,系统也会确保事务不部分完成。
  • 一致性 (Consistency)

    • 事务的执行必须使数据库从一个一致的状态变更为另一个一致的状态。任何事务在完成后,都必须满足所有数据约束和规则。
  • 隔离性 (Isolation)

    • 事务的执行是相互独立的,一个事务的执行不应受到其他事务的影响。即使多个事务并发执行,它们的结果也应是合理的。
  • 持久性 (Durability)

    • 一旦事务被提交,其结果是永久的,即使系统崩溃,也不会丢失。数据库会确保已提交的数据被保留。

5.3 使用事务

在 MySQL 中,事务可以通过以下 SQL 命令管理:

  • BEGIN:用于开始一个新事务。
  • COMMIT:用于提交当前事务,使所有变更生效。
  • ROLLBACK:用于撤销当前事务,回滚到事务开始前的状态。

5.3.1 BEGIN

开始一个新的事务,可以通过 START TRANSACTIONBEGIN 语句。

START TRANSACTION;

5.3.2 COMMIT

提交事务,将所有在该事务中执行的操作保存到数据库中。

COMMIT;

5.3.3 ROLLBACK

撤销事务,将数据库状态回滚到事务开始前的状态。

ROLLBACK;

例子

下面是一个简单的事务管理示例:

START TRANSACTION;

INSERT INTO accounts (account_id, balance) VALUES (1, 1000);
UPDATE accounts SET balance = balance - 500 WHERE account_id = 1;

-- 假设这里有一个条件判断
IF (某个条件) THEN
    COMMIT;  -- 提交事务
ELSE
    ROLLBACK;  -- 撤销事务
END IF;

6. 性能优化与索引

6.1 索引的基本概念

  • 索引是一个数据结构,它允许数据库快速查找和访问表中的数据。就像书籍的目录,索引能快速定位信息的位置,减少数据检索的时间。
  • 通常,索引会在特定列上创建,以加速基于这些列的查询。
  • 使用索引可以显著提高查询效率,尤其是在大数据集上。没有索引的情况下,数据库可能需要扫描整个表以找到匹配的记录,这会消耗大量时间。

例子 

假设 customers 表的 last_name 列包含如下数据:

customer_idlast_name
1Smith
2Johnson
3Smith
4Williams

创建索引后,索引可能看起来像这样:

last_namepointer
Johnsonrow 2
Smithrow 1, row 3
Williamsrow 4

第二个表格就是为第一个表创建的索引,当你需要检索last_name字段为Smith的记录时,就可以通过索引帮你快速定位到 row1和row3。

6.2 索引的优势 

6.2.1 数据结构优化

  • 高效的数据结构:索引通常使用如 B 树或哈希表等高效的数据结构。这些结构允许数据库在对数时间内查找元素,而不是线性时间。例如,使用 B 树时,查找时间复杂度为 O(log n),而全表扫描的复杂度为 O(n)。

6.2.2 直接定位

  • 直接访问记录:当你查询某个唯一值时,索引可以直接定位到该值在表中的位置,而不需要检查每一行。例如:
SELECT * FROM customers WHERE customer_id = 123;
  • 如果 customer_id 列有索引,数据库会直接根据索引找到 customer_id = 123 的位置,而不需要遍历整张表。 

6.2.3 减少 I/O 操作

  • 减少磁盘 I/O:索引能够减少从磁盘读取的数据量。对于大表,减少读取的行数和字节数可以显著提高性能。即使数据的值是唯一的,读取索引中的信息要比读取整个表要少得多。

6.2.4 更好的支持范围查询

  • 范围查询:索引还可以优化范围查询。假设有一个唯一的索引在 customer_id 上,当执行类似于:
SELECT * FROM customers WHERE customer_id BETWEEN 100 AND 200;
  • 数据库可以迅速定位到范围的开始和结束,而不是逐行扫描。

6.2.5 排序和连接

  • 排序优化:索引可以帮助数据库在排序时更快地定位数据。例如,如果你在某列上有索引,执行的排序操作将变得更快。
  • 连接操作:在执行连接查询时,索引也能大幅提高效率,因为数据库能够快速找到连接条件所需的行。

 总结来说,索引是凭借着其数据结构(通常是 B 树或哈希表)的优势,能够快速查询到所需的记录。(并不是因为单独建立了个表格就能够快速查询,关键还是因为独特的数据结构。

6.3 创建和使用索引 

创建索引

单列索引:适用于只查询单一列的场景。

通过 SQL 语句在表的一个或多个列上创建索引,语法如下:

CREATE INDEX index_name ON table_name (column1, column2, ...);

复合索引:适用于对多列的查询 

这个复合索引将在 last_nameage 列上创建,以支持同时基于这两列的查询。 

CREATE INDEX idx_name_age ON customers (last_name, age);

你不需要知道这个索引的结构,你只需要知道它能够帮助你自动提升查询效率就可以了。 

示例

CREATE INDEX idx_customer_name ON customers (last_name);
  • 这行代码在 customers 表的 last_name 列上创建了一个名为 idx_customer_name 的索引。
  • 当执行基于 last_name 列的查询时,数据库将使用这个索引来加速检索。

使用索引

创建索引后,数据库查询引擎会自动使用它来优化查询。示例:

SELECT * FROM customers WHERE last_name = 'Smith';
  • 在执行此查询时,如果 last_name 列上存在索引,数据库将首先查找索引,而不是全表扫描。这将大大提高查询速度。

注意事项

  • 更新成本:每次数据插入、更新或删除时,索引也需更新,过多的索引会影响写入性能,因此应谨慎创建。
  • 选择性:索引的选择性越高,即列中不同值的比例越高,索引的效果越好。例如,性别列的选择性较低(只有“男”和“女”两个值),而电子邮件列的选择性较高(每个值几乎都是唯一的)。

6.4 使用 EXPLAIN 了解查询性能

EXPLAIN 语句:在查询前加上 EXPLAIN 可以帮助分析数据库如何执行该查询,包括索引的使用情况、行数估算等信息。

示例

EXPLAIN SELECT * FROM customers WHERE last_name = 'Smith';

输出解读

列名描述
id查询的标识符,用于区分多个查询。
select_type查询的类型:
- SIMPLE:简单查询,不包含子查询或联合。
- PRIMARY:主要查询。
- UNION:联合查询。
table正在访问的表名。
type连接类型,表示访问表的方式:
- ALL:全表扫描,性能较差。
- index:使用索引扫描,性能较好。
- ref:使用非唯一索引查找,性能较好。
- eq_ref:使用唯一索引查找,性能最佳。
possible_keys可能使用的索引列表。
key实际使用的索引。
rows预估需要扫描的行数,数字越小,查询性能通常越好。

 就是系统会帮你去模拟这一次的查询,并给你返回关于这次模拟查询的各种信息,返回格式大致如下:

idselect_typetabletypepossible_keyskeyrows
1SIMPLEcustomersrefidx_last_nameidx_last_name5

7. 数据备份与恢复

7.1 使用 mysqldump 备份数据

mysqldump 工具是 MySQL 提供的一个命令行工具,用于备份数据库。它将数据库中的数据导出为 SQL 脚本文件,该文件包含创建数据库和插入数据的 SQL 语句。

备份命令示例

mysqldump -u 用户名 -p 数据库名 > 备份文件.sql
  • -u 用户名:指定连接数据库的用户名。
  • -p:提示输入密码。
  • 数据库名:要备份的数据库的名称。
  • 备份文件.sql:导出数据的文件名。

备份所有数据库

mysqldump -u 用户名 -p --all-databases > all_databases_backup.sql

7.2 从备份中恢复数据

要恢复数据,通常使用 MySQL 的命令行工具将备份文件中的 SQL 脚本导入到数据库中。

恢复命令示例

mysql -u 用户名 -p 数据库名 < 备份文件.sql
  • 数据库名:要恢复数据的目标数据库。
  • 备份文件.sql:包含备份数据的文件。

恢复所有数据库

如果备份了所有数据库,可以使用:

mysql -u 用户名 -p < all_databases_backup.sql

重要注意事项

  • 备份频率:根据业务需求定期备份,以防数据丢失。
  • 备份文件安全:确保备份文件存储在安全的位置,防止未经授权访问。
  • 测试恢复:定期测试备份恢复过程,确保在需要时能成功恢复数据。

8. 用户权限管理

8.1 创建用户

CREATE USER 'username'@'host' IDENTIFIED BY 'password';
  • 固定格式

    • CREATE USER:关键字,用于创建新用户。
    • IDENTIFIED BY:关键字,用于指定用户的密码。
  • 可更改字段

    • 'username':表示要创建的用户名,例如 'john_doe'
    • 'host':表示用户可以从哪个主机连接。常见的值有:
      • 'localhost':仅允许从本地连接。
      • '%':允许从任何主机连接。
    • 'password':表示用户的密码,例如 'securePassword123'

示例

CREATE USER 'john_doe'@'localhost' IDENTIFIED BY 'securePassword123';

8.2 删除用户

DROP USER 'username'@'host';
  • 固定格式

    • DROP USER:关键字,用于删除用户。
    • 'username'@'host':表示要删除的用户名及其连接主机。
  • 可更改字段

    • 'username':表示要删除的用户名。
    • 'host':表示要删除的用户可以从哪个主机连接。

 8.3 查看所有用户

SELECT User, Host FROM mysql.user;

 8.4 修改用户密码

SET PASSWORD FOR 'username'@'host' = PASSWORD('new_password');
  • 固定格式

    • SET PASSWORD FOR:关键字,用于修改用户密码。
    • PASSWORD:关键字,表示后面的内容是用户的新密码。
  • 可更改字段

    • 'username':表示要修改密码的用户名。
    • 'host':表示要修改密码的用户可以从哪个主机连接。
    • 'new_password':表示用户的新密码。

示例

SET PASSWORD FOR 'john_doe'@'localhost' = PASSWORD('newSecurePassword456');

8.5 授予权限

GRANT ALL PRIVILEGES ON database_name.* TO 'username'@'host';
  • 固定格式

    • GRANT:关键字,用于授予权限。
    • ON:关键字,指明权限的适用范围。
    • TO:关键字,指定授予权限的用户。
  • 可更改字段

    • ALL PRIVILEGES:可以更改为具体权限,例如:
      • SELECT:读取权限。
      • INSERT:插入权限。
      • UPDATE:更新权限。
      • DELETE:删除权限。
    • database_name:表示要授予权限的数据库名。
    • 'username':表示要授予权限的用户名。
    • 'host':表示要授予权限的用户可以从哪个主机连接。

示例

REVOKE INSERT ON my_database.* FROM 'john_doe'@'localhost';

8.6 撤销权限

REVOKE ALL PRIVILEGES ON database_name.* FROM 'username'@'host';
  • 固定格式

    • REVOKE:关键字,用于撤销权限。
    • ON:关键字,指明权限的适用范围。
    • FROM:关键字,指定撤销权限的用户。
  • 可更改字段

    • ALL PRIVILEGES:可以更改为具体权限,例如:
      • SELECTINSERTUPDATEDELETE
    • database_name:表示要撤销权限的数据库名。
    • 'username':表示要撤销权限的用户名。
    • 'host':表示要撤销权限的用户可以从哪个主机连接。

示例

REVOKE INSERT ON my_database.* FROM 'john_doe'@'localhost';

8.7 显示用户权限

SHOW GRANTS FOR 'username'@'host';
  • 固定格式

    • SHOW GRANTS:关键字,用于显示用户权限。
    • FOR:关键字,指定要查看权限的用户。
  • 可更改字段

    • 'username':表示要查看权限的用户名。
    • 'host':表示要查看权限的用户可以从哪个主机连接。

示例

SHOW GRANTS FOR 'john_doe'@'localhost';

8.8 刷新权限

FLUSH PRIVILEGES;
  • 固定格式
    • FLUSH PRIVILEGES:关键字,用于刷新权限,使更改生效。

9. 视图

9.1 视图的定义

视图可以看作是一个“窗口”,通过这个窗口,你可以查看数据库中数据的某种特定视图。它并不是存储实际的数据,而是存储一个查询的定义。当你通过视图查询数据时,数据库会根据这个定义自动生成结果。

视图的特点

  1. 虚拟表

    • 视图并不存储数据,只是保存了一段 SQL 查询。当你查询视图时,数据库实时运行这个查询来获取数据。
  2. 简化查询

    • 你可以把复杂的 SQL 查询封装成一个视图。这样,你只需要通过视图名称来获取结果,不必每次都写复杂的查询语句。
  3. 增强安全性

    • 通过视图,你可以限制用户对某些敏感数据的访问。只让他们看到视图中定义的内容,而不直接访问基础表。
  4. 便于维护

    • 如果基础表的结构发生变化,只要视图的查询逻辑依然有效,就不需要修改使用这个视图的地方。

使用场景

  • 汇总数据:比如,你想查看每个产品的总销售额,可以创建一个视图来展示这些信息,而不必每次都写聚合查询。

  • 多表联合:如果你需要从多个表中获取数据,可以把这个联合查询封装在视图中,方便后续使用。

  • 限制数据访问:你可以为不同的用户角色创建不同的视图,确保他们只能看到自己需要的数据

视图的存在就像将一系列复杂的查询条件封装成一个函数。下次你需要使用这个查询逻辑时,只需调用这个视图,而无需再写一大堆语句,便能获得相同的查询结果。

9.2 创建视图

创建视图的语法

CREATE VIEW 视图名 AS
SELECT 列1, 列2, ...
FROM 表名
WHERE 条件;
  • 固定格式

    • CREATE VIEW:关键字,用于创建视图。
    • AS:关键字,表示后面是视图的定义。
  • 可更改字段

    • 视图名:表示视图的名称,例如 customer_orders
    • 列1, 列2, ...:表示需要从表中选择的列。
    • 表名:表示从哪个表中选择数据。
    • 条件:表示过滤数据的条件(可选)。

示例

CREATE VIEW customer_orders AS
SELECT customers.first_name, orders.order_id
FROM customers
INNER JOIN orders ON customers.customer_id = orders.customer_id
WHERE orders.order_date > '2024-01-01';

此示例创建一个名为 customer_orders 的视图,显示2024年之后所有客户及其订单信息。

9.3 查询视图

创建视图后,可以像查询普通表一样查询视图:

SELECT * FROM 视图名;

示例

SELECT * FROM customer_orders;

此示例查询 customer_orders 视图中的所有数据。

9.3 修改视图

如果需要修改视图,可以使用 CREATE OR REPLACE VIEW

CREATE OR REPLACE VIEW 视图名 AS
SELECT 列1, 列2, ...
FROM 表名
WHERE 新的条件;

示例

CREATE OR REPLACE VIEW customer_orders AS
SELECT customers.first_name, orders.order_id, orders.order_date
FROM customers
INNER JOIN orders ON customers.customer_id = orders.customer_id
WHERE orders.order_date > '2024-01-01';

此示例修改 customer_orders 视图,新增了订单日期。

9.4 删除视图

如果不再需要视图,可以使用 DROP VIEW 删除:

DROP VIEW 视图名;

示例

DROP VIEW customer_orders;

此示例删除 customer_orders 视图。

10.存储过程

定义

存储过程是一个存储在数据库中的SQL语句集合,可以封装复杂的业务逻辑并通过调用来执行。存储过程使得代码更加模块化,易于重用和维护。

存储过程和视图类似,都是对SQL语句进行封装然后调用,区别是视图只对查询的SQL语句进行封装,而存储过程可以封装所有类型的SQL语句。 

10.1 存储过程的特点

  • 预编译

    • 存储过程在创建时进行编译,后续调用时直接执行,无需再次编译,从而提高执行效率。
  • 参数化

    • 可以接收输入参数(IN)、输出参数(OUT)和输入输出参数(INOUT),使其更加灵活。
  • 封装业务逻辑

    • 可以将复杂的操作和逻辑封装在存储过程中,简化调用。
  • 安全性

    • 用户可以被授予执行存储过程的权限,而不必直接访问底层表,增强了数据的安全性。
  • 事务控制

    • 存储过程可以包含事务处理,确保数据一致性。

10.2 创建存储过程

创建语法

使用 CREATE PROCEDURE 语句创建存储过程。基本语法如下:

DELIMITER //
CREATE PROCEDURE procedure_name ([parameter_list])
BEGIN
    -- SQL statements
END //
DELIMITER ;
  • procedure_name:存储过程的名称。
  • parameter_list:参数列表,可以包含多个参数,使用 INOUTINOUT 指定参数类型。
  • BEGIN ... END:包裹存储过程的逻辑。
示例

以下是一个简单的存储过程示例,用于根据客户ID查询订单:

DELIMITER //
CREATE PROCEDURE GetCustomerOrders(IN customerId INT)
BEGIN
    SELECT * FROM orders WHERE customer_id = customerId;
END //
DELIMITER ;
  • 该存储过程名为 GetCustomerOrders,接收一个输入参数 customerId

10.3 调用存储过程

使用 CALL 语句调用存储过程,语法如下:

CALL procedure_name([parameter_values]);
示例

调用上述存储过程查询客户ID为1的订单:

CALL GetCustomerOrders(1);

10.4 更新存储过程

如果需要修改存储过程,可以使用 DROP 删除原有存储过程,然后重新创建。例如:

DROP PROCEDURE IF EXISTS GetCustomerOrders;

DELIMITER //
CREATE PROCEDURE GetCustomerOrders(IN customerId INT)
BEGIN
    SELECT * FROM orders WHERE customer_id = customerId;
END //
DELIMITER ;

10.5 使用输出参数

存储过程也可以使用输出参数。以下是一个示例:

DELIMITER //
CREATE PROCEDURE GetOrderCount(IN customerId INT, OUT orderCount INT)
BEGIN
    SELECT COUNT(*) INTO orderCount FROM orders WHERE customer_id = customerId;
END //
DELIMITER ;

调用时:

CALL GetOrderCount(1, @count);
SELECT @count;
  • @count 是一个用户定义的会话变量,MySQL 允许使用以 @ 开头的变量,这些变量在整个会话中有效。
  • SELECT COUNT(*):这是一个查询,用于计算满足条件的记录数量。
  • INTO orderCount:将计算的结果(在这里是记录的数量)存储到变量 orderCount 中。INTO 关键字常用于存储过程和函数中,以便将查询结果直接赋值给变量。这种方法避免了使用临时表或额外的查询步骤,简化了数据处理流程。
  • 在调用时传入的参数@count,在原来的存储过程中代表了形参orderCount,然后INTO orderCount又把值传入了orderCount,相当于就是传入了@count,所以最后SELECT @count;才会返回相应的值。

11. 触发器 

触发器(Trigger)是一种特殊的存储程序,自动在特定事件发生时执行。它们可以用于确保数据完整性、自动维护审计日志、实现复杂的业务逻辑等。

触发器的基本概念

  • 自动执行:触发器在特定事件(如插入、更新或删除操作)发生时自动执行,而无需显式调用。
  • 关联表:触发器与特定的表关联,只有在该表上执行操作时,触发器才会被触发。

触发器的类型

  1. BEFORE 触发器:在插入、更新或删除操作之前执行。适用于数据验证或修改。
  2. AFTER 触发器:在插入、更新或删除操作之后执行。适用于日志记录或更新相关表。

触发器的创建

创建触发器时,需要指定触发条件(如 BEFORE INSERTAFTER DELETE)、触发器名称、关联的表以及触发时执行的操作。

示例

CREATE TRIGGER before_insert_customers
BEFORE INSERT ON customers
FOR EACH ROW
BEGIN
    SET NEW.created_at = NOW();  -- 设置当前时间为创建时间
END;

在这个示例中,创建了一个名为 before_insert_customers 的触发器,在每次向 customers 表插入新记录之前,会自动设置 created_at 字段为当前时间。

触发器的使用场景

  1. 数据验证:在插入或更新数据之前进行检查,确保数据符合一定的标准。
  2. 自动生成值:自动设置某些字段的值,如创建时间或更新时间。
  3. 审计日志:记录数据变更历史,例如在某个表中插入记录时,同时在审计表中添加一条记录。
  4. 复杂的业务逻辑:实现一些复杂的业务规则,例如自动更新相关表的数据。

注意事项

  • 性能影响:触发器会增加额外的处理时间,特别是在涉及大量数据操作时。
  • 调试困难:调试触发器比调试普通的 SQL 查询更复杂,因为触发器在背景中执行。
  • 递归调用:要小心避免触发器之间的递归调用,这可能导致无限循环。
--------语法 --建立视图 --if exists(select * from sysobjects where name='视图名') -- drop view 视图名 --go --create view 视图名 --as --select 字段名 from 表名 [条件] --go --主外健约束语句没有执行 use T90ERP go --***********人力资源 --部门表:Depet if exists(select * from sysobjects where name='Depet') drop table Depet go create table Depet ( dept_id Int primary key identity(1,1) not null, --部门编号 主键,自增 dept_name Varchar(20) not null --部门名称 ) ----约束 --alter table Depet add constraint UQ_dept_name unique (dept_name) go --职位表:Post if exists(select * from sysobjects where name='Post') drop table Post go create table Post ( Post_id Int primary key identity(1,1) not null, --职位编号 主键 自增 Post_name Varchar(50) not null, --职位名称 唯一 Post_money Money not null, --职位工资 Dept_id int not null --部门编号 外 Int 级联删除 ) ----约束 --alter table post add constraint UQ_post_name unique (post_name) alter table post add constraint FK_post_deptId foreign key(post_deptId) references depet(dept_id) go --员工信息表:Employee if exists(select * from sysobjects where name='Employee') drop table Employee go create table Employee ( Emp_id Int primary key identity(1,1) not null, --员工信息编号 主键,自增 Emp_number Varchar(50) not null, --员工工号 唯一 Emp_postId Int not null, --职位编号 外键 级联删除 Emp_hire Datetime not null, --录用时间 Emp_state Bit not null, --状态 默认1 (1在职/0离职) ) ----约束 --alter table Employee add constraint UQ_emp_number unique (emp_number) alter table Employee add constraint FK_emp_postId foreign key (emp_postId) references post(post_id) --alter table Employee add constraint DF_emp_state default(1) for emp_state go --简历表:Resume if exists(select * from sysobjects where name='Resume') drop table Resume go create table Resume ( Res_id Int primary key identity(1,1) not null, --职员信息ID 主键 非空自增 Int Emp_id Int not null, --职员ID 外键 Res_name Varchar(50) not null, --真实姓名 Res_englishname Varchar(50) null, --英文名 空 Res_idcard Varchar(19) not null, --身份证号 唯一索引 只有18位数字或18位数字加X Res_sex bit not null, --性别 默认1 男 只有男和女两种 Res_bornDate datetime not null, --出生年月 Res_nativeplace varchar(50) not null, --籍贯 Res_nation Varchar(50) not null, --民族 默认汉族 Res_health text null, --健康状况 空 默认健康 Res_diploma Varchar(50) not null, --学历 Res_address Varchar(50) null, --联系地址 空,默认地址不详 Res_Tel Varchar(50) not null, --电话 只能是11为数字 Res_photo image null --照片 空 ) ----约束 alter table Resume add constraint FK_res_empid foreign key (res_empid) references Employee(emp_id) --alter table Resume add constraint UQ_res_idcard unique (res_idcard) --alter table Resume add constraint CK_res_idcard check (res_idcard like '[1-9][1-9][1-9][1-9][1-9][1-9][1-9][1-9] --[1-9][1-9][1-9][1-9][1-9][1-9][1-9][1-9][1-9][1-9]' or res_idcard like '[1-9][1-9][1-9][1-9][1-9][1-9][1-9][1-9] --[1-9][1-9][1-9][1-9][1-9][1-9][1-9][1-9][1-9][1-9]X') --alter table Resume add constraint DF_res_sex default (1) for res_sex --alter table Resume add constraint CK_res_sex check(res_sex=1 or res_sex=0) --alter table Resume add constraint DF_res_nation default ('汉族') for res_nation --alter table Resume add constraint DF_res_health default ('健康') for res_health --alter table Resume add constraint DF_res_health defatult(1) for res_health --alter table Resume add constraint DF_res_address default ('地址不详') for res_address --alter table Resume add constraint CK_res_tel check(len(res_tel)=11) go --考勤类型表:CheckType if exists(select * from sysobjects where name='CheckType') drop table CheckType create table CheckType ( Checkt_id int primary key identity(1,1) not null, --考勤类型 主键 自增 Int Checkt_name varchar(50) not null --考勤名称(干什么) Varchar(50) ) go --考勤表:Check if exists(select * from sysobjects where name='CheckInfo') drop table CheckInfo create table CheckInfo ( Check_id int primary key identity(1,1) not null, --考勤id 主键 自增 Int Emp_id int not null, --员工id 外键 Int Check_hire datetime not null, --考勤开始时间 开始时间必须 Datetime Check_end datetime not null, --考勤结束时间 要在结束时间之前 Datatime Checkt_id int not null, --考勤类型 外键 Int Check_gtime int not null, --工休天数 Int check_time int not null --扣薪天数 Int ) ----约束 alter table CheckInfo add constraint FK_check_empId foreign key (check_empId) references Employee(emp_id) alter table CheckInfo add constraint FK_check_checktId foreign key (check_empId) references checkt(checkt_id) --alter table CheckInfo add constraint CK_check_hire check(check_hirecheck_hire) go --培训管理:Train if exists(select * from sysobjects where name='Train') drop table Train create table Train ( Train_id int primary key identity(1,1) not null, --培训编号 主键 自增 Int Train_time datetime not null, --培训日期 Datetime Train_address varchar(200) not null, --地址 Varchar(200) Train_content text not null, --内容 text Emp_id int not null, --职员编号 Int Train_teacher varchar(20) not null --讲师 Varchar(20) ) go --奖罚记录类型:PrizeAmerceType if exists(select * from sysobjects where name='PrizeAmerceType') drop table PrizeAmerceType create table PrizeAmerceType ( Prizet_id int primary key identity(1,1) not null, --奖罚记录类型id 主键 自增 Int Prizet_name varchar(50) not null, --奖罚记录名称 Varchar(50) Prizet_money money not null --奖罚金额 Money ) go --奖罚记录表:PrizeAmerceRecord if exists(select * from sysobjects where name='PrizeAmerceRecord') drop table PrizeAmerceRecord create table PrizeAmerceRecord ( Prize_id int primary key identity(1,1) not null, --奖罚记录id 主键 自增 Int Emp_id int not null, --员工id 外键 Int Prize_time datetime not null, --时间 Datetime Prizet_id int not null, --引用奖罚类型id 外键 Int Prize_desc text null, --描述 空,默认没有描述 text ) ----约束 --alter table PrizeAmerceRecord add constraint FK_prize_empid foreign key(prize_empId) references Employee(emp_id) --alter table PrizeAmerceRecord add constraint FK_prize_prizetid foreign key(prize_prizetId) references PrizeAmerceType(prizet_id) alter table PrizeAmerceRecord add constraint DF_prize_desc default('没有描述') for prize_desc go --档案:Record if exists(select * from sysobjects where name='Record') drop table Record create table Record ( Re_id int primary key identity(1,1) not null, --档案id 主键 自增 Int Re_code varchar(50) not null, --档案代码 日期+随即数生成 Varchar(50) Emp_id int not null, --员工id 外键 Int Prize_id int not null --奖罚记录id 外键 Int ) ----约束 --alter table Record add constraint FK_re_empId foreign key (re_empId) references Employee(emp_id) go --薪资表:SalaryInfo if exists(select * from sysobjects where name='SalaryInfo') drop table SalaryInfo create table SalaryInfo ( Sal_id int primary key identity(1,1) not null, --薪水表ID 主键 自增 Int Emp_id int not null, --职员ID 外键 Int Sal_bonus money not null, --奖金 Money Sal_deduct numeric(18,2) not null, --扣除 Numerica(18,2) Sal_tax money not null, --扣税 Money 默认为0 Sal_sum money not null, --总薪水 Money Sal_date smalldatetime not null --发放日期 smalldatetime ) ----约束 --alter table SalaryInfo add constraint FK_sal_empid foreign key (sal_empId) references Employee(emp_id) go --***********采购管理 --供应商级别:LevelInfo if exists(select * from sysobjects where name='LevelInfo') drop table LevelInfo create table LevelInfo ( Level_id int primary key identity(1,1) not null, --级别编号 主 自增 Int Level_name varchar(10) not null --级别名称 Varchar(10) ) go --供应商:Victualer if exists(select * from sysobjects where name='Victualer') drop table Victualer create table Victualer ( Victu_id int primary key identity(1,1) not null, --供应商编号 主 自增 Int Victu_name varchar(100) not null, --名称 Varchar(100) Level_id int not null, --级别编号 外,LevelInfo表 Int Victu_people varchar(20) not null, --联系人 Varchar(20) Victu_telephone varchar(11) not null, --联系电话 Varvhar(11),必须是11位 Victu_email varchar(50) null, --邮件 空,必须符合邮件格式 Varchar(50) Victu_address text not null, --联系地址 Text 默认地址不详 Victu_remark text null --备注 空,默认没有备注 Text ) ----约束 --alter table Victualer add constraint FK_Victu_levelId foreign key(Victu_levelId) references LevelInfo(Level_id) alter table Victualer add constraint CK_Victu_telephone check(len(victu_telephone)=11) alter table Victualer add constraint CK_Victu_email check(victu_email like '%@%.%') alter table Victualer add constraint DF_Victu_remark default ('没有描述') for victu_remark alter table Victualer add constraint DF_Victu_address default ('地址不详') for victu_address go --商品类别:Sort if exists(select * from sysobjects where name='Sort') drop table Sort create table Sort ( Sort_id int primary key identity(1,1) not null, --类别编号 主 自增 Int Sort_name varchar(50) not null --类别名称 Varchar(50) ) go --商品规格表:Spec if exists(select * from sysobjects where name='Spec') drop table Spec create table Spec ( Spec_id int primary key identity(1,1) not null, --规格编号 主 自增 Int Spec_name varchar(50) not null --规格名称 Varchar(50) ) go --商品表:Product if exists(select * from sysobjects where name='Product') drop table Product create table Product ( Pro_id int primary key identity(1,1) not null, --商品编号 主 自增 Int Pro_code varchar(20) not null, --商品代码 按日期+随机数生成,唯一 Varchar(20) Pro_name varchar(50) not null, --商品名称 Varchar(50) Sort_id int not null, --类别编号 外,Sort表 Int Spec_id int not null, --规格编号 外,Spec表 Int Pro_count int not null, --数量 Int Pro_inPrice money not null, --进货价 Money Pro_outPrice money not null, --销售价 Money Victu_id int not null, --供应商编号 外,Victualer表 Int 级联删除 Pro_remark text null --备注 空,默认没有备注 Text ) ----约束 go --询价单:AskPrice if exists(select * from sysobjects where name='AskPrice') drop table AskPrice create table AskPrice ( Ask_id int primary key identity(1,1) not null, --询价单编号 主 自增 Int Victu_id int not null, --供应商编号 外,Victualer表 Int Pro_id int not null, --商品编号 外,Product表 Int ask_price money not null, --报价 Money Ask_time datetime not null --添加时间 Datetime ) ----约束 go --采购单: BuyBill if exists(select * from sysobjects where name='BuyBill') drop table BuyBill create table BuyBill ( Buybill_id int primary key identity(1,1) not null, --采购单编号 主 自增 Int Buybill_num varchar(20) not null, --采购单据号 按日期+随机数生成,唯一 varchar(20) Emp_id int not null, --采购员编号 外,职员表 Int Buybill_time datetime not null, --采购时间 采购时间必须在交货时间之前 Datetime Buybill_delitime datetime not null, --交货时间 Datetime Buybill_remark text not null, --合同备注 Text Buybill_Isexam bit not null --库管是否审批 bit ) ----约束 go --采购明细表: BuyList if exists(select * from sysobjects where name='BuyList') drop table BuyList create table BuyList ( Buylist_id int primary key identity(1,1) not null, --采购明细编号 主 自增 Int Buybill_id int not null, --采购单编号 外,Buybill表 Int Pro_id int not null, --商品编号 外,Prduct表 Int Buylist_Count int not null, --采购数量 Int Buylist_price money not null, --采购价 Money Victu_id int not null, --供应商编号 外,Vitcualer表 Int Dsub_id int not null --采购单商品仓库编号 外,DepotSubarea表 Int ) ----约束 go --采购付款单:PayBill if exists(select * from sysobjects where name='PayBill') drop table PayBill create table PayBill ( Pay_id int primary key identity(1,1) not null, --付款单编号 主 自增 Int Buybill_id int not null, --采购单编号 外,Buybill表 Int Pay_oncoming money not null, --此次付款 如果应付款分为几次付 Money Pay_deal money not null, --应付款 则应付款应该要保持一致 Money Emp_id int not null, --财务部审批人编号 外,职员表 Int Pay_Isexam bit not null, --财务部是否审批 bit Pay_remark text null --备注 空,默认没有备注 text ) ----约束 go --采购退货单:MoveBill if exists(select * from sysobjects where name='MoveBill') drop table MoveBill create table MoveBill ( Move_id int primary key identity(1,1) not null, --退货单编号 主 自增 Int Buybill_id int not null, --采购单编号 外,Buybill表 Int Move_time datetime not null, --退单日期 退单日期必须是在采购日期之后 Datetime Dsub_id int not null, --库管审批人编号 外, Int Move_Isexam bit not null, --库管是否审批 Bit Move_remark text null --备注 空,默认没有备注 Text ) ----约束 go --***********仓库管理 --库区表:DepotSubarea if exists(select * from sysobjects where name='DepotSubarea') drop table DepotSubarea create table DepotSubarea ( Dsub_id int primary key identity(1,1) not null, --库区id 主键 自增 Int Dsub_name varchar(10) not null,--库区名称 Varchar(10) Dsub_type varchar(10) not null--仓库类别 Varchar(10) ) go --移动类型表:Transfer if exists(select * from sysobjects where name='Transfer') drop table Transfer create table Transfer ( Tran_id int primary key identity(1,1) not null, --移动类型id 主键 自增 Int Tran_name varchar(20) not null --移动类型名称 Varchar(20) ) go --入库明细表:PutInfo if exists(select * from sysobjects where name='PutInfo') drop table PutInfo create table PutInfo ( Put_id Int primary key identity(1,1) not null, --入库明细id 主键 自增 Put_code Varchar(20) not null, --入库单代码 日期+随即数生成 Buybill_id Int not null, --采购单编号 外键 Put_time Datetime not null, --入库时间 Put_people varchar(20) not null, --入库人 Dsub_id Int not null, --库区 外键 级联删除 Tran_id Int not null --移动类型 外键 ) ----约束 go --库存表:Stock if exists(select * from sysobjects where name='Stock') drop table Stock create table Stock ( Stock_id Int primary key identity(1,1) not null, --库存编号 主键 自增 Dsub_id Int not null,            --库区id 外键 Pro_id Int not null,              --商品id 外键 Stock_number Int not null             --商品数量 ) ----约束 go --出库明细表:OutInfo if exists(select * from sysobjects where name='OutInfo') drop table OutInfo create table OutInfo ( Out_id Int primary key identity(1,1) not null, --出库明细id 主键 自增 Out_code Varchar(20) not null, --出库单据号 唯一 Out_time Datetime not null, --出库时间 Out_llr Varchar(20) not null, --领料人 Out_flr Varchar(20) not null, --发料人 Out_tranId Int not null, --移动类型 Out_dsubId Int not null --库区 ) ----约束 go --补仓管理:RepairDepot if exists(select * from sysobjects where name='RepairDepot') drop table RepairDepot create table RepairDepot ( Repa_id Int primary key identity(1,1) not null, --补仓id 主键 自增 Pro_id Int not null, --商品id 外键 Repa_number Int not null, --补仓数量 Repa_dsubId Int not null, --库区表 外键 Repa_remark text null --备注 空,默认没有备注 ) ----约束 go --***********销售管理 --客户级别表(CustLevel) if exists(select * from sysobjects where name='CustLevel') drop table CustLevel create table CustLevel ( Cl_id Int primary key identity(1,1) not null,   --编号 主,自增 Cl_name Varchar(10) not null,           --级别名称 Cl_discount float not null            --折扣 ) --约束 go --客户信息表(customer) if exists(select * from sysobjects where name='customer') drop table customer create table customer ( C_id int primary key identity(1,1) not null,   --编号 主,自动增长 C_number Varchar(10) not null,          --客户代号 C_name Varchar(20) not null,            --客户名称 C_linkman Varchar(20) not null,        --联系人 C_phone Varchar(11) not null,          --联系电话 C_address Text null,              --公司地址 空,默认地址不详 Cl_id Int not null,              --级别编号 外 C_remark text null,               --备注信息 默认没有备注 空 ) --约束 go --订单表(orders) if exists(select * from sysobjects where name='orders') drop table orders create table orders ( O_id int primary key identity(1,1) not null,  --编号 主,自增 O_number Varchar(20) not null,         --订单代码 日期+随即数生成 O_timestart datetime not null,        --下单日期 下单时间必须在交货时间之前 O_timestop Datetime not null,         --交货日期 O_money Money not null,             --下单金额 C_id Int not null,             --客户编号 外 级联删除 Emp_id int not null              --员工编号 外 ) --约束 go --订单明细表(OrderDetails) if exists(select * from sysobjects where name='OrderDetails') drop table OrderDetails create table OrderDetails ( Od_id Int primary key identity(1,1) not null,   --编号 主,自增 O_id int not null,                --订单编号 外 Pro_id int not null,                --商品编号 外 Od_price Money not null,               --单件金额 Od_accounts Int not null               --单件数量 ) --约束 go --销售单表(Sells) if exists(select * from sysobjects where name='Sells') drop table Sells create table Sells ( Sell_id int primary key identity(1,1) not null,    --编号 主,自增 O_id int not null,                 --订单编号 外 Sell_timestart datetime not null,           --销售日期 下单时间必须在交货时间之前 Sell_timestop Datetime not null,            --交货日期 Sell_money Money not null,              --销售金额 C_id Int not null,              --客户编号 外 Emp_id int not null,               --员工编号 外 Sell_remark text null                   --备注 空 ) --约束 go --销售单明细表(SellDetails) if exists(select * from sysobjects where name='SellDetails') drop table SellDetails create table SellDetails ( Selld_id int primary key identity(1,1) not null,   --编号 主,自增 O_id int not null,               --订单编号 Pro_id int not null,              --商品编号 Selld_price Money not null,             --单件金额 Selld_accounts Int not null              --单件数量 ) --约束 go --***********财务管理 --财务科目表:FinaSub if exists(select * from sysobjects where name='FinaSub') drop table FinaSub create table FinaSub ( Fina_id Int primary key identity(1,1) not null, --科目编号 主,自增 Fina_name Varchar(50) not null, --科目名称 Fina_accounts Varchar(50) not null, --银行账号 随机数生成 Fina_people Varchar(50) not null, --联系人 Fina_telephone Varchar(11) not null, --联系电话 Fina_mode Varchar(10) not null, --是借或贷 Fina_play Varchar(10) not null, --借贷方式(现金、发票) Fian_money money not null --金额 ) go --发票信息表:Invoice if exists(select * from sysobjects where name='Invoice') drop table Invoice create table Invoice ( Invo_id Int primary key identity(1,1) not null, --发票编号 主,自增 Invo_code Varchar(50) not null, --发票单据号 日期+随机数生成,唯一 Invo_type Varchar(10) not null, --发票类型 Invo_money money not null, --金额 Invo_use Varchar(50) not null, --发票用途 Invo_datetime Datetime not null, --发票日期 Emp_id int not null --财务员编号 外,职员表 ) ----约束 go --固定资产表:FixedAssets if exists(select * from sysobjects where name='FixedAssets') drop table FixedAssets create table FixedAssets ( Fix_id Int primary key identity(1,1) not null, --资产编号 主,自增 Fix_name Varchar(100) not null, --资产名称 Fix_money Money not null, --可汇兑金额 Fix_datetime Datetime not null, --添加时间 Fix_remark Text null, --备注 空,默认没有备注 ) ----约束 go --财务员统计视图 --***********权限管理 --用户表:UserInfo if exists(select * from sysobjects where name='UserInfo') drop table UserInfo create table UserInfo ( u_id int primary key identity(1,1) not null, --用户编号,主,自增 u_name varchar(20) not null, --用户名,即登录名 u_pass varchar(10) not null, --登录密码 u_time datetime not null --登录时间 ) --insert into UserInfo values('admin','admin','2008-08-05') --insert into UserInfo values('yqh','yqh','2008-08-05') --insert into UserInfo values('gogo','gogo','2008-08-05') --insert into UserInfo values('wangwang','wangwang','2008-08-05') select * from UserInfo go --角色表:RolesInfo if exists(select * from sysobjects where name='RolesInfo') drop table RolesInfo create table RolesInfo ( r_id int primary key identity(1,1) not null, --角色编号,主,自增 r_name varchar(20) not null, --角色名称,即职位名称,唯一 r_desc text null --角色描述,空,默认没有描述 ) alter table RolesInfo add constraint UQ_r_name unique (r_name) alter table RolesInfo add constraint DF_r_desc default ('没有描述') for r_desc --insert into RolesInfo values('系统管理员','可以有任何操作') --insert into RolesInfo values('总经理','最高管理者') --insert into RolesInfo values('部门经理','管理者') --insert into RolesInfo values('普通员工',default) select * from RolesInfo go --用户和角色中间表(因为是、一对多的关系):UserRolesCenter if exists(select * from sysobjects where name='UserRolesCenter') drop table UserRolesCenter create table UserRolesCenter ( c_id int primary key identity(1,1) not null, --中间表编号,主,自增 u_id int not null, --外,用户编号,修改和删除规则都是层叠 r_id int not null --外,角色编号,修改和删除规则都是层叠 ) alter table UserRolesCenter add constraint FK_u_id foreign key (u_id) references UserInfo(u_id) alter table UserRolesCenter add constraint FK_r_id foreign key (r_id) references RolesInfo(r_id) --insert into UserRolesCenter values(1,1) --insert into UserRolesCenter values(1,2) --insert into UserRolesCenter values(2,2) --insert into UserRolesCenter values(3,3) --insert into UserRolesCenter values(4,4) select * from UserRolesCenter --delete from UserRolesCenter where c_id=5 --查询视图 select * from UserRolesView --查询角色1中已有的用户,利用视图 select * from UserRolesView where r_id=1 --查询角色1中没有的用户,利用子查询,用户表中的所有用户减去角色中已有的用户 Select * from UserInfo where u_id not in (select u_id from UserRolesView where r_id=1) go --菜单表:MenuInfo if exists(select * from sysobjects where name='MenuInfo') drop table MenuInfo create table MenuInfo ( M_id Int primary key identity(1,1) not null,--菜单编号 主,自增 M_name Varchar(50) not null,--菜单名称 M_url Varchar(50) null,--菜单链接 空 M_parentId int not null,--父菜单编号 ) --约束 --insert into MenuInfo values('系统权限管理','',0) --insert into MenuInfo values('人力资源管理','',0) --insert into MenuInfo values('采购管理','',0) --insert into MenuInfo values('仓库管理','',0) --insert into MenuInfo values('销售管理','',0) --insert into MenuInfo values('财务管理','',0) select * from MenuInfo go --4.角色和菜单中间表即权限表:PowerInfo if exists(select * from sysobjects where name='PowerInfo') drop table PowerInfo create table PowerInfo ( P_id Int primary key identity(1,1) not null,--权限编号 主 R_id Int not null,--角色编号 外 ,修改和删除规则都是层叠 M_id int not null,--菜单编号 外 ,修改和删除规则都是层叠 ) --约束 alter table PowerInfo add constraint FK_pr_id foreign key (r_id) references RolesInfo(r_id) alter table PowerInfo add constraint FK_m_id foreign key (m_id) references MenuInfo(m_id) --insert into PowerInfo values(1,1) --insert into PowerInfo values(1,2) --insert into PowerInfo values(2,2) --insert into PowerInfo values(3,3) --insert into PowerInfo values(4,4) select * from PowerInfo --查询视图 select * from RolesMenuView --查询角色1中已有的功能,利用视图 select * from RolesMenuView where r_id=1 --查询角色1中没有的功能,利用子查询,菜单表中的所有功能减去角色中已有的功能 Select * from MenuInfo where m_id not in (select m_id from RolesMenuView where r_id=1) go
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值