MySQL中CHECK约束无效和在PG中的对比

今天才知道在MySQL中CHECK约束是无效的,例如下面一段代码,在创建表table1时添加了CHECK约束,要求field1字段的值大于零,随后向field1字段插入-1,这明显违反CHECK约束,但这段代码在MySQL中却可以执行成功。

  1. CREATE TABLE table1  
  2. (  
  3.     field1 INT,  
  4.     CHECK (field1 > 0)  
  5. );  
  6. INSERT INTO table1 VALUES (-1);  
  7. SELECT * FROM table1;  

运行结果:

  1. +--------+  
  2. | field1 |  
  3. +--------+  
  4. |     -1 |  
  5. +--------+  
  6. 1 row in set (0.00 sec)  

解决这个问题有两种方式。如果需要设置CHECK约束的字段值离散的,并且能很容易列举全部可能值,就可以考虑将该字段的类型设置为枚举类型enum()或集合类型set()。比如性别字段可以这样设置,插入枚举值以外值的操作将不被允许:

  1. CREATE TABLE table1  
  2. (  
  3.     gender ENUM('男', '女')  
  4. );  
  5. INSERT INTO table1 VALUES ('秀吉');-- 此次插入操作将失败  

不过enum()类型和set()类型之间还有些小区别,官方文档上有说明。

如果需要设置CHECK约束的字段是连续的,或者列举全部值很困难,比如正实数或正整数,那就只能用触发器来代替约束实现数据有效性了。下面这段代 码创建了一个叫做TestField1_BeforeInsert的约束器,它将保证新插入的数据中field1字段的值不小于零。

  1. DELIMITER $$      
  2.   
  3. CREATE TRIGGER TestField1_BeforeInsert BEFORE INSERT ON table1  
  4. FOR EACH ROW  
  5. BEGIN  
  6.     IF NEW.field1 < 0 THEN  
  7.         SET NEW.field1 = 0;  
  8.     END IF;  
  9. END$$

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

同时在postgresql中进行check约束的测试:

CREATE TABLE OrderItems
(
  order_num  int          NOT NULL ,
  order_item int          NOT NULL ,
  prod_id    char(10)     NOT NULL ,
  quantity   int          NOT NULL check(quantity>0),
  item_price decimal(8,2) NOT NULL 
);
ar_test=# \d OrderItems;
       Table "public.orderitems"
   Column   |     Type      | Modifiers 
------------+---------------+-----------
 order_num  | integer       | not null
 order_item | integer       | not null
 prod_id    | character(10) | not null
 quantity   | integer       | not null
 item_price | numeric(8,2)  | not null
Check constraints:
    "orderitems_quantity_check" CHECK (quantity > 0)

#插入一条满足check约束的数据没有问题
ar_test=# insert into  orderitems values(20005,1,'BR01',100,5.49);
INSERT 0 1
#插入一条违反check约束的数据直接报错
ar_test=# insert into  orderitems values(20005,1,'BR01',0,5.49);
ERROR:  new row for relation "orderitems" violates check constraint "orderitems_quantity_check"
DETAIL:  Failing row contains (20005, 1, BR01      , 0, 5.49).
#可以看到刚刚正确插入的数据,而违反check约束的语句的数据没有插入==>
ar_test=# select * from orderitems;
 order_num | order_item |  prod_id   | quantity | item_price 
-----------+------------+------------+----------+------------
     20005 |          1 | BR01       |      100 |       5.49
(1 row)

 

posted @ 2016-03-11 08:10  arun_yh  阅读(526)  评论(0编辑  收藏  举报