定义列的约束类型 
=============================



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

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

约束类型 
-------------------------

下面以 `ware` 表和 `cut` 表为例，介绍 OceanBase 数据库的约束类型。

```sql
obclient>CREATE TABLE ware (w_id int
, w_ytd decimal(12,2)
, w_tax decimal(4,4)
, w_name varchar(10)
, w_street_1 varchar(20)
, w_street_2 varchar(20)
, w_city varchar(20)
, w_state char(2)
, w_zip char(9)
, unique(w_name, w_city)
, primary key(w_id)
);

Query OK, 0 rows affected (0.09 sec)

obclient>CREATE TABLE cust (c_w_id int NOT NULL
, c_d_id int NOT NULL
, c_id int NOT NULL
, c_discount decimal(4, 4)
, c_credit char(2)
, c_last varchar(16)
, c_first varchar(16)
, c_middle char(2)
, c_balance decimal(12, 2)
, c_ytd_payment decimal(12, 2)
, c_payment_cnt int
, c_credit_lim decimal(12, 2)
, c_street_1 varchar(20)
, c_street_2 varchar(20)
, c_city varchar(20)
, c_state char(2)
, c_zip char(9)
, c_phone char(16)
, c_since date
, c_delivery_cnt int
, c_data varchar(500)
, index icust(c_last, c_d_id, c_w_id, c_first, c_id)
, FOREIGN KEY (c_w_id) REFERENCES table_name1(w_id)
, primary key (c_w_id, c_d_id, c_id)
);

Query OK, 0 rows affected (0.10 sec)
```



* 非空约束（`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` 并且必须是不重复的。

  ```sql
  obclient>CREATE TABLE cust (c_w_id int NOT NULL,
  c_d_id int NOT NULL, c_id int NOT NULL,
  c_discount decimal(4, 4),
  c_credit char(2),
  c_last varchar(16),
  c_first varchar(16),
  c_middle char(2),
  c_balance decimal(12, 2),
  c_ytd_payment decimal(12, 2),
  c_payment_cnt int,
  c_credit_lim decimal(12, 2),
  c_street_1 varchar(20),
  c_street_2 varchar(20),
  c_city varchar(20),
  c_state char(2),
  c_zip char(9),
  c_phone char(16),
  c_since date,
  c_delivery_cnt int,
  c_data varchar(500),
  index icust(c_last, c_d_id, c_w_id, c_first, c_id),
  FOREIGN KEY (c_w_id) REFERENCES table_name1(w_id),
  primary key (c_w_id, c_d_id, c_id)
  );
  
  Query OK, 0 rows affected (0.10 sec)
  ```

  

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

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

  OceanBase 数据库默认开启了外键约束检查，外键约束检查开关由租户变量 `foreign_key_checks` 来控制。
  




默认情况下，约束创建后为启用状态。
**说明**



目前 OceanBase 数据库不支持通过 `ALTER TABLE` 语句增加或修改约束，因此您需要在创建表时即确定好表的约束。

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

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

示例：为表的时间列设置默认值，可以使用 `sysdate` 或 `systimestamp` 函数。

```sql
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)
```


