关于列的约束类型 
=============================



为了确保表里的数据符合业务规则，可以在列上定义约束。

约束定义在列上，限制了列里存储的值。当尝试在该列上写入或更新为违反约束定义的值时，会触发一个错误并回滚这个操作；当尝试在已有的表的列上加上一个跟现有数据相冲突的约束时，也会触发一个错误并回滚这个操作。

约束的类型有：

* 非空约束（NOT NULL），不允许约束包含的列的值包含 NULL。

  如 ware 表的 w_name 列类型后面有 not null 约束，表示业务约束每个仓库必须有个名称。有非空约束的列，在 INSERT 语句中必须指明该列的值，除非该列还定义了默认值。如 cust 表的列 c_discount 定义了默认值 0.99，即业务上每个人默认折扣是 0.99。
  




<!-- -->

* 唯一约束（UNIQUE），不允许约束包含的列的值有重复值，但是可以有多个 NULL 值。

  如 ware 表的 (w_name, w_city) 列上有个唯一约束，表示每个城市里仓库的名称必须是不重复的。
  




<!-- -->

* 主键约束（PRIMARY KEY），是 NOT NULL 约束和唯一约束的组合。

  如 ware 表和 cust 表都有个主键 w_id 和 c_id ，这两列不允许为 NULL 并且必须是不重复的。
  




<!-- -->

* 外键约束（FOREIGN KEY），要求约束的列的值取自于另外一个表的主键列。

  如 cust 表的 c_w_id 上有个外键约束引用了 ware 表的 w_id 列，表示业务上顾客归属的仓库必须是属于仓库表里的仓库。

  OceanBase 数据库默认是开启外键约束的，通过租户变量 foreign_key_checks 控制。
  




关于时间列的默认时间设置 
---------------------

当列上有 NOT NULL 约束时，通常建议设置默认值。当列类型是日期或时间类型时，可以设置默认值为数据库当前时间。

* 示例：为表的时间列设置默认值，可以使用 current_timestamp 函数。

  




```javascript
obclient> create table t1(
    id bigint not null primary KEY
    , gmt_create datetime not null default current_timestamp 
    , gmt_modified datetime not null default current_timestamp 
);
Query OK, 0 rows affected (0.07 sec)

obclient> insert into t1(id) values(1),(2),(3);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

obclient> select * from t1;
+----+---------------------+---------------------+
| id | gmt_create            | gmt_modified          |
+----+---------------------+---------------------+
|  1 | 2020-02-27 17:09:23 | 2020-02-27 17:09:23 |
|  2 | 2020-02-27 17:09:23 | 2020-02-27 17:09:23 |
|  3 | 2020-02-27 17:09:23 | 2020-02-27 17:09:23 |
+----+---------------------+---------------------+
3 rows in set (0.00 sec)
```


