Thread: Serial field

Serial field

From
Francois Thomas
Date:
Hello to all

Unable to find an answer by searching the list archive, I ask my question
here:
I want to migrate a database to PostgreSQL 6.5.2
I need an auto-increment field. I first tried the SERIAL type, but it
doesn't fit my needs.
In fact, I want to:
1/ keep the original INT value of my existing records from another server
(say, first row can be "1", second "3", next one "17",...)
2/ have an automatic incrementation of the last value for a new record. For
exemple, with the values above and a SERIAL field, the default value for a
new field would be "1" (first use of the sequence) instead of "18" (last
value+1)..
I hope my english is not too obscure !
Any advice will be welcome
Regards

--
François THOMAS

Re: Serial field

From
Jason Earl
Date:
I am not entirely sure I understand what you mean, but
I think I understand, so I am going to give answering
your question a shot.  But first of all I would highly
recommend using a newer version of PostgreSQL than
6.5.2.  The latest stable version is 7.1.2 and it is
literally light years ahead of 6.5.2.

That being said the trick that I will outline should
work for a version 6.5 PostgreSQL database.  At least
variations of this trick worked for me when I was
using a PostgreSQL version 6.5.3.

First off it appears to me that what you want is a
column that keeps track of the "revision level" of a
particular row.  Every time the row got updated it's
particular revision number should increment.  There
isn't a PostgreSQL type that does this for you, but it
is fairly easy to do using triggers and a simple
function.

Let's say that you had a table that looked like this:

CREATE TABLE foo (
  rev    int default 0,
  name   char(10)
);

And you created a function and trigger that looked
like this:

CREATE FUNCTION    update_rev() RETURNS OPAQUE AS '
    BEGIN
    NEW.rev := NEW.rev + 1;
    RETURN NEW;
    END;
' LANGUAGE 'plpgsql';

CREATE TRIGGER foo_update_rev BEFORE INSERT OR UPDATE
ON foo
    FOR EACH ROW EXECUTE PROCEDURE update_rev();

Now if you inserted a record into foo without
specifically setting rev like this:

INSERT INTO foo (name) VALUES ('Jason');

Your database would contain the following row:

 rev |    name
-----+------------
   1 | Jason

So far so good.  New rows added to the database would
automagically get a rev of 1.  More importantly if you
decided to update this particular record with an
update statement like:

UPDATE foo SET name = 'Francois' WHERE name = 'Jason'

Your database would look like this.  Note that when
the row was updated it triggered our trigger and
incremented rev by one.

 rev |    name
-----+------------
   2 | Francois


Hopefully this is what you had in mind.  If not please
try and restate your question with a little more
detail.

Take Care,
Jason

--- Francois Thomas <FrancoisT@alsdesign.fr> wrote:
>
> Hello to all
>
> Unable to find an answer by searching the list
> archive, I ask my question
> here:
> I want to migrate a database to PostgreSQL 6.5.2
> I need an auto-increment field. I first tried the
> SERIAL type, but it
> doesn't fit my needs.
> In fact, I want to:
> 1/ keep the original INT value of my existing
> records from another server
> (say, first row can be "1", second "3", next one
> "17",...)
> 2/ have an automatic incrementation of the last
> value for a new record. For
> exemple, with the values above and a SERIAL field,
> the default value for a
> new field would be "1" (first use of the sequence)
> instead of "18" (last
> value+1)..
> I hope my english is not too obscure !
> Any advice will be welcome
> Regards
>
> --
> Fran�ois THOMAS
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 6: Have you searched our list archives?
>
> http://www.postgresql.org/search.mpl


__________________________________________________
Do You Yahoo!?
Get personalized email addresses from Yahoo! Mail
http://personal.mail.yahoo.com/

RE: Serial field

From
"Robby Slaughter"
Date:
Jason and Francois:

