数据库的两种模式

数据库的 严格模式(Strict Mode)宽松模式(Non-Strict Mode) 是数据库管理系统(DBMS)中用于控制数据验证和处理方式的两种不同模式。它们的主要区别在于对数据完整性、一致性和错误处理的严格程度。


1. 严格模式(Strict Mode)

在严格模式下,数据库会对数据的插入、更新和删除操作进行严格的验证,确保数据的完整性和一致性。如果数据不符合定义的表结构或约束条件,数据库会拒绝操作并返回错误。

特点
  • 数据验证
    • 数据库会检查数据的类型、长度、唯一性、外键约束等。
    • 例如,如果尝试插入一个超出字段长度的字符串,数据库会拒绝操作。
  • 错误处理
    • 如果数据不符合要求,数据库会直接抛出错误,操作失败。
  • 数据完整性
    • 严格模式确保数据库中的数据始终符合预定义的规则,避免脏数据。
  • 适用场景
    • 适用于对数据完整性要求高的场景,如金融系统、医疗系统等。
示例

假设有一个表 users,定义如下:

sql 复制代码
CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    age INT CHECK (age >= 0)
);

在严格模式下:

  • 如果尝试插入一个 nameNULL 的记录,数据库会拒绝操作。
  • 如果尝试插入一个 age 为负数的记录,数据库会拒绝操作。

2. 宽松模式(Non-Strict Mode)

在宽松模式下,数据库对数据的验证较为宽松,允许某些不符合规则的数据插入或更新,可能会自动截断数据或使用默认值。

特点
  • 数据验证
    • 数据库对数据的验证较为宽松,可能会忽略某些约束条件。
    • 例如,如果插入一个超出字段长度的字符串,数据库可能会自动截断字符串。
  • 错误处理
    • 如果数据不符合要求,数据库可能会尝试修复或忽略错误,而不是直接抛出错误。
  • 数据完整性
    • 宽松模式可能导致数据不一致或脏数据,因为某些不符合规则的数据可能被允许插入。
  • 适用场景
    • 适用于对数据完整性要求较低的场景,如日志记录、临时数据存储等。
示例

在宽松模式下:

  • 如果尝试插入一个 nameNULL 的记录,数据库可能会自动填充默认值(如空字符串)。
  • 如果尝试插入一个 age 为负数的记录,数据库可能会忽略约束条件并允许插入。

3. 严格模式 vs 宽松模式

特性 严格模式 宽松模式
数据验证 严格验证,拒绝不符合规则的数据 宽松验证,可能允许不符合规则的数据
错误处理 抛出错误,操作失败 可能忽略错误或自动修复
数据完整性 高,确保数据始终符合规则 低,可能导致脏数据或不一致
适用场景 金融、医疗等高完整性要求的系统 日志记录、临时数据存储等低要求场景

4. 如何设置严格模式或宽松模式

不同的数据库管理系统(如 MySQL、PostgreSQL、SQLite)对严格模式和宽松模式的支持和设置方式有所不同。

MySQL
  • 严格模式通过 sql_mode 参数控制。

  • 启用严格模式:

    sql 复制代码
    SET sql_mode = 'STRICT_ALL_TABLES';
  • 禁用严格模式:

    sql 复制代码
    SET sql_mode = '';
PostgreSQL
  • PostgreSQL 默认启用严格模式,不支持宽松模式。
  • 如果需要宽松行为,可以通过触发器或规则手动实现。
SQLite
  • SQLite 默认是宽松模式,但可以通过 PRAGMA 命令启用严格模式:

    sql 复制代码
    PRAGMA foreign_keys = ON; -- 启用外键约束
    PRAGMA ignore_check_constraints = OFF; -- 启用检查约束

5. 选择模式的建议

  • 严格模式
    • 适用于对数据完整性要求高的场景。
    • 可以避免脏数据和不一致问题。
  • 宽松模式
    • 适用于对数据完整性要求较低的场景。
    • 可以提高开发效率,但需要额外注意数据质量问题。

总结

严格模式和宽松模式是数据库管理中的重要概念,选择哪种模式取决于应用场景和对数据完整性的要求。严格模式适合高完整性要求的系统,而宽松模式适合对数据质量要求较低的场景。

数据库的常见模式分类:

sql_mode 是 MySQL 中的一个系统变量,它定义了数据库的运行模式,控制了 SQL 语句的解析和执行方式。通过设置不同的 sql_mode,可以启用或禁用特定的 SQL 特性和行为,从而改变数据库的行为方式。

sql_mode 可以包含多个选项,这些选项会影响数据验证、日期/时间处理、空值处理等方面的行为。sql_mode 变量可以在会话级别(针对当前连接)和全局级别(对所有连接)进行设置。

