Discussion:
Question about serial vs. int datatypes
Lynna Landstreet
2003-06-05 20:05:53 UTC
Permalink
Not sure if the lists are currently working - I just joined both this one
and pgsql-novice, and posted a message to that one earlier in the day, but I
haven't received either any replies or even my own message back, so I don't
know if it's working. I know there was some kind of hardware failure with
regard to the lists, but I don't know how severe.

Anyway: I'm converting a FileMaker Pro database into PostgreSQL, and have a
question (actually, tons of questions, but I'll stick to one for now). Each
of the three major database files in FMP (equivalent to tables in
PostgreSQL) has a number field as a primary key which is incremented
serially as new records are added. Nice and simple, and the same thing a lot
of PostgreSQL databases use.

But... when converting an existing database that already has several hundred
records in it, I can't make that field serial in PostgreSQL, can I? Because
I don't want the existing records renumbered - that would break the links
between the different tables. But if I make the id number just a smallint
field, then I'm stuck incrementing it manually after the conversion. Is
there any way around this? Any way to import the existing records with their
id number intact, and then have it switch to serial after that for new
records?

Any advice would be appreciated...


Lynna
--
Resource Centre Database Coordinator
Gallery 44
www.gallery44.org


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

http://www.postgresql.org/docs/faqs/FAQ.html
Paul Thomas
2003-06-08 08:11:25 UTC
Permalink
Post by Lynna Landstreet
Anyway: I'm converting a FileMaker Pro database into PostgreSQL, and have a
question (actually, tons of questions, but I'll stick to one for now). Each
of the three major database files in FMP (equivalent to tables in
PostgreSQL) has a number field as a primary key which is incremented
serially as new records are added. Nice and simple, and the same thing a lot
of PostgreSQL databases use.
But... when converting an existing database that already has several hundred
records in it, I can't make that field serial in PostgreSQL, can I? Because
I don't want the existing records renumbered - that would break the links
between the different tables. But if I make the id number just a smallint
field, then I'm stuck incrementing it manually after the conversion. Is
there any way around this? Any way to import the existing records with their
id number intact, and then have it switch to serial after that for new
records?
Any advice would be appreciated...
Looking at the docs and after a bit of playing around with 7.3.3, I think
this may work:

1) I believe PG _will_ accept the serial numbers you insert so importing
the data with your serial number fields should work.

2) For each serial type you will find that PG has a created a Sequence
object with a name of the form tablename_columnname_seq. After the import,
you will need to set this to the max value of your serial column with
SELECT pg_catalog.setval("sequencename", value, true);
HTH
--
Paul Thomas
+------------------------------+---------------------------------------------+
| Thomas Micro Systems Limited | Software Solutions for the Smaller
Business |
| Computer Consultants |
http://www.thomas-micro-systems-ltd.co.uk |
+------------------------------+---------------------------------------------+

---------------------------(end of broadcast)---------------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to ***@postgresql.org so that your
message can get through to the mailing list cleanly
Jean-Christian Imbeault
2003-06-08 07:00:14 UTC
Permalink
the current structure where the keywords in any given set (i.e. subject,
medium, etc.) are all lumped together into one long string for each
record
would be considered bad database design
Again, I'm no expert either but I would definitely say that is bad
design. Strangely enough my current job is also converting a FMP DB to
postgres and I had the same issue. Many data clumped into one field.
But if I make each keyword into a boolean field, I'm not sure how
to display them.
That's not a DB issue. In your case that's a web browser issue and
related to whatever web programming language you will use.
Pg usually return the data in the columns, not
the column names.
The data returned is associated with a column name so you always know
where your data came from ;)
When people ultimately view the database records on the
Medium: black and white photograph
Subject: landscape, nature
Processes: hand-tinting, photocollage
black and white photograph: yes
landscape: yes
nature: yes
hand-tinting: yes
photocollage: yes
The only difference between the two versions you show here is that in
the second one you don't show the column names, but of course you (the
programmer) know what they are since you did the SELECT that fetched the
data ...
So I'm thinking that probably each set of keywords (medium, subject,
etc.)
probably needs to be a table {...]
Hum, database design. A thorny issue for the newbie. The way you decide
to go will affect many things so plan carefully.

I don't know enough about your data or database design to suggest
anything but from what I can gather of your data you would have an
exhibition/art piece (?) table in it.

Then you would have a table for, say b/w photography and in that table
you would have one entry for each art piece that fell into that
category. And so on for all the other kinds of possible ways to
categorize the art piece.

So the art piece table would no contain any information at all on what
kind of art it is. To find that out you would need to search all the
possible category tables to see if there was a matching entry for that
art piece.

