当前位置: 首页 > 面试题库 >

PostgreSQL 8.3中具有非空且唯一约束的增量字段

陶博涉
2023-03-14
问题内容

我有一个带有列“ position”的表“ items”。位置具有唯一且非空的约束。为了在位置x插入新行,我首先尝试增加后续项的位置:

UPDATE items SET position = position + 1 WHERE position >= x;

这导致了唯一的约束冲突:

ERROR:  duplicate key value violates unique constraint

问题似乎出在PostgreSQL执行更新的顺序上。PostgreSQL
<9.0中的唯一约束是不可延迟的,不幸的是,当前无法使用9.0。另外,UPDATE语句不支持ORDER BY子句,并且以下命令也不起作用(仍然重复键冲突):

UPDATE items SET position = position + 1 WHERE id IN (
  SELECT id FROM items WHERE position >= x ORDER BY position DESC)

有人知道不涉及迭代代码中所有项目的解决方案吗?


问题答案:

另一个具有多个唯一索引的表:

create table utest(id integer, position integer not null, unique(id, position));
test=# \d utest
      Table "public.utest"
  Column  |  Type   | Modifiers 
----------+---------+-----------
 id       | integer | 
 position | integer | not null
Indexes:
    "utest_id_key" UNIQUE, btree (id, "position")

一些数据:

insert into utest(id, position) select generate_series(1,3), 1;
insert into utest(id, position) select generate_series(1,3), 2;
insert into utest(id, position) select generate_series(1,3), 3;

test=# select * from utest order by id, position;
 id | position 
----+----------
  1 |        1
  1 |        2
  1 |        3
  2 |        1
  2 |        2
  2 |        3
  3 |        1
  3 |        2
  3 |        3
(9 rows)

我创建了一个以正确的顺序更新位置值的过程:

create or replace function update_positions(i integer, p integer) 
  returns void as $$
declare
  temprec record;
begin
  for temprec in 
    select * 
      from utest u 
      where id = i and position >= p 
      order by position desc 
  loop
    raise notice 'Id = [%], Moving % to %', 
      i, 
      temprec.position, 
      temprec.position+1;

    update utest 
      set position = position+1 
      where position=temprec.position and id = i;
  end loop;
end;
$$ language plpgsql;

一些测试:

test=# select * from update_positions(1, 2);
NOTICE:  Id = [1], Moving 3 to 4
NOTICE:  Id = [1], Moving 2 to 3
 update_positions 
------------------

(1 row)

test=# select * from utest order by id, position;
 id | position 
----+----------
  1 |        1
  1 |        3
  1 |        4
  2 |        1
  2 |        2
  2 |        3
  3 |        1
  3 |        2
  3 |        3
(9 rows)

希望能帮助到你。



 类似资料:
  • 我对Postgres Unique约束有问题,该约束包含多个可能包含空值的列。 让我们假设这种情况: Insert将插入('foo',bar')一次和('foo',NULL)两次(尽管直觉告诉它应该插入一次)。 在这种情况下,解决方案非常简单。我可以添加唯一的索引 但是当有更多的列和不同的类型(不仅仅是文本)时,问题就开始了。假设我们有10列,其中9列可以有值。也许我可以用大量的限制来解决它,但这

  • 我有这样布局的模型: 这里的场景是我永远不希望用户删除数据。相反,删除只会隐藏记录。但是,我仍然希望所有非软删除的记录都遵循唯一的键约束。基本上,我希望有尽可能多的重复的已删除记录,但只有一个唯一的未删除记录可以存在。所以我本来想包括“已删除”字段(由django安全删除库提供),但问题是Django的唯一检查因“psycopg2”而失败。完整性错误:重复的键值违反了 ['field2', 'fi

  • 关于Oracle中对可为空的列进行唯一约束定义的可能解决方案,我想向你们请教/收集一些想法。 null 现在困难的部分来了。我决定,在这个表中,可以存储更多(独立)客户的数据。为此,我添加了名为customer_code的新列。这段代码实际上将表分割成不同的空格,而每个客户只能看到自己的数据。 为此,引入了oracle vpd(虚拟专用数据库)。 每个客户都使用自己的oracle用户 登录时,将加

  • 问题内容: 我有以下代码: 它尝试创建具有给定ID和电子邮件的用户,如果已经存在一个用户-尝试获取现有记录。 我知道这是一个不好的构造,无论如何都会对其进行重构。但是我的问题是这样的: 我如何确定发生了什么:一种与约束违反有关的(在(user_id,电子邮件)上有唯一键)或一种与约束有关的(不能为null)? 问题答案: psycopg2作为成员提供了例外,它为您提供了相当细粒度的错误信息以进行匹

  • 问题内容: 我有这张桌子: 我想创建一个仅在时才适用于字段的唯一约束。 我试图创建一个,但是Oracle说: 什么是正确的语法? 问题答案: @jamesfrj:您似乎正在尝试确保您的表应只包含一个记录。 您可以尝试通过串联各列来创建唯一的功能索引,如下所示 希望能帮助到你

  • 问题内容: 在一个假设的场景中,我是没有表创建特权的用户。我想知道表中的列是否具有 UNIQUE CONSTRAINT 。是否可以在 词典中 查找?我将如何处理? 问题答案: 此处给出的两个答案都缺少一种在列上实施唯一性的方法:通过创建 唯一索引 (而不在列上定义唯一约束)。如果您不熟悉此选项,请参见这两个链接(一个,两个)。 除 唯一约束检查 外 ,还应执行此检查: 要检查唯一约束,请使用已经提