常见的 sql_mode 选项包括:

  1. STRICT_TRANS_TABLES:在严格模式下,如果出现不合法的数据插入(例如,插入空值到非空字段,插入超出字段长度的值等),MySQL 会返回错误而不是警告。如果没有设置该选项,MySQL 会将数据插入并发出警告。

  2. ALLOW_INVALID_DATES:允许插入无效日期(如 '2023-02-30'),而在严格模式下,MySQL 会拒绝插入无效日期。

  3. NO_ZERO_DATE:禁止插入值为 '0000-00-00' 的日期。如果开启该模式,插入该日期时会返回错误。

  4. NO_ZERO_IN_DATE:禁止在日期中出现零日(例如,'2023-01-00')。该模式会在遇到零日时抛出错误。

  5. ERROR_FOR_DIVISION_BY_ZERO:在除零操作时抛出错误。在该模式下,执行除以零的操作会导致错误,而不是返回 NULL 或其他值。

  6. NO_AUTO_CREATE_USER :禁止 GRANT 语句自动创建用户。如果没有此模式,GRANT 语句可以在没有先前创建用户的情况下自动创建用户。

  7. NO_ENGINE_SUBSTITUTION:禁止在表的存储引擎不可用时使用默认存储引擎。当启用此选项时,如果指定的存储引擎不可用,MySQL 会抛出错误,而不是回退到默认的存储引擎。

  8. ONLY_FULL_GROUP_BY :启用此模式时,GROUP BY 子句必须包含所有在 SELECT 列表中的非聚合列。也就是说,查询必须按照标准 SQL 语法进行,避免在 GROUP BY 中省略某些字段。这有助于避免不明确的分组操作。

  9. TRADITIONAL:传统模式,它相当于启用了多种严格模式,确保 MySQL 更加严格地执行 SQL 语句,避免一些不良的行为,比如插入无效日期或自动类型转换。

  10. ANSI:启用 ANSI SQL 语法模式,会禁用 MySQL 特有的语法特性,并且遵循标准的 SQL 语法。

  11. STRICT_ALL_TABLES :启用严格模式,对所有表都应用严格检查,和 STRICT_TRANS_TABLES 类似,但是作用范围更广。

设置和查看 sql_mode

  • 查看当前的 sql_mode

    sql 复制代码
    SELECT @@sql_mode;
  • 设置会话级别的 sql_mode

    sql 复制代码
    SET SESSION sql_mode = 'STRICT_TRANS_TABLES,ONLY_FULL_GROUP_BY,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
  • 设置全局级别的 sql_mode

    sql 复制代码
    SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,ONLY_FULL_GROUP_BY,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
  • 设置为某个预定义的模式(例如 TRADITIONAL):

    sql 复制代码
    SET sql_mode = 'TRADITIONAL';

通过合理配置 sql_mode,可以确保数据库在处理数据时符合预期的规范和行为,避免出现潜在的错误或不一致。

以下是每个选项的详细解释:


好的,以下是 sql_mode 中每个选项的详细目的、作用以及示例:

1. STRICT_TRANS_TABLES

  • 目的:启用严格模式,确保插入的数据符合数据库约束条件,避免插入无效或不合法的数据。
  • 作用:当插入的数据不符合表的约束(例如,插入空值到非空字段、插入超出字段长度的数据)时,MySQL 会抛出错误,而不是警告或自动修正。
  • 示例
    • 如果一个列定义为 NOT NULL,而插入 NULL 值:

      sql 复制代码
      CREATE TABLE test (id INT NOT NULL);
      INSERT INTO test (id) VALUES (NULL);  -- 会抛出错误,因为 id 是 NOT NULL
    • 如果插入的字符串长度超过字段长度限制:

      sql 复制代码
      CREATE TABLE test (name VARCHAR(5));
      INSERT INTO test (name) VALUES ('LongName');  -- 会抛出错误,因为 'LongName' 长度超过 5

2. ALLOW_INVALID_DATES

  • 目的:允许插入无效日期数据(如 '2023-02-30')。

  • 作用:在没有严格模式时,MySQL 会允许插入无效的日期值。

  • 示例

    sql 复制代码
    SET sql_mode = 'ALLOW_INVALID_DATES';
    CREATE TABLE test (date_col DATE);
    INSERT INTO test (date_col) VALUES ('2023-02-30');  -- 插入成功,即使日期无效

3. NO_ZERO_DATE

  • 目的:禁止插入值为 '0000-00-00' 的日期。

  • 作用:如果插入一个日期为 '0000-00-00',会抛出错误。

  • 示例

    sql 复制代码
    SET sql_mode = 'NO_ZERO_DATE';
    CREATE TABLE test (date_col DATE);
    INSERT INTO test (date_col) VALUES ('0000-00-00');  -- 会抛出错误

4. NO_ZERO_IN_DATE

  • 目的:禁止在日期中出现零日(如 '2023-01-00')。

  • 作用:如果日期中出现零日('00' 日),会抛出错误。

  • 示例

    sql 复制代码
    SET sql_mode = 'NO_ZERO_IN_DATE';
    CREATE TABLE test (date_col DATE);
    INSERT INTO test (date_col) VALUES ('2023-01-00');  -- 会抛出错误