Jason: That's not how I interepreted Francois' request,
but it's  a clever approach to what sounds like a common
need in database design. And yes, using a recent version
of PostgreSQL is a good idea!

Francois: It sounds like you just want an
auto-increment field but you don't want to
values you've already have in the table.

I think your best option is to do create the table
first just using standard INTEGERs and import your
data into the table. Then do an ALTER TABLE and
change the table design.

I don't have a convienent way to try it right now
but that should work.

If it doesn't, you count always just create your
own pgplsql stored procedure that works like
a standard sequence. As far as I can tell, when
you create a SERIAL type, that's what happens
anyway. The table definition ends up having
a DEFAULT value for the serial field, which
is a function call to nextval('tablename_fieldname_seq');

You could implement the same code yourself and just
not "turn on" the function until after your original
data is entered.

Hope that helps.

-Robby

> I want to migrate a database to PostgreSQL 6.5.2
> I need an auto-increment field. I first tried the
> SERIAL type, but it
> doesn't fit my needs.
> In fact, I want to:
> 1/ keep the original INT value of my existing
> records from another server
> (say, first row can be "1", second "3", next one
> "17",...)
> 2/ have an automatic incrementation of the last
> value for a new record. For
> exemple, with the values above and a SERIAL field,
> the default value for a
> new field would be "1" (first use of the sequence)
> instead of "18" (last
> value+1)..
> I hope my english is not too obscure !
> Any advice will be welcome
> Regards
>
> --
> Frangois THOMAS
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 6: Have you searched our list archives?
>
> http://www.postgresql.org/search.mpl


__________________________________________________
Do You Yahoo!?
Get personalized email addresses from Yahoo! Mail
http://personal.mail.yahoo.com/

---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

http://www.postgresql.org/users-lounge/docs/faq.html

RE: Serial field

From
Jason Earl
Date:
I actually was torn in my interpretation between the
question that I answered and the one that you
answered.  Since I wasn't sure what the problem was I
chose to answer the question that I thought most
interesting.

If you are correct and Francois simply needs to be
able to import data from another source and "then"
have future values auto increment then that is also
quite possible.  In fact, if you used versions of
PostgreSQL before the SERIAL type was available you
would already know the answer on how to import data
that already has information in the field that you
want to have become auto increment field.

The secret lies in how the SERIAL type is implemented
in PostgreSQL.  For example if I were to create the
table orgs like this:

processdata=> CREATE TABLE orgs (id serial, name
char(10));
NOTICE:  CREATE TABLE will create implicit sequence
'orgs_id_seq' for SERIAL column 'orgs.id'
NOTICE:  CREATE TABLE/UNIQUE will create implicit
index 'orgs_id_key' for table 'orgs'
CREATE

You will notice that the command also creates a
sequence orgs_id_seq.  This sequence is where orgs
gets its values for orgs.id.  Once you know how the
serial type actually works it becomes straightforward
to simply create the table like:

processdata=> CREATE TABLE orgs (id int primary key,
name char(10));
NOTICE:  CREATE TABLE/PRIMARY KEY will create implicit
index 'orgs_pkey' for table 'orgs'
CREATE

Once the table is created you can easily import your
data in whatever manner makes you the happiest.  Once
your data is imported it is a simple manner to find
out the largest value for orgs.id (or whatever) with a
select statement like this:

SELECT max(id) FROM orgs;

Then create a new sequence with a start value one
higher than the value that is returned:

CREATE SEQUENCE orgs_id_seq START <value>;

Once you have got a sequence then you simply alter the
table so that it gets it's default values from that
sequence:

alter table orgs alter id set default
nextval('orgs_id_seq');

Presto, you have just created an auto increment field
from the ground up.

Hope this is helpful,
Jason

