5

我正在为Patient表的现有列设置一个标识列。
在这里,我想使用GENERATED ALWAYS AS IDENTITY

所以我使用以下语句设置身份列(以前是serial):

ALTER TABLE Patient ALTER PatientId
   ADD GENERATED ALWAYS AS IDENTITY (START WITH 1);

对于现有的患者表,我总共有 5 条记录。(patientId1到5)
当我在身份设置后插入新记录时,会抛出如下错误:

more than one owned sequence found

即使在重置标识列之后,我仍然得到同样的错误。

ALTER TABLE Patient ALTER COLUMN PatientId RESTART WITH 6;

如果您有任何解决方案,请告诉我。

4

3 回答 3

12

更新:此错误已在 PostgreSQL v12 中通过提交19781729f78 修复
其余答案与旧版本有关。

列具有由serial列拥有的序列和DEFAULT获取净序列值的值。

如果您尝试将该列更改为标识列,则会收到一条错误消息,指出该列已经存在默认值。

现在您必须删除默认值,而不是属于该serial列的序列。然后,当您将该列转换为标识列时,将创建该列拥有的第二个序列。

现在,当您尝试插入一行时,PostgreSQL 尝试查找并使用列拥有的序列,但有两个,因此出现错误消息。

我认为这是 PostgreSQL 中的一个错误:在我看来,它应该重新利用标识列的现有序列,或者给你一个错误,表明该列已经拥有一个序列,你应该删除它。我会尝试修复这个错误

同时,您应该手动删除列中留下的序列serial。运行以下查询:

SELECT d.objid::regclass
FROM pg_depend AS d
   JOIN pg_attribute AS a ON d.refobjid = a.attrelid AND
                             d.refobjsubid = a.attnum
WHERE d.classid = 'pg_class'::regclass
  AND d.refclassid = 'pg_class'::regclass
  AND d.deptype <> 'i'
  AND a.attname = 'patientid'
  AND d.refobjid = 'patient'::regclass;

serial这应该会给你从列中留下的序列的名称。删除它,标识列应该按需要运行。

于 2019-04-14T13:24:51.793 回答
1

这不是一个答案——道歉,但这让我能够以生动的形象展示我今天早上(无意中)发现的疯狂行为......

在此处输入图像描述

我所要做的就是:

alter TABLE db.generic_items alter column generic_item_id drop default;
alter TABLE db.generic_items alter column generic_item_id add generated by default as identity;

现在在将表编写为 SQL 脚本时,我得到(缩写):

CREATE TABLE db.generic_items
(
    generic_item_id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
    generic_item_id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
    generic_item_name character varying(50) COLLATE pg_catalog."default" NOT NULL,
    CONSTRAINT pk_generic_items PRIMARY KEY (generic_item_id),
)

我很感谢Laurenz Albe 在上面发布的答案!正如他解释的那样,只需删除用于串行默认值的序列,这种疯狂就会消失,表格看起来又正常了。

于 2019-10-01T14:40:42.833 回答
0

同样,这不是答案,但评论并没有让我添加足够的文字。道歉。继续我之前的评论。这就是我执行的操作,它表明,imo,手动修复是不够的,并且对于大型表,我使用的重复技巧(见下文)将是不切实际的并且可能是错误的,因为采用属于已删除行的 id。

-- pls disregard the absence of 2 id rows, this is the final situation    
\d vaste_data.studie_type
                                  Table "vaste_data.studie_type"
     Column |         Type          | Collation | Nullable |             Default
    --------+-----------------------+-----------+----------+----------------------------------
     id     | integer               |           | not null | generated by default as identity
     naam   | character varying(25) |           | not null |
    Indexes:
        "pk_tstudytype_tstudytype_id" PRIMARY KEY, btree (id)
    Referenced by:
        TABLE "stuwadoors" CONSTRAINT "fk_t_stuwadoors_t_studytype" FOREIGN KEY (study_type_id) REFERENCES vaste_data.studie_type(id)
        TABLE "psux" CONSTRAINT "study_studytype_fk" FOREIGN KEY (studie_type_id) FOREIGN KEY (studie_type_id) REFERENCES vaste_data.studie_type(id)
    
    alter table vaste_data.studie_type alter column id drop default;
    ALTER TABLE
    alter table vaste_data.studie_type alter column id add generated by default as identity;
    ALTER TABLE
    -- I chose to show both sequences so I could try to drop either one.
    SELECT d.objid::regclass
    FROM pg_depend AS d
       JOIN pg_attribute AS a ON d.refobjid = a.attrelid AND
                                 d.refobjsubid = a.attnum
    WHERE d.classid = 'pg_class'::regclass
      AND d.refclassid = 'pg_class'::regclass
      AND a.attname = 'id'
      AND d.refobjid = 'vaste_data.studie_type'::regclass;
                      objid
    -----------------------------------------
     vaste_data.studie_type_id_seq
     vaste_data.tstudytype_tstudytype_id_seq
    (2 rows)
    
    drop sequence vaste_data.studie_type_id_seq;
    ERROR:  cannot drop sequence vaste_data.studie_type_id_seq because column id of table vaste_data.studie_type requires it
    HINT:  You can drop column id of table vaste_data.studie_type instead.
    
    \d vaste_data.studie_type_id_seq
                   Sequence "vaste_data.studie_type_id_seq"
      Type   | Start | Minimum |  Maximum   | Increment | Cycles? | Cache
    ---------+-------+---------+------------+-----------+---------+-------
     integer |     1 |       1 | 2147483647 |         1 | no      |     1
    Sequence for identity column: vaste_data.studie_type.id
    
    alter sequence vaste_data.studie_type_id_seq start 6;
    ALTER SEQUENCE
    drop sequence vaste_data.tstudytype_tstudytype_id_seq;
    DROP SEQUENCE
    insert into vaste_data.studie_type (naam) values('Overige leiding');
    ERROR:  duplicate key value violates unique constraint "pk_tstudytype_tstudytype_id"
    DETAIL:  Key (id)=(1) already exists.
    ...
    ERROR:  duplicate key value violates unique constraint "pk_tstudytype_tstudytype_id"
    DETAIL:  Key (id)=(5) already exists.
    insert into vaste_data.studie_type (naam) values('Overige leiding');
    INSERT 0 1
于 2021-10-10T13:04:10.097 回答