Download presentation
Presentation is loading. Please wait.
Published byChad Barrie Anderson Modified over 9 years ago
1
By: Lloyd Albin 11/6/2012
2
Serials are really integers that have a sequence attached to provide the capability to have a auto incrementing integer. There are three sizes of serials: NameStorage SizeRange smallserial2 bytes1 to 32,767 serial4 bytes1 to 2,147,483,647 bigserial8 bytes1 to 9,223,372,036,854,775,807
3
The simplest way to create a serial is to use the serial type. CREATE TABLE tablename ( colname SERIAL ); Using the serial type will cause this notice to show up. NOTICE: CREATE TABLE will create implicit sequence "tablename_colname_seq" for serial column "tablename.colname"
4
The notice can be avoided by creating a serial the long method. CREATE SEQUENCE tablename_colname_seq; CREATE TABLE tablename ( colname integer NOT NULL DEFAULT nextval('tablename_colname_seq') ); ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
5
The dump method does the same thing but in a different order and does two extra command. CREATE TABLE tablename ( colname integer NOT NULL ); CREATE SEQUENCE tablename_colname_seq; ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname; SELECT pg_catalog.setval('tablename_colname_seq', 1, true); ALTER TABLE tablename ALTER COLUMN colname SET DEFAULT nextval('tablename_colname_seq'::regclass);
6
Thus, we have created an integer column and arranged for its default values to be assigned from a sequence generator. A NOT NULL constraint is applied to ensure that a null value cannot be inserted. (In most cases you would also want to attach a UNIQUE or PRIMARY KEY constraint to prevent duplicate values from being inserted by accident, but this is not automatic.) Lastly, the sequence is marked as "owned by" the column, so that it will be dropped if the column or table is dropped. The sequence created for a serial column is automatically dropped when the owning column is dropped. You can drop the sequence without dropping the column, but this will force removal of the column default expression.
7
When you need to move a table with a serial, you may just simply move the table and the sequence will automatically move with the table. ALTER TABLE old_schemaname.tablename SET SCHEMA new_schemaname;
8
When you need to delete a table with a serial, you may just simply delete the table and the sequence will automatically be deleted with the table. DROP TABLE tablename; Even if you use restrict, the sequence will be deleted. DROP TABLE tablename RESTRICT;
9
According to the docs, 9.2 and older, you may delete the sequence and this will remove the default expression. DROP SEQUENCE tablename_colname_seq; ERROR: cannot drop sequence tablename_colname_seq because other objects depend on it DETAIL: default for table tablename column colname depends on sequence tablename_colname_seq HINT: Use DROP... CASCADE to drop the dependent objects too.
10
So now we will try dropping the sequence with a cascade command. DROP SEQUENCE tablename_colname_seq CASCADE; This works perfectly leaving the table and having removed the default and switching the serial to a integer.
11
Everything seems to be great. You go along moving tables/views/etc to other schemas, so anything left over must me ok to drop before dropping the schema. There might even be some sequences that you can drop without any error messages. But the problem appears later when you try entering data into a table and receive this message. INSERT INTO tablename VALUES (DEFAULT); ERROR: relation "tablename_colname_seq" does not exist
12
So while these two serials may look the same on the outside, they don’t act the same and so must be different on the inside.
13
When looking closely at two tables, one that the sequence moved and one that the sequence did not move, I noticed that they were slightly different. Working Style – Sequence moves: CREATE TABLE tablename ( colname integer DEFAULT nextval('tablename_colname_seq'::regclass) NOT NULL ); Problem Style – Sequence does not move: CREATE TABLE tablename ( colname integer DEFAULT nextval(('tablename_colname_seq'::text)::regclass) NOT NULL );
14
To fix the default value, you need to remove the text by issuing an alter table command. ALTER TABLE tablename ALTER COLUMN colname SET DEFAULT nextval('tablename_colname_seq'::regclass);
15
If you now move the tables to a different schema and then try to delete the sequence in the old schema you will get the error message about “cannot drop sequence”. This is good because we are now seeing some referential integrity. But they sequence did not move with the table. If you delete the table the sequence will not be deleted. So there is currently only one way referential integrity.
16
With my GUI tools the tables/sequence now look the same, so I dumped both types of tables and found one more difference. ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
17
Now the table acts the way we expect it should. When we move the table, the sequence moves also. We are not allowed to delete the sequence without deleting the table. If we delete the table, the sequence is automatically deleted. We now have bi-directional referential integrity.
18
When looking at the Postgres documentation about Sequence Functions, I found when everything changed. It happened between versions 8.0 and 8.1. If you have any serials created in 8.0 or before and are now using 8.1 or newer, you do not have any referential integrity on those early serials but will have either one- way or bi-directional referential integrity on the newer serials.
19
If you have a 1-1 relationship, sequence to table, then you will want bi-directional referential integrity. If you have a 1 to many relationship, one sequence to many tables, then you will want one way referential integrity. This one way relationship keeps you from dropping the sequence when other tables still rely on it. But you must move the sequence separately when moving the tables.
20
Note: Before PostgreSQL 8.1, the arguments of the sequence functions were of type text, not regclass, and the above-described conversion from a text string to an OID value would happen at run time during each call. For backwards compatibility, this facility still exists, but internally it is now handled as an implicit coercion from text to regclass before the function is invoked. When you write the argument of a sequence function as an unadorned literal string, it becomes a constant of type regclass. Since this is really just an OID, it will track the originally identified sequence despite later renaming, schema reassignment, etc. This "early binding" behavior is usually desirable for sequence references in column defaults and views. But sometimes you will want "late binding" where the sequence reference is resolved at run time. To get late-binding behavior, force the constant to be stored as a text constant instead of regclass: nextval('foo'::text) foo is looked up at runtime Note that late binding was the only behavior supported in PostgreSQL releases before 8.1, so you may need to do this to preserve the semantics of old applications. Of course, the argument of a sequence function can be an expression as well as a constant. If it is a text expression then the implicit coercion will result in a run-time lookup.
21
What we need to do is look at all the default values and see if there are any ‘ ::text)::regclass) ’. SELECT adsrc FROM pg_catalog.pg_attrdef WHERE adnum = 1 AND adsrc LIKE '%::text)::regclass)'; adsrc nextval(('schemaname.tablename_colname_seq'::text)::regclass)
22
The answer is yes, with conditions. 1. If you don’t use the same sequence on more than one table some of the time. It needs to be one way or the other. This is so that you can either do the OWNED BY or not. 2. If you use the default name formatting for the sequence name, this will allow you to easily figure out the table and field name, otherwise it is more complex but not impossible.
23
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname; This provides referential integrity from the table to the sequence. If you move or drop the table, the sequence will either move or be dropped at the same time. ALTER TABLE tablename ALTER COLUMN colname SET DEFAULT nextval('tablename_colname_seq'::regclass); This provides referential integrity from the sequence to the table. You may not delete the sequence if any table relies on it. But must be of type regclass and not a re-cast to type regclass.
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.