使用空列创建唯一约束

2023-12-23

我有一张具有以下布局的桌子:

CREATE TABLE Favorites (
  FavoriteId uuid NOT NULL PRIMARY KEY,
  UserId uuid NOT NULL,
  RecipeId uuid NOT NULL,
  MenuId uuid
);

我想创建一个与此类似的唯一约束:

ALTER TABLE Favorites
ADD CONSTRAINT Favorites_UniqueFavorite UNIQUE(UserId, MenuId, RecipeId);

但是,这将允许多行具有相同的(UserId, RecipeId), if MenuId IS NULL。我想允许NULL in MenuId存储没有关联菜单的收藏夹,但我只需要每个用户/食谱对最多其中一行。

到目前为止我的想法是:

  1. 使用一些硬编码的 UUID(例如全零)而不是 null。
    然而,MenuId每个用户的菜单都有 FK 约束,所以我必须为每个用户创建一个特殊的“空”菜单,这很麻烦。

  2. 使用触发器检查是否存在空条目。
    我认为这很麻烦,我喜欢尽可能避免触发因素。另外,我不相信他们能保证我的数据永远不会处于不良状态。

  3. 只需忘记它并检查中间件或插入函数中先前是否存在空条目即可,并且没有此约束。

我正在使用 Postgres 9.0。有什么我忽略的方法吗?


Postgres 15 或更高版本

Postgres 15 添加了该子句NULLS NOT DISTINCT. 发行说明: https://www.postgresql.org/docs/15/release-15.html#id-1.11.6.5.5.3.4

  • 允许唯一约束和索引将 NULL 值视为不不同 (Peter Eisentraut)

    以前 NULL 值总是被索引为不同的值,但是 现在可以通过使用创建约束和索引来更改UNIQUE NULLS NOT DISTINCT.

有了这个条款null被视为只是另一个值,并且UNIQUE约束 https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-UNIQUE-CONSTRAINTS不允许多于一行具有相同的内容null价值。现在任务很简单:

ALTER TABLE favorites
ADD CONSTRAINT favo_uni UNIQUE NULLS NOT DISTINCT (user_id, menu_id, recipe_id);

手册章节里有例子“独特的约束” https://www.postgresql.org/docs/15/ddl-constraints.html#DDL-CONSTRAINTS-UNIQUE-CONSTRAINTS.
该子句切换行为all相同索引的键。你无法治疗null对于一个键来说相等,但对于另一个键则不相等。
NULLS DISTINCT保留默认值(与标准 SQL 一致)并且不必拼写出来。

相同的子句适用于UNIQUE index https://www.postgresql.org/docs/15/sql-createindex.html, too:

CREATE UNIQUE INDEX favo_uni_idx
ON favorites (user_id, menu_id, recipe_id) NULLS NOT DISTINCT;

注意新子句的位置after关键领域。

Postgres 14 或以上

Create 两个部分索引 https://www.postgresql.org/docs/current/indexes-partial.html:

CREATE UNIQUE INDEX favo_3col_uni_idx ON favorites (user_id, menu_id, recipe_id)
WHERE menu_id IS NOT NULL;

CREATE UNIQUE INDEX favo_2col_uni_idx ON favorites (user_id, recipe_id)
WHERE menu_id IS NULL;

这样一来,只能有一种组合(user_id, recipe_id) where menu_id IS NULL,有效地实现所需的约束。

可能的缺点:

  • 您不能有外键引用(user_id, menu_id, recipe_id)。 (您似乎不太可能需要三列宽的 FK 参考 - 请改用 PK 列!)
  • 你不能根据CLUSTER在部分索引上。
  • 没有匹配的查询WHERE条件不能使用部分索引。

如果您需要一个complete索引,您也可以删除WHERE条件来自favo_3col_uni_idx并且您的要求仍然得到执行。
该索引现在包含整个表,与另一个索引重叠并变得更大。取决于典型的查询和百分比null值,这可能有用也可能没用。在极端情况下,它甚至可能有助于维护所有三个索引(两个部分索引和顶部的总计索引)。