I think someone may suggest that a view would make you life easier if
you did decide to go that route ...
but I'm not sure if there's a way to modify a select statement so that it
outputs the names of all columns with a yes/true/1 in them, rather than
outputting the values themselves.
If you go with my design you don't knew to output anything. If there is
an entry for that art piece in a particular category table then it's of
that category.
BTW, I'll be using PHP to create the front end
of this for the web site, if that makes a difference.
I'm using PHP too. So far so good ... I did have to dump out all the FMP
data into one big text file and create a custom PHP script to parse the
data and insert it into PG tables and make the necessary relationships
though.

In my case I did have the same serial issue you mentioned in your last
question but since the primary keys in FMP weren't used for anything
else but keys into tables I didn't need to actually keep the same key
id. I just found all the data in the text file that matched on that key,
parsed it, inserted it into PG, let PG assign a new serial and used the
assigned serial to create the relationships in all the other tables.

HTH,
--
Jean-Christian Imbeault


---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to ***@postgresql.org
Joe Conway
2003-06-08 05:39:15 UTC
Permalink
Post by Lynna Landstreet
But... when converting an existing database that already has several hundred
records in it, I can't make that field serial in PostgreSQL, can I? Because
I don't want the existing records renumbered - that would break the links
between the different tables. But if I make the id number just a smallint
field, then I'm stuck incrementing it manually after the conversion. Is
there any way around this? Any way to import the existing records with their
id number intact, and then have it switch to serial after that for new
records?
You can create the field as serial. A serial data type makes the column
*default* to the next value of a sequence, but if you provide a value
(as you would during the import), the default is not used. But you will
need to set the sequence after the import so that it starts with a
number higher than any you imported. See:

http://www.us.postgresql.org/postgresql-7.3.3/functions-sequence.html

For example:

regression=# create table s1(id serial primary key, f2 text);
NOTICE: CREATE TABLE will create implicit sequence 's1_id_seq' for
SERIAL column 's1.id'
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 's1_pkey'
for table 's1'
CREATE TABLE
regression=# \d s1
Table "public.s1"
Column | Type | Modifiers
--------+---------+----------------------------------------------------
id | integer | not null default nextval('public.s1_id_seq'::text)
f2 | text |
Indexes:
"s1_pkey" PRIMARY KEY btree (id)

INSERT INTO s1(id,f2) VALUES (1,'hello');
INSERT INTO s1(id,f2) VALUES (2,'world');
SELECT setval('s1_id_seq',42);
INSERT INTO s1(f2) VALUES ('abc');
regression=# SELECT * FROM s1;
id | f2
----+-------
1 | hello
2 | world
43 | abc
(3 rows)

HTH,

Joe


---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

http://archives.postgresql.org
n***@celery.tssi.com
2003-06-08 05:11:10 UTC
Permalink
Post by Lynna Landstreet
But... when converting an existing database that already has several hundred
records in it, I can't make that field serial in PostgreSQL, can I?
I guess you haven't actually tried this yet, but if you do an insert
with an explicit value for a column of type serial, it inserts that value.
If you leave that column off the list of columns in the insert statement,
it uses the nextval of the implicit sequence, which is the default value
of the column. If you use NULL, you will get an error. You can also
explicitly select the sequence value.

Here's a sample table, test1. Note the two modifiers for 'keyval'.

Column | Type | Modifiers

---------+------------------+----------------------------------------------
keyval | integer | not null
default nextval('public.test1_keyval_seq'::text)
dataval | character varying(30)

INSERT into test1 values ('15','TEST');
INSERT into test1 (dataval) values ('FISH');
INSERT into test1 values (null,'MOUSE');
INSERT into test1 values (nextval('test1_keyval_seq'),'CAT');

select * from test1;
keyval | dataval
--------+---------
15 | TEST
1 | FISH
2 | CAT
(3 rows)
--
Mike Nolan

---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to ***@postgresql.org)
Rory Campbell-Lange
2003-06-08 12:03:43 UTC
Permalink
Post by Lynna Landstreet
But... when converting an existing database that already has several hundred
records in it, I can't make that field serial in PostgreSQL, can I? Because
I don't want the existing records renumbered - that would break the links
between the different tables. But if I make the id number just a smallint
field, then I'm stuck incrementing it manually after the conversion. Is
there any way around this? Any way to import the existing records with their
id number intact, and then have it switch to serial after that for new
records?
Make a new table with a serial type field and then do a \d on that table. You will see that the default value for the field is the next value from the relevant (autocreated) sequence. If you specify a value for the "SERIAL" type field, the field will be filled with that rather than a value from the sequence.

Note that if you do this you need to reset the value of the current sequence. Use something like setval(sequencename) to max(your_serial_field).

Rory

---------------------------(end of broadcast)---------------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to ***@postgresql.org so that your
message can get through to the mailing list cleanly
Lynna Landstreet
2003-06-11 18:21:17 UTC
Permalink
Thanks to everyone who replied to this question, as well as my other one
about special characters. I'm now busily reading up on sequences and
localization. :-)


Lynna
--
Resource Centre Database Coordinator
Gallery 44
www.gallery44.org


---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to ***@postgresql.org
Loading...