--- Robby Slaughter <webmaster@robbyslaughter.com>
wrote:
> Jason and Francois:
>
> Jason: That's not how I interepreted Francois'
> request,
> but it's  a clever approach to what sounds like a
> common
> need in database design. And yes, using a recent
> version
> of PostgreSQL is a good idea!
>
> Francois: It sounds like you just want an
> auto-increment field but you don't want to
> values you've already have in the table.
>
> I think your best option is to do create the table
> first just using standard INTEGERs and import your
> data into the table. Then do an ALTER TABLE and
> change the table design.
>
> I don't have a convienent way to try it right now
> but that should work.
>
> If it doesn't, you count always just create your
> own pgplsql stored procedure that works like
> a standard sequence. As far as I can tell, when
> you create a SERIAL type, that's what happens
> anyway. The table definition ends up having
> a DEFAULT value for the serial field, which
> is a function call to
> nextval('tablename_fieldname_seq');
>
> You could implement the same code yourself and just
> not "turn on" the function until after your original
> data is entered.
>
> Hope that helps.
>
> -Robby
>
> > I want to migrate a database to PostgreSQL 6.5.2
> > I need an auto-increment field. I first tried the
> > SERIAL type, but it
> > doesn't fit my needs.
> > In fact, I want to:
> > 1/ keep the original INT value of my existing
> > records from another server
> > (say, first row can be "1", second "3", next one
> > "17",...)
> > 2/ have an automatic incrementation of the last
> > value for a new record. For
> > exemple, with the values above and a SERIAL field,
> > the default value for a
> > new field would be "1" (first use of the sequence)
> > instead of "18" (last
> > value+1)..
> > I hope my english is not too obscure !
> > Any advice will be welcome
> > Regards
> >
> > --
> > Frangois THOMAS
> >
> > ---------------------------(end of
> > broadcast)---------------------------
> > TIP 6: Have you searched our list archives?
> >
> > http://www.postgresql.org/search.mpl
>
>
> __________________________________________________
> Do You Yahoo!?
> Get personalized email addresses from Yahoo! Mail
> http://personal.mail.yahoo.com/
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/users-lounge/docs/faq.html
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 6: Have you searched our list archives?
>
> http://www.postgresql.org/search.mpl


__________________________________________________
Do You Yahoo!?
Get personalized email addresses from Yahoo! Mail
http://personal.mail.yahoo.com/

Re: Serial field

From
A_Schnabel@t-online.de (Andre Schnabel)
Date:
Hi,

does anybody know, what happens, if a client-app. generates it's own id
like:

INSERT INTO orgs VALUES (
(SELECT max(id)+1 from org),
'orgname');

Will the next insert of just a name throw an error? (duplicate value on
primary key?)
I never tried that. But I do have a postgresql server accessed by two
clients. An old one (generating it's own id's) an a newer one (using DEFAULT
values). So I wrote my own function with pl/pgsql to generate my id's.
If I could handle the duplicate values with a sequenc, maybe it would be the
easier way.

kind regards,
Andre
----- Original Message -----
From: Jason Earl
To: webmaster@robbyslaughter.com ; Francois Thomas ;
pgsql-novice@postgresql.org
Sent: Friday, July 13, 2001 3:39 AM
Subject: RE: [NOVICE] Serial field
......
....Once you know how the
serial type actually works it becomes straightforward
to simply create the table like:

processdata=> CREATE TABLE orgs (id int primary key,
name char(10));
NOTICE:  CREATE TABLE/PRIMARY KEY will create implicit
index 'orgs_pkey' for table 'orgs'
CREATE

Once the table is created you can easily import your
data in whatever manner makes you the happiest.  Once
your data is imported it is a simple manner to find
out the largest value for orgs.id (or whatever) with a
select statement like this:

SELECT max(id) FROM orgs;

Then create a new sequence with a start value one
higher than the value that is returned:

CREATE SEQUENCE orgs_id_seq START <value>;

Once you have got a sequence then you simply alter the
table so that it gets it's default values from that
sequence:

alter table orgs alter id set default
nextval('orgs_id_seq');

Presto, you have just created an auto increment field
from the ground up.