5. ERROR_FOR_DIVISION_BY_ZERO

  • 目的:在除零操作时抛出错误。

  • 作用:如果发生除以零的运算,MySQL 会抛出错误,而不是返回 NULL 或其他结果。

  • 示例

    sql 复制代码
    SET sql_mode = 'ERROR_FOR_DIVISION_BY_ZERO';
    SELECT 1 / 0;  -- 会抛出错误,因为除以零

6. NO_AUTO_CREATE_USER

  • 目的 :禁止 GRANT 语句自动创建用户。

  • 作用 :当使用 GRANT 语句授权时,如果指定的用户不存在,MySQL 不会自动创建该用户。

  • 示例

    sql 复制代码
    SET sql_mode = 'NO_AUTO_CREATE_USER';
    GRANT ALL PRIVILEGES ON *.* TO 'new_user'@'localhost';  -- 如果用户 'new_user' 不存在,会抛出错误

7. NO_ENGINE_SUBSTITUTION

  • 目的:禁止在指定的存储引擎不可用时回退到默认存储引擎。

  • 作用:如果指定的存储引擎不可用,MySQL 会抛出错误,而不是使用默认的存储引擎(如 InnoDB)。

  • 示例

    sql 复制代码
    SET sql_mode = 'NO_ENGINE_SUBSTITUTION';
    CREATE TABLE test (id INT) ENGINE=MYISAM;  -- 如果 MYISAM 不可用,会抛出错误

8. ONLY_FULL_GROUP_BY

  • 目的 :强制在 GROUP BY 中包含所有非聚合列,遵循 SQL 标准。

  • 作用 :当进行 GROUP BY 查询时,必须显式地在 GROUP BY 子句中包含所有非聚合列,否则查询会抛出错误。

  • 示例

    sql 复制代码
    SET sql_mode = 'ONLY_FULL_GROUP_BY';
    CREATE TABLE test (id INT, name VARCHAR(20));
    SELECT id, name FROM test GROUP BY id;  -- 会抛出错误,因为 `name` 没有被聚合或包含在 GROUP BY 中

9. TRADITIONAL

  • 目的:启用严格模式,确保 MySQL 更加严格地执行 SQL 语句。

  • 作用 :启用此模式时,相当于启用了 STRICT_TRANS_TABLESNO_ZERO_DATENO_ZERO_IN_DATE 等多个严格模式,确保数据更严格地符合约束条件。

  • 示例

    sql 复制代码
    SET sql_mode = 'TRADITIONAL';
    CREATE TABLE test (id INT NOT NULL, name VARCHAR(5));
    INSERT INTO test (id, name) VALUES (1, 'LongName');  -- 会抛出错误,因为 name 的长度超出了限制

10. ANSI

  • 目的:启用 ANSI SQL 语法模式,禁用 MySQL 特有的语法。

  • 作用:此模式会使 MySQL 遵循标准 SQL 语法,禁用 MySQL 特有的扩展特性。

  • 示例

    sql 复制代码
    SET sql_mode = 'ANSI';
    CREATE TABLE test (id INT);
    INSERT INTO test (id) VALUES (1);  -- 使用标准的 SQL 语法进行操作

11. STRICT_ALL_TABLES

  • 目的:对所有表应用严格模式。

  • 作用:启用此模式时,对所有表的数据操作都会严格检查,确保数据符合字段约束。

  • 示例

    sql 复制代码
    SET sql_mode = 'STRICT_ALL_TABLES';
    CREATE TABLE test (id INT NOT NULL, name VARCHAR(5));
    INSERT INTO test (id, name) VALUES (1, 'LongName');  -- 会抛出错误,因为 'LongName' 超过了字段长度限制

总结

sql_mode 可以根据需要启用不同的选项来严格控制 MySQL 数据库的行为,确保数据符合预期的规则。通过配置这些选项,可以防止一些潜在的错误和不一致性,保证数据的准确性和完整性。

``

相关推荐
LJTYBQ34 分钟前
轻松认识 SQL 关键字,打开数据库操作大门
数据库·笔记·sql
山外有山a37 分钟前
从 Neo4j 数据库中提取数据并绘制图谱
数据库·neo4j
Full Stack Developme2 小时前
SQL 版本历史
数据库·sql
杰克逊的日记5 小时前
mysql数据实时全量+增量迁移
数据库·mysql·数据迁移
linuxxx1106 小时前
centos7 升级MariaDB 到 10.5 或更高版本
数据库·mariadb
换个网名有点难6 小时前
django怎么配置404和500
数据库·django
Adellle7 小时前
MySQL
数据库·后端·mysql
就是有点傻7 小时前
C# 中实现一个线程持续读取,另一个线程负责写入,且写入时读取线程暂停
数据库·c#
云观秋毫7 小时前
试试智能体工作流,自动化搞定运维故障排查
运维·数据库·自动化
是沫沫子耶8 小时前
mysql实例
数据库