我有一个文本列,它应该只有 3 个可能的字符串中的 1 个。要对其施加约束,我将不得不引用另一个表。我可以将约束的值直接放在列上而不引用另一个表吗?
3 回答
如果这是SQL Server、Oracle或PostgreSQL,是的,您可以使用check constraint
.
如果是 MySQL,check constraint
则 s 被识别但不强制执行。不过,您可以使用enum
. 如果您需要一个逗号分隔的列表,您可以使用set
.
然而,这通常是不受欢迎的,因为它绝对不容易维护。最好创建一个查找表并通过它确保引用完整性。
除了其他提到的 CHECK 约束和 ENUM 数据类型之外,您还可以编写触发器来强制执行所需的限制。
我不一定推荐触发器作为一个好的解决方案,我只是指出另一个符合您不引用查找表标准的选项。
我的习惯是定义查找表而不是使用约束或触发器,当规则只是将列限制为一组有限的值时。检查查找表的性能影响并不比使用 CHECK 约束或触发器差,而且当值集可能不时更改时,管理起来要容易得多。
还有一个常见的任务是查询允许值的集合,例如在用户界面中填充表单字段。当允许的值在查找表中时,这比在 CHECK 约束或 ENUM 定义中的文字值列表中定义时容易得多。
重新评论“如何在没有 id 的情况下进行查找”
CREATE TABLE LookupStrings (
string VARCHAR(20) PRIMARY KEY
);
CREATE TABLE MainTable (
main_id INT PRIMARY KEY,
string VARCHAR(20) NOT NULL,
FOREIGN KEY (string) REFERENCES LookupStrings (string)
);
现在您可以放心,没有任何值MainTable.string
是无效的,因为参照完整性可以防止这种情况发生。但是,当您查询时,您不必加入LookupStrings
表来获取字符串MainTable
:
SELECT main_id, string FROM MainTable;
看?不加入!但是你得到了字符串值。
重新评论多个外键列:
您可以有两个单独的外键,每个外键都可能指向查找表中的不同行。外键列的名称不必与引用表中的列相同。
我的常见示例是错误跟踪数据库,其中一个错误由一个用户报告,但分配给另一个用户修复。reported_by
和都是assigned_to
引用Accounts
表的外键。
CREATE TABLE Bugs (
bug_id INT PRIMARY KEY,
reported_by INT NOT NULL,
assigned_to INT,
FOREIGN KEY (reported_by) REFERENCES Accounts (account_id),
FOREIGN KEY (assigned_to) REFERENCES Accounts (account_id)
);
在Oracle
,SQL Server
和PostgreSQL
中,使用CHECK
约束。
CREATE TABLE mytable (myfield INT VARCHAR(50) CHECK (myfield IN ('first', 'second', 'third'))
在MySQL
中,使用ENUM
数据类型:
CREATE TABLE mytable (myfield ENUM ('first', 'second', 'third'))