社區投稿 | MySQL 8.0.16 開始支持 check 完整性

一直以來MySQL都只實現了實體完整性、域完整性、引用完整性、惟一鍵約束。html

惟獨 check 完整性遲遲沒有到來,MySQL 8.0.16(2019-04-25 GA) 版本爲這個畫上了句號。mysql


1、沒有 check 完整性約束會怎樣

一、沒有 check 完整性約束可能會影響到數據的質量。sql

 
 
  1.   -- 建立一個 person 表來保存名字,年齡這個兩個基本信息app

  2.   CREATE TABLE person ( NAME VARCHAR ( 16 ), age INT );ide


  3.   -- 這種狀況下能夠插入一個年齡爲 -32 的行,負的年齡明顯是沒有意義的spa

  4.   INSERT INTO person ( NAME, age ) code

  5.   VALUEorm

  6.    ( '張三歲',- 32 );htm


  7.   select * from person;ci

  8.   +-----------+------+

  9.   | name      | age  |

  10.   +-----------+------+

  11.   | 張三歲    |  -32 |

  12.   +-----------+------+

  13.   1 row in set (0.00 sec)


二、若是單單只是不能容忍負值,咱們能夠換一種非負整數類型來克服一下。

 
 
  1.   -- 先刪除以前的 person 定義

  2.   drop table if exists person;

  3.   Query OK, 0 rows affected (0.01 sec)


  4.   -- 建立一個新的 person

  5.   create table if not exists person(name varchar(16),age int unsigned);

  6.   Query OK, 0 rows affected (0.01 sec)


  7.   -- 聲明的時候說明了 age 只能是正數,因此插入負數就會報錯

  8.   insert into person(name,age) value('張三歲',-32);

  9.   ERROR 1264 (22003): Out of range value for column 'age' at row 1


上面的這種解決方案其實就是經過域完整性來實現的數據驗證,域完整性的能力仍是有邊界的。

好比說,要求age必定要18歲之上它是作不到的,而這種需求正是check完整性大顯身手的地方。


2、看用 check 如何解決

一、MySQL  8.0.16+版本, check 完整性解決age要大於18的問題。

 
 
  1.   select @@version;                                                                          

  2.   +-----------+

  3.   | @@version |

  4.   +-----------+

  5.   | 8.0.16    |

  6.   +-----------+

  7.   1 row in set (0.00 sec)


  8.   -- 先刪除以前定義的表

  9.   drop table if exists person;

  10.   Query OK, 0 rows affected (0.01 sec)


  11.   -- 建立新的表,並對 age 列進行驗證,要求它必定要大於 18

  12.   create table if not exists person(

  13.       name varchar(16),

  14.       age int,

  15.       constraint ck_person_001 check (age > 18) -- 加一個 check 約束條件

  16.   );

  17.   Query OK, 0 rows affected (0.02 sec)


  18.   -- 查看錶的定義

  19.   show create table person;                                                                  

  20.   +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

  21.   | Table  | Create Table                                                                                                                                                                                                  |

  22.   +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

  23.   | person | CREATE TABLE `person` (

  24.   `name` varchar(16) DEFAULT NULL,

  25.   `age` int(11) DEFAULT NULL,

  26.   CONSTRAINT `ck_person_001` CHECK ((`age` > 18))

  27.   ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |

  28.   +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+



  29.   1 row in set (0.00 sec)


  30.   -- 插入的數據若是不能經過 check 約束就會報錯

  31.   insert into person(name,age) value('張三歲',-32);

  32.   ERROR 3819 (HY000): Check constraint 'ck_person_001' is violated.


  33.   insert into person(name,age) values('張三歲',17);

  34.   ERROR 3819 (HY000): Check constraint 'ck_person_001' is violated.


  35.   insert into person(name,age) values('張三歲',19);

  36.   Query OK, 1 row affected (0.01 sec)


二、MySQL 8.0.16 如下版本的 MySQL 會怎樣?

 
 
  1.   select @@version;  

  2.   +-----------+

  3.   | @@version |

  4.   +-----------+

  5.   | 8.0.15    |

  6.   +-----------+

  7.   1 row in set (0.00 sec)


  8.   drop table if exists person;

  9.   Query OK, 0 rows affected (0.00 sec)


  10.   create table if not exists person(

  11.       name varchar(16),

  12.       age int,

  13.       constraint ck_person_001 check (age > 18) -- 加一個 check 約束條件

  14.   );

  15.   Query OK, 0 rows affected (0.01 sec)


  16.   -- 能夠看到在低版本下 check 約束被直接無視了,也就是說低版本是沒有 check 約束的

  17.   show create table person;

  18.   +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

  19.   | Table  | Create Table                                                                                                                                                                          |

  20.   +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

  21.   | person | CREATE TABLE `person` (

  22.   `name` varchar(16) COLLATE utf8mb4_general_ci DEFAULT NULL,

  23.   `age` int(11) DEFAULT NULL

  24.   ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci |

  25.   +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

  26.   1 row in set (0.00 sec)


  27.   --

  28.   insert into person(name,age) value('張三歲',-32);

  29.   Query OK, 1 row affected (0.00 sec)


能夠看到在 MySQL 8.0.16 如下的版本中,check直接被忽略。


新版本在CHECK Constraints功能上的完善提升了對非法或不合理數據寫入的控制能力。

除了以上示例中的列約束以外,CHECK Constraints還支持表約束。

想要了解更多關於CHECK Constraints 的詳細語法規則和注意事項,請參考MySQL官網文檔

https://dev.mysql.com/doc/refman/8.0/en/create-table-check-constraints.html

相關文章
相關標籤/搜索