postgresql - 如何从数组中删除特定值?
问题描述
我有一个表,其中有一列存储数组值。我最近被要求从数组中删除一个特定的值,我认为这是一项简单的工作,但我最终迷失在复杂的函数和答案中。
这是表的结构和数据。
CREATE TABLE contacts (
id serial PRIMARY KEY,
name VARCHAR (100),
phones TEXT []
);
INSERT INTO contacts (name, phones)
VALUES
(
'John Doe',
'{"(408)-589-5846","(408)-589-5555"}'
),
(
'Lily Bush',
'{"(408)-589-5841"}'
),
(
'William Gate',
'{"(408)-589-5842","(408)-589-58423"}'
);
这是有人帮助我获取数组的索引值的查询,我希望能够基于该索引以某种方式删除该值,但我找不到方法。因此,例如我想删除John Doe
第二个索引处的电话号码,我该如何通过在 where 子句或其他方式中提供索引号来做到这一点?
select c.name,
p.phone,
p.idx
from contacts c
left join lateral unnest(phones) with ordinality as p(phone, idx) on true;
解决方案
您可以使用“切片”表示法获取数组的一部分。phone[2:2]
返回第二个元素,如果要删除,则需要将切片“之前”和切片“之后”连接起来,例如phones[1:1]||phones[3:]
,如果要删除第 4 个元素,则为phones[1:3]||phones[5:]
如果要更改表,请使用带有该表达式的 UPDATE
update contacts
set phones = phones[1:1]||phones[3:]
where name = 'John Doe';
如果您愿意,可以将其放入函数中:
create function array_remove_index(p_input anyarray, p_index int)
returns anyarray
as
$$
select p_input[1:p_index - 1]||p_input[p_index + 1:];
$$
language sql;
update contacts
set phones = array_remove_index(phones, 2)
where name = 'John Doe';
像这样的要求通常表明对模型进行非规范化的决定并不是一个好的选择(并且需要通过索引访问事物是一个强烈的迹象)。
数组不是集合;搜索特定的数组元素可能是数据库设计错误的标志。考虑使用一个单独的表,其中每个项目将是一个数组元素。这将更容易搜索,并且对于大量元素可能会更好地扩展。
数组有时非常方便,但特别是如果您不熟悉 SQL、关系数据库和 Postgres,特别是您应该坚持经过验证的良好规范化数据模型的设计原则。
推荐阅读
- java - 使用 A* 查找最短路径
- amazon-s3 - 如何以动态/编程方式向特定应用程序用户授予对 AWS S3 存储桶上的文件夹的访问权限
- selenium - 如何解决错误“找不到带有定位器'名称:ide_username'的元素。” 使用 Selenium 和 RobotFramework
- amazon-web-services - AWS Xray SDK:我需要使用 boto3 提取服务图,观察“TypeError:'module' object is not callable”错误
- c - 如何避免在函数调用中保留 C 中的字符串值
- sqlite - 在 Android 中获取 SQLite 结果的正确方法
- android - 如何在android中实现实时动态图标,如时钟/日历应用程序?
- javascript - 拦截任何请求 - javascript
- python - 从 Azure Databricks 中的 Azure Datalake Gen2 读取 .nc 文件
- antd - Ant Design 异步树的功能重构返回关键错误