Re: Simulating sequences - Mailing list pgsql-general

From
Subject Re: Simulating sequences
Date
Msg-id 65238.216.238.112.88.1061222501.squirrel@$HOSTNAME
Whole thread Raw
In response to Simulating sequences  ("Vilson farias" <vilson.farias@digitro.com.br>)
Responses Re: Simulating sequences  (Dennis Gearon <gearond@cvc.net>)
Re: Simulating sequences  (Dustin Sallings <dustin@spy.net>)
List pgsql-general
>   I'm getting a big performance problem and I would like to ask you
> what
> would be the reason, but first I need to explain how it happens.
>
>   Let's suppose I can't use sequences (it seams impossible but my boss
> doesn't like specific database features like this one).

I can't help you with the details of the performance problem, but I did
have a situation similar in that I had to maintain sequences "manually",
rather than use the PostgreSQL serial data type. The advice I got here
was to "update first, then select". Two important points I learned from
the gurus in this forum were

1) since in my case I was manipulating my simulated sequence inside a
trigger, there is an implicit transaction around the trigger associated
with the insert or update statement that fires the trigger

2) an update statement locks the record until the transaction commits.


With those items in mind, your function could become:

CREATE FUNCTION key_generation(integer, varchar(20)) RETURNS integer
AS'
DECLARE
  the_department ALIAS FOR $1;
  the_table_name ALIAS FOR $2;
BEGIN
  IF NOT EXISTS(SELECT 1 FROM cnfg_key_generation
    WHERE the_department = department AND the_table_name = table_name) THEN
   INSERT INTO cnfg_key_generation VALUES (the_department,the_table_name,0);
  END IF;


    UPDATE cnfg_key_generation
      SET current_key_value = 1 + current_key_value
      WHERE department = the_department AND
            table_name = the_table_name;

  RETURN (SELECT current_value INTO new_value
     FROM cnfg_key_generation
    WHERE the_department = department AND the_table_name = table_name);
END;



> Per example, for a table called 'my_test' I would have the following
> values :
>   department  = 1
>   table_name  = 'my_test'
>   current_key = 1432
>
> Everytime I want a new key to use in my_test primary-key I just
> increment current_key value. For this job, I've created a simple stored
> procedure called key_generation
>
>
> CREATE FUNCTION key_generation(integer, varchar(20)) RETURNS integer
> AS' DECLARE
>   the_department ALIAS FOR $1;
>   the_table_name ALIAS FOR $2;
>   new_key_value  integer;
>   err_num        integer;
> BEGIN
>   new_value := 0;
>
>   LOCK TABLE cnfg_key_generation IN ROW EXCLUSIVE MODE;
>
>   SELECT current_value INTO new_value
>     FROM cnfg_key_generation
>     WHERE the_department = department AND the_table_name = table_name;
>
>   IF NOT FOUND THEN
>     new_key_value := 1;
>     INSERT INTO cnfg_key_generation VALUES
> (the_department,the_table_name,
> new_key_value);
>   ELSE
>     new_key_value := new_key_value + 1;
>
>     UPDATE cnfg_key_generation
>       SET current_key_value = new_key_value
>       WHERE department = the_department AND
>             table_name = the_table_name;
>   END IF;
>
>   RETURN new_key_value;
>
> END;
> '
> LANGUAGE 'plpgsql';
>
>
> Data insertion is done by the following way :
>
> INSERT INTO my_test VALUES (key_generation(1, 'my_test'), ...other
> fields...);
>


~Berend Tober




pgsql-general by date:

Previous
From: Aaron
Date:
Subject: newbie and no idea
Next
From: Rich Parker
Date:
Subject: Re: New to list, quick question.