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

发布于 2024-08-03 21:32:39 字数 79 浏览 8 评论 0原文

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

I have a text column that should only have 1 of 3 possible strings. To put a constraint on it, I would have to reference another table. Can I instead put the values of the constraint directly on the column without referring to another table?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

羅雙樹 2024-08-10 21:32:39

如果这是 SQL ServerOracle,或 PostgreSQL,是的,您可以使用检查约束

如果是 MySQL,检查约束会被识别,但不会强制执行。您可以使用 enum , 尽管。如果需要逗号分隔的列表,可以使用 设置

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

If this is SQL Server, Oracle, or PostgreSQL, yes, you can use a check constraint.

If it's MySQL, check constraints are recognized but not enforced. You can use an enum, though. If you need a comma-separated list, you can use a set.

However, this is generally frowned upon, since it's definitely not easy to maintain. Just best to create a lookup table and ensure referential integrity through that.

顾铮苏瑾 2024-08-10 21:32:39

除了其他提到的 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 中没有值是无效的,因为引用完整性可以防止这种情况发生。但是,当您查询 MainTable 时,您不必加入 LookupStrings 表来获取字符串:

SELECT main_id, string FROM MainTable;

看到了吗?不加入!但你得到了字符串值。


重新评论多个外键列:

您可以有两个单独的外键,每个外键可能指向查找表中的不同行。外键列的名称不必与引用表中的列的名称相同。

我常见的例子是错误跟踪数据库,其中一个错误由一个用户报告,但分配给另一位用户修复。 reported_bysigned_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)
);

In addition to the CHECK constraint and ENUM data type that other mention, you could also write a trigger to enforce your desired restriction.

I don't necessarily recommend a trigger as a good solution, I'm just pointing out another option that meets your criteria of not referencing a lookup table.

My habit is to define lookup tables instead of using constraints or triggers, when the rule is simply to restrict a column to a finite set of values. The performance impact of checking against a lookup table is no worse than using CHECK constraints or triggers, and it's a lot easier to manage when the set of values might change from time to time.

Also a common task is to query the set of permitted value, for instance to populate a form field in the user interface. When the permitted values are in a lookup table, this is a lot easier than when they're defined in a list of literal values in a CHECK constraint or ENUM definition.


Re comment "how exactly to do lookup without 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)
);

Now you can be assured that no value in MainTable.string is invalid, since the referential integrity prevents that. But you don't have to join to the LookupStrings table to get the string, when you query MainTable:

SELECT main_id, string FROM MainTable;

See? No join! But you get the string value.


Re comment about multiple foreign key columns:

You can have two individual foreign keys, each potentially pointing to different rows in the lookup table. The foreign key column doesn't have to be named the same as the column in the referenced table.

My common example is a bug-tracking database, where a bug was reported by one user, but assigned to be fixed by a different user. Both reported_by and assigned_to are foreign keys referencing the Accounts table.

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)
);
过气美图社 2024-08-10 21:32:39

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'))

In Oracle, SQL Server and PostgreSQL, use CHECK constraint.

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

In MySQL, use ENUM datatype:

CREATE TABLE mytable (myfield ENUM ('first', 'second', 'third'))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文