我可以在不引用另一个表的情况下对列进行约束吗?

时间:2009-08-29 22:20:09

标签: sql constraints lookup-tables

我有一个文本列,只能有3个可能的字符串中的1个。要对它施加约束,我将不得不引用另一个表。我可以将约束的值直接放在列上而不引用另一个表吗?

3 个答案:

答案 0 :(得分:5)

如果这是SQL ServerOraclePostgreSQL,是的,您可以使用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_byassigned_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)

OracleSQL ServerPostgreSQL中,使用CHECK约束。

CREATE TABLE mytable (myfield INT VARCHAR(50) CHECK (myfield IN ('first', 'second', 'third'))

MySQL中,使用ENUM数据类型:

CREATE TABLE mytable (myfield ENUM ('first', 'second', 'third'))