对于innodb存储引擎本身而言,提供了以下几种约束:
primary key
unique key
foreign key
default
not null
约束的创建可以采用以下两种方式:
表建立时就进行约束定义;
利用alter table 命令来进行创建约束。
对于主键约束来说,其默认约束名为primary。而对unique key 约束而言,默认约束名和列名一样,也可以自定义约束名。foreign key 约束似乎会有一个比较神秘的默认名称。
例 :
create table test(
id int ,
id_card varchar(20) ,
name varchar (20) not null ,
country char(20) default 'china ',
primary key (id),
unique key(id_card)
)
看见这样的约束,通常都会产生一个疑问,primary key,unique key ,不就是索引嘛,那这和索引有啥区别呢,其实这两个确实创建了索引,也创建了约束。
但是索引和约束在概念上还是有不同的,约束是从逻辑上来说,规范数据,保证数据完整性;索引是数据结构,既有逻辑上的概念,也有数据的物理存储方式。
在从约束上来讲,还有一种数据数据定义上的约束,enum 和set :
sex enum ('男','女'),
还有一种约束可以用触发器来实现,触发器的作用是在执行insert 、delete、和update命令之前或之后自动调用sql命令后存储过程。
最多可以为一个表创建6个触发器,即insert、update、delete的before和after。
现金表:
CREATE TABLE `usercash` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
`cash` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
错误表:
CREATE TABLE `user_cash_err_log` (
`usehost` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
`id` int(11) NOT NULL,
`user` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
`old_cash` int(10) unsigned NOT NULL,
`new_cash` int(10) unsigned NOT NULL,
`time` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
创建触发器
DELIMITER $$
CREATE
/*[DEFINER = { user | CURRENT_USER }]*/
TRIGGER `test`.`trg_usercash_update` BEFORE UPDATE
ON `test`.`usercash`
FOR EACH ROW BEGIN
IF new.cash-old.cash>0 THEN
INSERT INTO user_cash_err_log SELECT USER(),old.id,old.user,old.cash,new.cash,NOW();
SET new.cash=old.cash;
END IF;
END$$
DELIMITER ;
这个示例是在更新usercash表前,调用触发器,判断新的金额是否大于表中的金额,假如大于表中的金额则向错误表中插入错误信息,同时设置新的金额为表中的金额。
这里面还隐藏了一个错误,如果new.cash-old.cash是一个负数,则会报错,因为定义的cash字段是无符号的。
这时需要改写一下触发器 IF CAST(new.cash AS SIGNED)-CAST(old.cash AS SIGNED)>0 THEN 把字段属性转化一下。