Hope this is helpful,
Jason




RE: Serial field

From
"Sykora, Dale"
Date:
Francois,
    It sounds like you want your migrated data to keep their sequence
values but have new records have n+1 as the sequence value where n is the
largest previous sequence value.  Here is how I would approach this problem.
Create a new table with a serial(sequence) and other fields.  Write a perl
script to read and sort your migration data by sequence number and then
output a sql command file to insert the migrated data 1 row at a time
setting the sequence nextval appropriately before each insert.  Run the sql
file via psql.  Now your table has the migrated data with correct sequence
values and future inserts will work normally.

Thanks,
Dale


> --- Francois Thomas <FrancoisT@alsdesign.fr> wrote:
> >
> > Hello to all
> >
> > Unable to find an answer by searching the list
> > archive, I ask my question
> > here:
> > I want to migrate a database to PostgreSQL 6.5.2
> > I need an auto-increment field. I first tried the
> > SERIAL type, but it
> > doesn't fit my needs.
> > In fact, I want to:
> > 1/ keep the original INT value of my existing
> > records from another server
> > (say, first row can be "1", second "3", next one
> > "17",...)
> > 2/ have an automatic incrementation of the last
> > value for a new record. For
> > exemple, with the values above and a SERIAL field,
> > the default value for a
> > new field would be "1" (first use of the sequence)
> > instead of "18" (last
> > value+1)..
> > I hope my english is not too obscure !
> > Any advice will be welcome
> > Regards
> >
> > --
> > François THOMAS
> >
> > ---------------------------(end of
> > broadcast)---------------------------
> > TIP 6: Have you searched our list archives?
> >
> > http://www.postgresql.org/search.mpl
>
>
> __________________________________________________
> Do You Yahoo!?
> Get personalized email addresses from Yahoo! Mail
> http://personal.mail.yahoo.com/
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/users-lounge/docs/faq.html
>

Silly newbie questions

From
jim davis
Date:
Ok, I was directed that I would be taking over an old mac based database
and was told that we would be moving to a SQL based DB.  I looked into
MySQL (sorry, I know thats a bad word around these parts :) )and sorta
got into it.  Well, I saw the light and have decided to move to
PstgreSQL.  I have downloaded and installed on my SuSE linux server the
latest version (7.1.2) and got it to work... But I have noticed some
differences (duh) that I can't find answers for in the online docs.
In the command line interface in MySQL, if I wanted to see all the
databases on my server, or if I wanted to see all the tables in a given
database, I would type "show databases" or "show tables"  but that
doesnt seem to work in PostgreSQL...

Also, is there a painless way to get all of my MySQL databases and data
moved over to PostgreSQL?

thanks!
-Jim


Re: Silly newbie questions

From
A_Schnabel@t-online.de (Andre Schnabel)
Date:
Hi,

for documentation of the command line interface to PostgreSQL you may look
at the docs for psql (client applications)
http://www.postgresql.org/idocs/index.php?app-psql.html

One of the commands, you are looking for, is "\d". Equivalent to "show
tables".

More informations can be found in the system catalogs (or system tables) of
PostgreSQL.
docs are at:
http://www.postgresql.org/idocs/index.php?catalogs.html

So "select * from pg_database;" should be equivalent to MySQL's "show
databases"

CU,
Andre

----- Original Message -----
From: jim davis
To: 'pgsql-novice@postgresql.org'
Sent: Friday, July 13, 2001 5:44 PM
Subject: [NOVICE] Silly newbie questions


Ok, I was directed that I would be taking over an old mac based database
and was told that we would be moving to a SQL based DB.  I looked into
MySQL (sorry, I know thats a bad word around these parts :) )and sorta
got into it.  Well, I saw the light and have decided to move to
PstgreSQL.  I have downloaded and installed on my SuSE linux server the
latest version (7.1.2) and got it to work... But I have noticed some
differences (duh) that I can't find answers for in the online docs.
In the command line interface in MySQL, if I wanted to see all the
databases on my server, or if I wanted to see all the tables in a given
database, I would type "show databases" or "show tables"  but that
doesnt seem to work in PostgreSQL...

