简体   繁体   English

在Postgresql中,是否有一种方法可以将列的值限制为枚举?

[英]In Postgresql, is there a way to restrict a column's values to be an enum?

In postgresql , I can create a table documenting which type of vehicle people have. postgresql ,我可以创建一个表格来记录人们拥有的车辆类型。

CREATE TABLE IF NOT EXISTS person_vehicle_type
( id SERIAL NOT NULL PRIMARY KEY
, name TEXT NOT NULL
, vehicle_type TEXT
);

This table might have values such as 该表可能具有诸如

 id | name    | vehicle_type
----+---------+---------
  1 | Joe     | sedan
  2 | Sue     | truck
  3 | Larry   | motorcycle
  4 | Mary    | sedan
  5 | John    | truck
  6 | Crystal | motorcycle
  7 | Matt    | sedan

The values in the car_type column are restricted to the set { sedan , truck , motorcycle }. car_type列中的值仅限于{ sedantruckmotorcycle }集。

Is there a way to formalize this restriction in postgresql ? 有没有一种方法可以在postgresql将此限制形式化?

Personally I would use foreign key and lookup table. 我个人将使用外键和查找表。

Anyway you could use enums. 无论如何,您都可以使用枚举。 I recommend to read article PostgreSQL Domain Integrity In Depth : 我建议阅读Depth的PostgreSQL Domain Integrity

A few RDBMSes (PostgreSQL and MySQL) have a special enum type that ensures a variable or column must be one of a certain list of values. 一些RDBMS(PostgreSQL和MySQL)具有特殊的枚举类型,以确保变量或列必须是某个值列表中的一个。 This is also enforcible with custom domains. 这对于自定义域也是强制的。

However the problem is technically best thought of as referential integrity rather than domain integrity, and usually best enforced with foreign keys and a reference table. 但是,从技术上最好将问题视为引用完整性而不是域完整性,并且通常最好使用外键和引用表来解决。 Putting values in a regular reference table rather than storing them in the schema treats those values as first-class data. 将值放在常规参考表中而不是将其存储在架构中会将这些值视为第一类数据。 Modifying the set of possible values can then be performed with DML (data manipulation language) rather than DDL (data definition language) .... 然后可以使用DML(数据操作语言)而不是DDL(数据定义语言)来执行对可能值集的修改。

However when the possible enumerated values are very unlikely to change, then using the enum type provides a few minor advantages. 但是,当可能的枚举值不太可能更改时,则使用枚举类型提供了一些次要的优点。

  1. Enums values have human-readable names but internally they are simple integers. 枚举值具有易于理解的名称,但在内部它们是简单的整数。 They don't take much storage space. 它们不会占用太多存储空间。 To compete with this efficiency using a reference table would require using an artificial integer key, rather than a natural primary key of the value description. 为了使用参考表与这种效率竞争,将需要使用人工整数键,而不是值描述的自然主键。 Even then the enum does not require any foreign key validation or join query overhead. 即使这样,枚举也不需要任何外键验证或联接查询开销。

  2. Enums and domains are enforced everywhere, even in stored procedure arguments, whereas lookup table values are not. 枚举和域在任何地方都被强制执行,即使在存储过程参数中也是如此,而查找表的值则没有。 Reference table enumerations are enforced with foreign keys, which apply only to rows in a table. 参考表枚举使用外键强制执行,外键仅适用于表中的行。

  3. The enum type defines an automatic (but customizable) order relation: 枚举类型定义自动(但可自定义)顺序关系:

 CREATE TYPE log_level AS ENUM ('notice', 'warning', 'error', 'severe');
 CREATE TABLE log(i SERIAL, level log_level);
 INSERT INTO log(level) 
 VALUES ('notice'::log_level), ('error'::log_level), ('severe'::log_level);

 SELECT * FROM log WHERE level >= 'warning';

DBFiddle Demo DBFiddle演示

Drawback: 退税:

Unlike a restriction of values enforced by foreign key, there is no way to delete a value from an existing enum type. 与外键强制执行的值限制不同,无法从现有的枚举类型中删除值。 The only workarounds are messing with system tables or renaming the enum, recreating it with the desired values, then altering tables to use the replacement enum. 唯一的解决方法是弄乱系统表或重命名枚举,使用所需的值重新创建它,然后更改表以使用替换枚举。 Not pretty. 不漂亮。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM