Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database Postgres循环id序列_Database_Postgresql_Locking - Fatal编程技术网

Database Postgres循环id序列

Database Postgres循环id序列,database,postgresql,locking,Database,Postgresql,Locking,假设我有一张桌子: CREATE TABLE custom_sequence ( name TEXT NOT NULL, number INTEGER DEFAULT NULL, is_expired BOOLEAN DEFAULT FALSE ); 在插入时,我必须找到第一个过期的号码,并将其放入新的记录中 例如: "a" 1 FALSE "b" 2 TRUE "c" 3 FALSE 但我需要为每次插入锁定表!有没有更好的办法解

假设我有一张桌子:

CREATE TABLE custom_sequence (
  name       TEXT NOT NULL,
  number     INTEGER DEFAULT NULL,
  is_expired BOOLEAN DEFAULT FALSE
);
在插入时,我必须找到第一个过期的号码,并将其放入新的记录中

例如:

"a" 1 FALSE "b" 2 TRUE "c" 3 FALSE
但我需要为每次插入锁定表!有没有更好的办法解决这个问题?

没有,没有解决办法。这是你想要的东西所固有的。您不能重复使用第一个过期的数字,并且仍然具有并发性,因为在您提交之前,其他人可能会接受并插入它

要使这个并发,您需要某种全局序列管理器,它可以跟踪它已经发出的ID,并对表进行脏读以查看其状态。在数据库引擎中没有类似的功能,您不能在SQL级别执行。也很难做到正确


所以不需要。如果你想重复使用ID,你必须连续进行交易。

你能解释一下为什么要这样做吗?您试图用此代码解决的“业务问题”是什么?如果一个记录#1过期,那么所有子项记录也必须获得编号#1,对吗? "c" 2 FALSE
CREATE OR REPLACE FUNCTION write_custom_number()
  RETURNS TRIGGER AS
  $$
  DECLARE
    next_number INTEGER;
  BEGIN

    SELECT
      CASE
      WHEN count(*) > 0 THEN min(number)
      WHEN count(*) = 0 THEN
        CASE
        WHEN (SELECT
                count(*)
              FROM custom_sequence) > 0
        THEN (SELECT
                count(*)
              FROM custom_sequence) + 1
        WHEN (SELECT
                count(*)
              FROM custom_sequence) = 0
        THEN
          1
        END
      END
    INTO next_number
    FROM custom_sequence
    WHERE is_expired = TRUE;


    IF next_number IS NULL
    THEN
      next_number = 1;
    END IF;

    NEW.number := next_number;

    RETURN NEW;
  END
  $$
LANGUAGE plpgsql;

CREATE TRIGGER write_custom_number
BEFORE INSERT ON custom_sequence FOR EACH ROW
EXECUTE PROCEDURE write_custom_number();