2014-07-31
这个示例是在Joe Celko的《SQL编程风格》中看到的。这本书中的代码是基于SQL规范的,下面以MySQL为例说一下。
使用CHECK约束
在Mysql下,我们在test数据库下创建名为Constant的符合要求的Table:
USE test;
CREATE TABLE Constant (
single CHAR(1) DEFAULT 'X' NOT NULL PRIMARY KEY
CHECK(single = 'X'),
pi REAL DEFAULT 3.1415926 NOT NULL,
e REAL DEFAULT 2.71828 NOT NULL
);
当然,也可以按照下面的形式创建:
CREATE TABLE Constant (
single CHAR(1) DEFAULT 'X' NOT NULL PRIMARY KEY,
pi REAL DEFAULT 3.1415926 NOT NULL,
e REAL DEFAULT 2.71828 NOT NULL,
CONSTRAINT chk_constant_single CHECK(single = 'X')
);
这两种创建方法其实是一回事,就是第二个方法为check约束加了名称。
之所以可以实现Constant表中只能有一行数据,是因为主键single
的值被设定为了有且只能有一个值,即X
。
插入数据:
INSERT INTO Constant(single) VALUES('X');
这之后,如果再执行一次:
INSERT INTO Constant(single) VALUES('X');
会报错如下:
Error Code: 1062. Duplicate entry 'X' for key 'PRIMARY' 0.000 sec
然而,若执行:
INSERT INTO Constant(single) VALUES('Y');
却可以成功执行,这是我们不希望得到的结果。
搜了一下资料,得到了令人蛋疼的答案:MySQL并没有实现CHECK约束。具体可见Mysql CHECK Constraint。
使用ENUM
这样的话,只能换个思路了,ENUM是一个不错的选择:
CREATE TABLE Constant (
single ENUM('X') DEFAULT 'X' NOT NULL PRIMARY KEY,
pi REAL DEFAULT 3.1415926 NOT NULL,
e REAL DEFAULT 2.71828 NOT NULL
);
此时,插入下面的数据:
INSERT INTO Constant(single) VALUES('Y');
将会得到以下错误:
[Err] 1265 - Data truncated for column 'single' at row 1
好了,达到要求了。
资料
关于ENUM的用法,可以参考11.4.4 The ENUM Type。
另外,发现了一篇有意思的文章8 Reasons Why MySQL's ENUM Data Type Is Evil。