Also, is there a painless way to get all of my MySQL databases and data
moved over to PostgreSQL?

thanks!
-Jim


---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

http://www.postgresql.org/users-lounge/docs/faq.html


Re: Silly newbie questions

From
GH
Date:
On Fri, Jul 13, 2001 at 08:44:44AM -0700, some SMTP stream spewed forth:
> Ok, I was directed that I would be taking over an old mac based database
> and was told that we would be moving to a SQL based DB.  I looked into
> MySQL (sorry, I know thats a bad word around these parts :) )and sorta
> got into it.  Well, I saw the light and have decided to move to
> PstgreSQL.

Congratulations, you have found the One True Database. :)

> I have downloaded and installed on my SuSE linux server the
> latest version (7.1.2) and got it to work... But I have noticed some
> differences (duh) that I can't find answers for in the online docs.

> In the command line interface in MySQL, if I wanted to see all the
> databases on my server, or if I wanted to see all the tables in a given
> database, I would type "show databases" or "show tables"  but that
> doesnt seem to work in PostgreSQL...

Databases: select * from pg_database
Tables can be shown by \dt.
Look into the 'backslash' commands in psql (i.e. refer to \?).
You might also gain something from the psql manpage.
Starting psql with -E will show the actual queries used in the backslash
commands.

> Also, is there a painless way to get all of my MySQL databases and data
> moved over to PostgreSQL?

I know there have been some efforts, and I think there are some completed
systems, but I am not familiar with these.

> thanks!
> -Jim

gh
--
> What, no one sings along with Ricky Martin anymore?
My kid sister does (but then, she prefers pico to vi ...)
    -- Suresh Ramasubramanian, alt.sysadmin.recovery

Re: Serial field

From
"Todd T. Fries"
Date:
Just wanted to chime in here, I'm not on the mailing list so please cc me
any replies.

The techniques you have described I am surprised to not hear the solution
I am employing:

 =# create table foo (id int default nextval('foo_seq'::text),
 (# data text);
CREATE
 =# create sequence foo_seq;
CREATE
 =#

Then if you insert data, the default value will be a sequence that has
several properties to it:

=# \d foo_seq
   Sequence "foo_seq"
   Attribute   |  Type
---------------+---------
 sequence_name | name
 last_value    | integer
 increment_by  | integer
 max_value     | integer
 min_value     | integer
 cache_value   | integer
 log_cnt       | integer
 is_cycled     | "char"
 is_called     | "char"

=# select * from foo_seq;
 sequence_name | last_value | increment_by | max_value  | min_value | cache_value | log_cnt | is_cycled | is_called
---------------+------------+--------------+------------+-----------+-------------+---------+-----------+-----------
 foo_seq       |          1 |            1 | 2147483647 |         1 |           1 |       1 | f         | f
(1 row)

=# insert into foo (data) values ('fee');
INSERT 107739 1
=# insert into foo (data) values ('fie');
INSERT 107740 1
=# insert into foo (data) values ('fo');
INSERT 107741 1
=# insert into foo (data) values ('fum');
INSERT 107742 1
=# select * from foo;
 id | data
----+------
  1 | fee
  2 | fie
  3 | fo
  4 | fum
(4 rows)

=# select * from foo_seq;
 sequence_name | last_value | increment_by | max_value  | min_value | cache_value | log_cnt | is_cycled | is_called
---------------+------------+--------------+------------+-----------+-------------+---------+-----------+-----------
 foo_seq       |          4 |            1 | 2147483647 |         1 |           1 |      30 | f         | t
(1 row)

=#

I believe this is how things were meant to be, no?
--
Todd Fries .. todd@fries.net