我有一个文本列,只能有3个可能的字符串中的1个。要对它施加约束,我将不得不引用另一个表。我可以将约束的值直接放在列上而不引用另一个表吗?
答案 0 :(得分:5)
如果这是SQL Server,Oracle或PostgreSQL,是的,您可以使用check constraint
。
如果是MySQL,check constraint
被识别但未被强制执行。不过,您可以使用enum
。如果您需要以逗号分隔的列表,则可以使用set
。
然而,这通常是不受欢迎的,因为它绝对不容易维护。最好创建一个查找表,并通过它确保参照完整性。
答案 1 :(得分:3)
除了另外提及的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)
);
答案 2 :(得分:2)
在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'))