postgresql SQL:ENUM与一对多关系

jq6vz3qz  于 2023-05-28  发布在  PostgreSQL
关注(0)|答案(9)|浏览(200)

我很少看到ENUM数据类型被广泛使用;开发人员几乎总是使用类似于以下的辅助表:

CREATE TABLE officer_ranks (
id int PRIMARY KEY
,title varchar NOT NULL UNIQUE);
INSERT INTO officer_ranks VALUES (1,'2LT'),(2,'1LT'),(3,'CPT'),(4,'MAJ'),(5,'LTC'),(6,'COL'),(7,'BG'),(8,'MG'),(9,'LTG'),(10,'GEN');

CREATE TABLE officers (
solider_name varchar NOT NULL
,rank int NOT NULL REFERENCES officer_ranks(id) ON DELETE RESTRICT
,serial_num varchar PRIMARY KEY);

但是同样的事情也可以使用用户定义的类型/ ENUM来显示:

CREATE TYPE officer_rank AS ENUM ('2LT', '1LT','CPT','MAJ','LTC','COL','BG','MG','LTG','GEN');
    
CREATE TABLE officers (
solider_name varchar NOT NULL
,rank officer_rank NOT NULL
,serial_num varchar PRIMARY KEY);

(示例使用PostgreSQL显示,但其他RDBMS具有类似的语法)
我认为使用ENUM的最大缺点是,从应用程序内部进行更新更加困难。而且它还可能使那些习惯于将SQL DB简单地用作位桶的没有经验的开发人员感到困惑。
假设信息大部分是静态的(工作日名称、月份名称、美国陆军军衔等),使用ENUM有什么好处吗?

46scxncf

46scxncf1#

  • 使用PostgreSQL显示的示例,但其他RDBMS具有类似的语法 *

这是不正确的。它不是ISO/IEC/ANSI SQL要求,因此商业数据库不提供它(您应该提供查找表)。小镇的小端实现了各种“额外”,但没有实现更严格的要求,或者说是小镇的大端。
我们也没有ENUM作为DataType的一部分,这是荒谬的。
ENUM的第一个缺点是它是非标准的,因此不是可移植的。
ENUM的第二大缺点是数据库是封闭的。可以在数据库上使用的数百个报告工具(独立于应用程序)无法找到它们,因此无法投影名称/含义。如果您有一个普通的标准SQL查找表,则可以消除该问题。
第三个问题是,当您更改值时,必须更改DDL。在普通标准SQL数据库中,您只需在查找表中插入/更新/删除一行。
最后,您无法轻松获得ENUM的内容列表;您可以使用查找表。更重要的是,您有一个向量来执行任何Dimension-Fact查询,从而消除了从大型Fact表和GROUP BY中进行选择的需要。

nc1teljy

nc1teljy2#

我看不出使用ENUMS有什么好处。
它们更难维护,并且不提供任何带有适当外键的常规查找表不允许您做的事情。

j2cgzkjk

j2cgzkjk3#

ENUMS非常非常有用!你只需要知道如何使用它们:
1.一个ENUM只使用4个字节的存储空间。
1.不需要额外的约束(作为FK的替代)。
1.与FK中的自然值相比,值的更改更便宜。
1.无需额外的JOIN

  1. ENUM是有序的,例如您可以比较星期一<星期五,或一月<六月或项目启动<工资单。
    因此,如果你有一个固定的字符串值列表,你想使用,一个ENUM是一个更好的解决方案相比,一个查找表。假设你需要列出产品中的氨基酸,以及它们各自的重量。今天有大约20种氨基酸。如果你要存储他们的全名,你需要更多的空间,每次然后2字节。另一种选择是使用伪键并链接到外部表。但是外国的table会是什么样子呢?它应该有两列:ID和氨基酸名称?你每次都坐在那张table上?如果你的主表有超过40个这样的字段怎么办?查询该表将涉及>40个连接。
    如果你的数据库有1600个表,其中400个是查找表,只是替换ENUM,你的开发人员将浪费大量的时间浏览它们(除了JOIN)。是的,你可以使用前缀、模式等。但为什么不把那些table踢出去呢
    ENUM是枚举列表/有序的。这意味着如果你有有序的值,你实际上节省了维护一个3列查找表的麻烦。
    问题是:为什么我需要查找表呢?答案很简单
    1.当你的价值观经常改变
    1.当你需要存储更多的附加属性时-->查找表对应于一个完整的数据对象,而不是一个查找列表。
    1.当你需要它快速和肮脏
    有趣的是查找表和ENUMS不能完全替代彼此!!!!如果你有一个列表,其中的PK是单列自然键。列表可以增长,或者值可以更改它们的名称(出于某种原因),然后您可以定义一个ENUM并将其用于两者:查找中的PK,主表中的FK!
    示例益处:您必须更改查找键的名称。如果不使用ENUM,DBMS将不得不将更改级联到所有表,在这些表中,您使用此值,而不仅仅是查找表。如果您使用的是ENUM,那么您只需更改ENUM的值,而不会更改数据。
