1

The question follows, can I auto increment (verification_number) depending on a value of a specific column (here business_uuid) so that verification_number increments by one (1) depending on that business_uuid's own highest number of verification_number?

Database looks as follows: table: verification

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

The verification_id is the Primary Key in this table and I want the verification_number to follow it's own auto increment depending on what it's highest value is filtered only for business_uuid.

The business_uuid is a unique identifier for each business.

Is it possible?

2
  • 1
    Can you give sample input and it's output ? Commented Nov 8, 2016 at 11:27
  • You can fill the values automatically by means of trigger function. Commented Nov 8, 2016 at 11:36

3 Answers 3

1

I think that this is a bad design, but if you really want that, you can achieve it as follows:

  1. Create a unique constraint:

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

    The index created by this will also make the following trigger function faster.

  2. Create a BEFORE trigger to modify 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 new values like this:

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

    Then verification_number will be set as you desire.

There is a problem with concurrency, however.

If several sessions try to insert or update the table concurrently, you will get an error like this:

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

That is because the SELECT statements in concurrent modifications will only see the current (committed) table contents and may erroneously try to insert the same verification_number for a business_uuid.

There is no way to avoid that short of locking the table. But if you receive such an error, you can simply retry the transaction, and odds are that it will work the next time.

Sign up to request clarification or add additional context in comments.

Comments

0

It is not clear if you want the verification_number to be saved to the table but it is possible to create it at query time:

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

The problem with the above approach is that the verification_number will change if rows are deleted

Window functions

Comments

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;

Then, you can call that function as a default value of every key value of every table of your database, as follows:

DEFAULT creaid('key_field'::text, 'table_name'::text)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.