插入postgres SQL

问题描述 投票:0回答:2

有没有办法可以在没有自增ID的表中插入一条新记录,而无需专门输入ID。我只想ID是lastId+1。

INSERT  INTO lists VALUES (id,'KO','SPH', '5')
//新id

sql postgresql insert
2个回答
17
投票

不要这样做! 永远想都别想这样做!

这个错误解决方案可能看起来(实际上并不)适合您:

INSERT INTO lists VALUES ((SELECT max(id)+1 FROM lists),'KO','SPH', '5');

但是,如果有人尝试与您同时插入,你们都会得到相同的

id
,这将导致无效结果。您确实应该使用
sequence
或更可靠的机制(当序列中不能有漏洞时,辅助表很常见,但它有一些缺点[它会锁定])。您甚至可以使用
serial
数据类型来使其更容易(它在下面创建一个序列):

CREATE TABLE lists(id serial, col2 text, col3 text, ...);
-- If you don't specify "id", it will autogenerate for you:
INSERT INTO lists(col2, col3, ...) VALUES('KO','SPH', ...);
-- You can also specify using DEFAULT (the same as above):
INSERT INTO lists(id, col2, col3, ...) VALUES(DEFAULT, 'KO','SPH', ...);

如果你真的、真的、真的不能创建和使用序列,你可以按照上面的方法做,但是你必须处理异常(假设

id
字段是 PK 或 UK,并使用读提交事务),类似的东西(在 PL/pgSQL 中):

DECLARE
    inserted bool = false;
BEGIN
    WHILE NOT inserted LOOP;
        BEGIN
            INSERT INTO lists
            VALUES ((SELECT coalesce(max(id),0)+1 FROM lists),'KO','SPH', '5');
            inserted = true;
        EXCEPTION
            WHEN unique_violation THEN
                NULL; -- do nothing, just try again
        END;
    END LOOP;
END;

但是,我再次强烈建议您避免它:使用序列并感到高兴......=D

另外,我知道这是一个示例,但在

INSERT INTO
子句上使用显式列列表。


0
投票

我自己找到了这个解决方案,没有使用额外的功能。 首先,我将最后一个表 ID 移至 CTE,然后使用窗口进行增量。 从视觉上看,这是一个稍微复杂的解决方案,但总体来说相当有效。 示例:

;with table_id as (
    select max(id) as id
    from table
)
insert into table
select table_id.id + row_number() over(),
tab.val1,
val2,
val3
from table_id
cross join(
  values
  ('KO', 'SPH', 5),
  ('PQ', 'RTO', 10)
) as tab(val1, val2, val3);
© www.soinside.com 2019 - 2024. All rights reserved.