lymnna71

lymnna714#

使用类似ENUM的东西的缺点是,如果数据表中不存在所有可用值,则无法获得所有可用值的列表,除非您在某处硬编码可用值的列表。例如,如果在您的OFFICERS表中,您没有碰巧有一个MG在岗位上,那么就没有办法知道该排名是否存在。因此,当BG Blowhard被MG Marjorie Banks解除职务时,你将无法进入新军官的行列-这是一种耻辱,因为他是现代少将的典范。:-)当军队的将军(五星将军)出现时会发生什么?
对于简单的类型,不会改变我已经成功地使用域。例如,在我的一个数据库中,我有一个yes_no_domain定义如下:

CREATE DOMAIN yes_no_dom
  AS character(1)
  DEFAULT 'N'::bpchar
  NOT NULL
   CONSTRAINT yes_no_dom_check
     CHECK ((VALUE = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])));

分享和享受。

k5ifujac

k5ifujac5#

一个小的优势可能在于这样一个事实,即您在创建ENUM时有一种UDT。用户定义的类型可以在许多其他数据库对象中正式重用,例如在视图、其他表、其他类型、存储过程(在其他RDBMS中)等中。
另一个优点是记录字段的允许值。示例:

  • 是/否字段
  • 男性/女性领域
  • 一个mr/mrs/ms/dr字段

可能是品味问题。对于这类字段,我更喜欢使用ENUM,而不是使用外键来查找表中的这些简单概念。
另一个优点可能是,当您在Java中使用代码生成或ORM(如jOOQ)时,您可以使用该ENUM从它生成Java枚举类,而不是加入查找表或使用ENUM文字的ID
然而,事实上只有少数RDBMS支持正式的ENUM类型。我只知道Postgres和MySQL。Oracle或DB2没有。

2ekbmq32

2ekbmq326#

优点:

  • 存储过程的类型安全:如果无法将参数强制转换为类型,则会引发类型错误。例如:select court_martial('3LT')会自动引发类型错误。
  • 自定义联盟订单:在您的示例中,可以在没有排名ID的情况下对军官进行排序。
j2datikz

j2datikz7#

一般来说,enum更适合那些变化不大的东西,而且它使用的资源稍微少一些,因为在insert等操作中没有FK检查或类似的操作。
使用查找表更优雅和/或传统,并且比枚举更容易添加和删除选项。它也比枚举更容易批量更改值。

cunj1qz1

cunj1qz18#

您没有看到,因为通常开发人员在Java等编程语言中使用枚举,而在数据库设计中没有对应的枚举。
在数据库中,这样的枚举通常是文本或整数字段,没有约束。数据库枚举不会被转换为Java/C#/等。枚举,因此开发人员看不到这方面的好处。
有很多非常好的数据库功能很少使用,因为大多数ORM工具太原始而无法支持它们。

chy5wohz

chy5wohz9#

枚举相对于查找表的另一个好处是,当您编写SQL函数时,您可以进行类型检查。

相关问题