postgresql - 在 Postgresql 中,有没有办法将列的值限制为枚举?

标签 postgresql enums

postgresql 中,我可以创建一个表来记录人们拥有哪种类型的车辆。

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

该表可能具有诸如以下的值

 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

car_type 列中的值仅限于集合 {sedantruckmotorcycle}。

有没有办法在 postgresql 中正式化此限制?

最佳答案

我个人会使用外键和查找表。

无论如何你可以使用枚举。我建议阅读文章 PostgreSQL Domain Integrity In Depth :

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

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

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.

关于postgresql - 在 Postgresql 中,有没有办法将列的值限制为枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48212153/

相关文章:

ruby-on-rails - 来自 ActiveRecord 关联的查询结果的自定义排序

bash - 如何将 Redshift SELECT 属性保存到脚本变量中

java - 使用 String name() 声明实现 Java 接口(interface)的 Kotlin 枚举

swift - 关联值和原始值可以在 Swift 枚举中共存吗?

postgresql - pg_dump vs pg_dumpall?哪个用于数据库备份?

postgresql - 我如何使用变量创建或更新 postgresql 序列

sql - 数据库查询以生成基于时间的图表

java - 如何在 spring 数据 jpa 规范中将枚举作为字符串处理

php - 错误 : Class 'SplEnum' not found in PHP 7

ios - Swift 中的开关 - 开关中的 Case 标签应该至少有一个可执行语句