MostlyHuman
Programmer
I'm updating a PgSQL application that needs to allow moving of full or partial datasets between databases and servers. Using serial values as primary keys is problematic, as the increment values obviously are not synched on different servers, etc.
I've written a simple plpgsql function to generate a strong primary key, without using serial values. It is a poor-man's equivalent of a GUID (globally unique identifier), at least within our own production environment. I wanted to post it here and see what comments anyone might have. I realize that using a table OID may not be the best server ID, but if a strong server method ID is chosen, what problems does anyone foresee if I use this to generate primary keys with the intent to freely move data between servers and databases?
Here's the function:
/*
plpgsql function which generates a primary key with a strong probability of
being unique across multiple servers and databases. Can be
used to generate strong primary keys which can enhance portability
of data, and eliminate reliance on serial indexes (i.e. autoincrement fields)
to maintain uniqueness of primary keys.
The function retrieves the current time of day, using the timeofday() function,
which will return the actual current time of day (CURRENT_TIMESTAMP function
will return only the time when the TRANSACTION begins, not for the insertion
of each row). The OID of a given table is retrived as well. The table OID is
combined with the current datetime converted in Unix epoch and right-padded
with zeros. The resulting key is a 30-char varchar.
The table OID could (and perhaps should) be replaced with another value that is unique
to a given server, and available to this function.
*/
declare
ts timestamp;
tbl record;
id varchar;
pkey varchar;
begin
/* Get the current date and time */
ts := timeofday();
/* Get the OID from a given table, or replace with other server ID */
SELECT * INTO tbl FROM (SELECT oid FROM pg_class WHERE relname = 'tablename') AS foo;
/* Store the server ID value */
id := tbl.oid;
/* Combine server ID, and epoch value from timestamp and right-pad with zeros */
pkey := rpad((id || '.' || EXTRACT(EPOCH FROM ts)),30,'0');
/* Return the key as a varchar
return pkey;
end;
I've written a simple plpgsql function to generate a strong primary key, without using serial values. It is a poor-man's equivalent of a GUID (globally unique identifier), at least within our own production environment. I wanted to post it here and see what comments anyone might have. I realize that using a table OID may not be the best server ID, but if a strong server method ID is chosen, what problems does anyone foresee if I use this to generate primary keys with the intent to freely move data between servers and databases?
Here's the function:
/*
plpgsql function which generates a primary key with a strong probability of
being unique across multiple servers and databases. Can be
used to generate strong primary keys which can enhance portability
of data, and eliminate reliance on serial indexes (i.e. autoincrement fields)
to maintain uniqueness of primary keys.
The function retrieves the current time of day, using the timeofday() function,
which will return the actual current time of day (CURRENT_TIMESTAMP function
will return only the time when the TRANSACTION begins, not for the insertion
of each row). The OID of a given table is retrived as well. The table OID is
combined with the current datetime converted in Unix epoch and right-padded
with zeros. The resulting key is a 30-char varchar.
The table OID could (and perhaps should) be replaced with another value that is unique
to a given server, and available to this function.
*/
declare
ts timestamp;
tbl record;
id varchar;
pkey varchar;
begin
/* Get the current date and time */
ts := timeofday();
/* Get the OID from a given table, or replace with other server ID */
SELECT * INTO tbl FROM (SELECT oid FROM pg_class WHERE relname = 'tablename') AS foo;
/* Store the server ID value */
id := tbl.oid;
/* Combine server ID, and epoch value from timestamp and right-pad with zeros */
pkey := rpad((id || '.' || EXTRACT(EPOCH FROM ts)),30,'0');
/* Return the key as a varchar
return pkey;
end;