2

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

4

3 回答 3

5

如果这是SQL ServerOraclePostgreSQL,是的,您可以使用check constraint.

如果是 MySQL,check constraint则 s 被识别但不强制执行。不过,您可以使用enum. 如果您需要一个逗号分隔的列表,您可以使用set.

然而,这通常是不受欢迎的,因为它绝对不容易维护。最好创建一个查找表并通过它确保引用完整性。

于 2009-08-29T22:21:05.480 回答
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)
);
于 2009-08-29T22:37:44.760 回答
2

Oracle,SQL 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'))
于 2009-08-29T22:25:15.063 回答