4

Is there a way to insert a new record to a table which doesn't have an auto-increment ID without specifically entering the ID. I just want the ID to be lastId+1.

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

4

1 回答 1

13

不要那样做!永远甚至不要考虑这样做!

这个错误的解决方案可能看起来(它没有)为你工作:

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另外,我知道这是一个示例,但在子句中使用显式列列表。

于 2013-09-04T14:28:56.583 回答