这是一个很好的解决方案单个可为空列,也许适合两个人。但它很快就会失控,因为您需要为每个可为空列的组合建立一个单独的部分索引,因此该数字呈二项式增长。为了多个可为空的列,请参阅:

  • 为什么我的 UNIQUE 约束没有触发? https://dba.stackexchange.com/a/299107/3684

旁白:我建议不要使用PostgreSQL 中的混合大小写标识符 https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用空列创建唯一约束 的相关文章

  • 多级排序

    我有一个表 其中包含一些记录 其中包含名称 评级等字段 我首先想要根据评级将结果限制为 20 进行排序 然后在此结果集上想要进一步应用基于名称的排序 我知道要排序我们需要使用像这样的查询 Select from table order by
  • 尝试使用 sql 获取单行结果? [复制]

    这个问题在这里已经有答案了 我正在尝试显示所有员工 ID 我需要这样的结果 emp id 10 11 12 13 14 15 当尝试时 SELECT LISTAGG emp id WITHIN GROUP ORDER BY emp id A
  • 将 5 gig 文件导入表时出错

    我正在尝试批量插入表 use SalesDWH go BULK INSERT dbo npi FROM S tmp npi csv WITH FIELDTERMINATOR ROWTERMINATOR n lastrow 200 first
  • 关系代数 - 笛卡尔积与自然连接?

    我正在准备考试 但未能找到一个可靠的标准来确定笛卡尔积是否x要使用或者如果自然连接 X 是要使用的 我想出了一个粗略的指南 如果您需要投影与要连接的表中的属性同名的属性 则必须使用x并说明要投影的表名称 tableA colname1 ta
  • SqlAlchemy:查询具有数组的长度json字段

    我有一个包含 JSON 类型字段的表 JSON 字段包含一个带有数组的 JSON 对象 如何查询该数组每一行的长度 class Post Base tablename posts id Column Integer primary key
  • PLSQL 中的时区转换

    我需要将系统日期和时间转换为特定时区 例如东部时间 我无法假设我当前的时区 如何在plsql中转换它 请帮我 假设你有一个TIMESTAMP WITH TIME ZONE 例如systimestamp 您可以使用AT TIME ZONE句法
  • 如何在此查询中获取以 KM 为单位的距离

    salons Salon select salons gt selectRaw 6371 acos cos radians cos radians lat cos radians lng radians sin radians sin ra
  • MySQL创建表中的日期格式

    我必须使用 MySql 创建一个表 它可以按以下格式存储日期 我尝试过如下 CREATE TABLE birth date DATE 但它不起作用 因为日期格式是 YYYY MM DD 我该怎么办 谢谢 MySQL 或几乎任何其他数据库 中
  • 从 URL 生成报告 - SQL Server Reporting Services 2008

    我有 SQL Server Reporting Services 2008 当我打开以下 URL 时 http localhost Reports Pages Report aspx someReport 我正在进入报告屏幕 在其中填写参数
  • MySQL中如何重置表的自增列

    我有一张桌子 它的第一列sl是自动递增的 填充表格后 我删除了前两行 第一个条目有sl1 是否可以重置为1维持AI 我正在使用 PHP MyAdmin ALTER TABLE tablename AUTO INCREMENT 1
  • Postgresql:删除某些类型的数字之间的空格

    我有一列地址 例如 01031 970 S o Paulo SP BR 我想删除邮政编码之间的空格 邮政编码可以出现在地址的任何位置 例如 S o Paulo 01031 970 SP BR 结果应该是 S o Paulo 01031970
  • QGIS 和 PostGIS(地图点(美国地图上的纬度和经度以及半径)

    我安装了QGIS和PostGIS 我想在美国地图上以 100 英里为半径显示 200 个点 我已将纬度和经度导入 PostGIS 数据库中 所以我有三个字段 地址 纬度 经度 1 我需要将纬度和经度字段转换为点或几何字段吗 如果是这样怎么办
  • 使用输出在合并语句中设置变量

    我有一个合并语句应该始终更新或插入一条记录 我想记住变量中该语句的 ID 它看起来像这样 DECLARE int int MERGE dbo table AS A USING SELECT stringtomatch AS string A
  • LINQ 表达式中的 String.IsNullOrWhiteSpace

    我有以下代码 return this ObjectContext BranchCostDetails Where b gt b TarrifId tariffId b Diameter diameter b TarrifId tariffI
  • MYSQL 中当前行上日期之前(并包括该日期)的所有行的总和

    重要的是要知道在查询期间日期是未知的 因此我不能只硬编码 WHERE 子句 这是我的桌子 Date ID Customer Order Count 20150101 Jones 6 20150102 Jones 4 20150103 Jon
  • 如何使用索引更改表的列?

    我想将带有某些索引的表中 a 列的列大小从 varchar 200 更改为 varchar 8000 我应该如何进行 既然是VARCHAR你正在增加尺寸 然后简单地ALTER TABLE ALTER COLUMN https learn m
  • NOLOCK 和 UNCOMMITTED 之间有什么区别

    我使用 SQL Server 2012 我写了两个查询 但是它们之间有什么不同NOLOCK and UnCommitted SELECT lastname firstname FROM HR Employees with READUNCOM
  • sql连接一个表中的两个字段

    我有一个预订表 其中有两个人 我想将 person 1 作为一行返回 将 person 2 作为新行返回 但该人的 id 与人员表相关 这是我所得到的 但没有提取预订信息 SELECT people FROM select booking
  • 新分配的序列不起作用

    在 PostgreSQL 中 我创建了一个新表并为其分配了一个新序列id柱子 如果我从 PostgreSQL 控制台插入记录 它可以工作 但是当我尝试从 Rails 导入记录时 它会引发异常 无法找到关联的序列 这是表格 d user me
  • SQL Server 为什么索引不与 OR 一起使用

    我一直在研究索引并试图了解它们是如何工作的以及如何使用它们来提高性能 但我错过了一些东西 我有下表 Person Id Name Email Phone 1 John E1 P1 2 Max E2 P2 我正在尝试找到对列进行索引的最佳方法

随机推荐

  • 用 Java 编写互斥锁

    我是计算机科学的新手 我正在读一本介绍线程和互斥体的书 我尝试过用 Java 编写互斥体 它似乎在大多数情况下都能工作 但有时却不能 在我的代码中 关键部分将数字 1 到 10 添加到静态变量 j 中 结果为 55 如果 j 从 0 开始
  • D3.js:从选择中删除force.drag

    我有一个 相当简单 的问题 如何在 D3 js 所做的选择上 取消调用 force drag 假设我创建了一组元素并对其调用 call 为其提供强制导向布局的拖动回调 看起来像这样 d3 selectAll rect call force
  • SVG feGaussianBlur 和 feColorMatrix 滤镜在 Chrome 中不起作用?

    我正在尝试使用此代码中的过滤器http bl ocks org nbremer 0e98c72b043590769facc5e829ebf43f http bl ocks org nbremer 0e98c72b043590769facc5
  • 新的 KitKat URI 不响应 Intent.ACTION_VIEW

    由于 KitKat 已将 URI 从选择器更改为类似 content com android providers media documents document image 3951 那么我的 ACTION VIEW 意图都不再起作用了
  • 在Using语句中捕获异常

    我知道Using http msdn microsoft com en us library yh598w02 28v vs 100 29 aspx语句释放正在创建的对象 就像我想做这样的事情 Using SqlConnection con
  • openpyxl 导入时请不要将文本假定为数字

    关于如何阻止 Excel 将文本解释为数字 或者如何使用 openpyxl 输出数字格式 有很多问题 但我还没有看到此问题的任何解决方案 我有一个别人给我的 Excel 电子表格 所以我没有创建它 当我用 Excel 打开文件时 我有某些值
  • 如何使用点“.”访问字典成员?

    如何使 Python 字典成员可以通过点 访问 例如 不要写mydict val 我想写mydict val 我也想以这种方式访问 嵌套字典 例如 mydict mydict2 val 会指 mydict mydict2 val 我一直将其
  • 在 Perl 中如何用单个空格替换多个空格?

    为什么这不起作用 data What is the STATUS of your mind right now data tr print data Use data s 反而 解释 The tr is the 翻译 http www co
  • DataContext 有何用途?

    作为问题的延续将 DataContext 与 WPF 中的另一个属性链接 https stackoverflow com questions 7235403 linking datacontext with another property
  • 使用代理服务器托管多个识别子域的 Node.JS 应用程序

    我正在尝试将某些子域重定向到我的 ubuntu AWS EC2 虚拟服务器上的特定端口 已经尝试过使用 DNS 但根据以下主题 这是行不通的 使用node http proxy的默认路由 https stackoverflow com qu
  • 如何使用 tortoise hg “属于存储库的一部分”忽略 kiln/mercurial 中的文件

    我们将 tortoise hg 与 Kiln 一起使用 在我的 vs 2010 c 项目中 有一些文件是存储库的一部分 但我希望 tortoise hg 在我提交时忽略它们 例如 假设在登录屏幕中 我可以对用户 ID 密码进行硬编码以进行测
  • Shadow DOM 会取代 ::before 和 ::after 吗?

    CSS 范围 http www w3 org TR css scoping 1 shadow dom says 一个的后代影子主机 http www w3 org TR css scoping 1 shadow host不得在中生成框 格式
  • Android Studio 构建 Gradle 速度缓慢

    Android studio 在等级构建过程中变得越来越慢 更新到新版本 3 5 后我注意到这个问题 有什么方法可以解决吗 加快建设进程 1 确保您使用的是最新版本Gradle 一般来说 每次新的更新都会在性能上带来显着的改进 注意 Jav
  • 如何使用 VB6 或 BAT/CMD 列出连接到我的 WiFi 网络的设备?

    我正在制作一个程序来列出连接到我的 Wi Fi 网络的所有设备 以便我可以查看是否有其他人已连接 我找到了 CMD 的代码 net view但它仅列出连接到我的 Wi Fi 的计算机 而不列出移动设备 是否有其他命令可以使用 CMD 列出连
  • JavaScript 倒计时,添加小时和分钟

    所以 我有以下 秒倒计时 井然有序 但 我也尝试在倒计时中添加小时和分钟 理想情况下保持相同的结构 并且只使用纯 JS 我希望输出是 本次促销活动还剩 X 小时 X 分钟 X 秒 var count 30 var counter setIn
  • 作业提交后出现 ClassNotFoundException

    我正在尝试Spring数据 Hadoop http www springsource org spring data hadoop用于从本地计算机的 IDE 在远程集群上执行 MR 代码 Hadoop 1 1 2 Spring 3 2 4
  • 在mssql 2005中保存日期时间,不带小时,分钟和秒

    我想将 sql 2005 中的日期保存为日期 没有小时 分钟和秒 我想这样做是因为如果填写了小时 分钟和秒 则 Between 函数并不总是正确的 但 datetime 和 Smalldatetime 都不允许这样做 在 2008 年 您可
  • 在 PostgreSQL 中如何连接两个表选择单独的信息

    连接时遇到问题 我有一张桌子叫subjects subno subname 30006 Math 31445 Science 31567 Business 我还有一张名为enrollment subno sno 30009 980008 4
  • 创建固定大小的 std::vector 并写入元素

    在 C 中 我希望分配一个固定大小 但大小在运行时确定 的 std vector 然后写入该向量中的元素 这是我正在使用的代码 int b 30 const std vector
  • 使用空列创建唯一约束

    我有一张具有以下布局的桌子 CREATE TABLE Favorites FavoriteId uuid NOT NULL PRIMARY KEY UserId uuid NOT NULL RecipeId uuid NOT NULL Me