根据PostgreSQL中列的值自动增加

时间:2016-11-08 11:20:56

标签: postgresql primary-key auto-increment

接下来的问题是,我可以根据特定列(此处为business_uuid)的值自动递增(verification_number),以便verify_number根据business_uuid自己的最大数量的verify_number递增一(1)吗? / p>

数据库如下所示: 表:验证

verification_id = integer, sequence (Primary Key)
business_uuid = text
verification_number = integer

verify_id是此表中的主键,我希望verify_number遵循它自己的自动增量,具体取决于它仅为business_uuid过滤的最高值。

business_uuid是每个商家的唯一标识符。

有可能吗?

3 个答案:

答案 0 :(得分:0)

目前尚不清楚您是否希望将verification_number保存到表中,但可以在查询时创建它:

select verification_id, business_uuid, 
    row_number() over(
        partition by business_uuid
        order by verification_id
    ) as verification_number
from verification

上述方法存在的问题是,如果删除行,verification_number会发生变化

Window functions

答案 1 :(得分:0)

我认为这是一个糟糕的设计,但如果你真的想要,你可以按如下方式实现:

  1. 创建一个唯一约束:

    ALTER TABLE verification
       ADD CONSTRAINT verification_uuid_nr_unique
          UNIQUE (business_uuid, verification_number);
    

    由此创建的索引也将使以下触发功能更快。

  2. 创建BEFORE触发器以修改verification_number

    CREATE OR REPLACE FUNCTION veritrig() RETURNS trigger
       LANGUAGE plpgsql AS
    $$BEGIN
       SELECT COALESCE(max(verification_number)+1, 1) INTO NEW.verification_number
          FROM verification
          WHERE business_uuid = NEW.business_uuid;
       RETURN NEW;
    END;$$;
    
    CREATE TRIGGER veritrig
       BEFORE INSERT OR UPDATE ON verification FOR EACH ROW
       EXECUTE PROCEDURE veritrig();
    
  3. 插入如下的新值:

    INSERT INTO verification (business_uuid) VALUES ('42');
    

    然后verification_number将根据您的需要设置。

  4. 然而,并发性存在问题。

    如果多个会话尝试同时插入或更新表,您将收到如下错误:

    ERROR:  duplicate key value violates unique constraint "verification_uuid_nr_unique"
    DETAIL:  Key (business_uuid, verification_number)=(43, 1) already exists.
    

    这是因为并发修改中的SELECT语句只会看到当前(已提交的)表内容,并可能错误地尝试为verification_number插入相同的business_uuid

    没有办法避免锁定表格。但是如果你收到这样的错误,你可以简单地重试交易,并且可能会在下次有效。

答案 2 :(得分:0)

CREATE OR REPLACE FUNCTION public.creaid(
    IN key_field text,
    IN table_mane text,
    OUT id integer)
    RETURNS integer AS
$BODY$
    DECLARE  maxid INT;
    BEGIN
        EXECUTE 'SELECT max('||key_field||') FROM '||table_name INTO maxid;
        IF maxid IS NULL THEN
            id = 1;
        ELSE
            id = maxid + 1;
        END IF;
    END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

然后,您可以将该函数作为数据库每个表的每个键值的默认值调用,如下所示:

DEFAULT creaid('key_field'::text, 'table_name'::text)
相关问题