Generating a UUID in Postgres for Insert statement? - postgresql

My question is rather simple. I'm aware of the concept of a UUID and I want to generate one to refer to each 'item' from a 'store' in my DB with. Seems reasonable right?
The problem is the following line returns an error:
honeydb=# insert into items values(
uuid_generate_v4(), 54.321, 31, 'desc 1', 31.94);
ERROR: function uuid_generate_v4() does not exist
LINE 2: uuid_generate_v4(), 54.321, 31, 'desc 1', 31.94);
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
I've read the page at: http://www.postgresql.org/docs/current/static/uuid-ossp.html
I'm running Postgres 8.4 on Ubuntu 10.04 x64.

uuid-ossp is a contrib module, so it isn't loaded into the server by default. You must load it into your database to use it.
For modern PostgreSQL versions (9.1 and newer) that's easy:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
but for 9.0 and below you must instead run the SQL script to load the extension. See the documentation for contrib modules in 8.4.
For Pg 9.1 and newer instead read the current contrib docs and CREATE EXTENSION. These features do not exist in 9.0 or older versions, like your 8.4.
If you're using a packaged version of PostgreSQL you might need to install a separate package containing the contrib modules and extensions. Search your package manager database for 'postgres' and 'contrib'.

Without extensions (cheat)
If you need a valid v4 UUID
SELECT uuid_in(overlay(overlay(md5(random()::text || ':' || random()::text) placing '4' from 13) placing to_hex(floor(random()*(11-8+1) + 8)::int)::text from 17)::cstring);
Thanks to #Denis Stafichuk #Karsten and #autronix
Or you can simply get UUID-like value by doing this (if you don't care about the validity):
SELECT uuid_in(md5(random()::text || random()::text)::cstring);
output>> c2d29867-3d0b-d497-9191-18a9d8ee7830
(works at least in 8.4)

PostgreSQL 13 supports natively gen_random_uuid ():
PostgreSQL includes one function to generate a UUID:
gen_random_uuid () → uuid
This function returns a version 4 (random) UUID. This is the most commonly used type of UUID and is appropriate for most applications.
db<>fiddle demo

The answer by Craig Ringer is correct. Here's a little more info for Postgres 9.1 and later…
Is Extension Available?
You can only install an extension if it has already been built for your Postgres installation (your cluster in Postgres lingo). For example, I found the uuid-ossp extension included as part of the installer for Mac OS X kindly provided by EnterpriseDB.com. Any of a few dozen extensions may be available.
To see if the uuid-ossp extension is available in your Postgres cluster, run this SQL to query the pg_available_extensions system catalog:
SELECT * FROM pg_available_extensions;
Install Extension
To install that UUID-related extension, use the CREATE EXTENSION command as seen in this this SQL:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
Beware: I found the QUOTATION MARK characters around extension name to be required, despite documentation to the contrary.
The SQL standards committee or Postgres team chose an odd name for that command. To my mind, they should have chosen something like "INSTALL EXTENSION" or "USE EXTENSION".
Verify Installation
You can verify the extension was successfully installed in the desired database by running this SQL to query the pg_extension system catalog:
SELECT * FROM pg_extension;
UUID as default value
For more info, see the Question: Default value for UUID column in Postgres
The Old Way
The information above uses the new Extensions feature added to Postgres 9.1. In previous versions, we had to find and run a script in a .sql file. The Extensions feature was added to make installation easier, trading a bit more work for the creator of an extension for less work on the part of the user/consumer of the extension. See my blog post for more discussion.
Types of UUIDs
By the way, the code in the Question calls the function uuid_generate_v4(). This generates a type known as Version 4 where nearly all of the 128 bits are randomly generated. While this is fine for limited use on smaller set of rows, if you want to virtually eliminate any possibility of collision, use another "version" of UUID.
For example, the original Version 1 combines the MAC address of the host computer with the current date-time and an arbitrary number, the chance of collisions is practically nil.
For more discussion, see my Answer on related Question.

pgcrypto Extension
As of Postgres 9.4, the pgcrypto module includes the gen_random_uuid() function. This function generates one of the random-number based Version 4 type of UUID.
Get contrib modules, if not already available.
sudo apt-get install postgresql-contrib-9.4
Use pgcrypto module.
CREATE EXTENSION "pgcrypto";
The gen_random_uuid() function should now available;
Example usage.
INSERT INTO items VALUES( gen_random_uuid(), 54.321, 31, 'desc 1', 31.94 ) ;
Quote from Postgres doc on uuid-ossp module.
Note: If you only need randomly-generated (version 4) UUIDs, consider using the gen_random_uuid() function from the pgcrypto module instead.

Update from 2021,
There is no need for a fancy trick to auto generate uuid on insert statement.
Just do one thing:
Set default value of DEFAULT gen_random_uuid () to your uuid column.
That is all.
Say, you have a table like this:
CREATE TABLE table_name (
unique_id UUID DEFAULT gen_random_uuid (),
first_name VARCHAR NOT NULL,
last_name VARCHAR NOT NULL,
email VARCHAR NOT NULL,
phone VARCHAR,
PRIMARY KEY (unique_id)
);
Now you need NOT to do anything to auto insert uuid values to unique_id column. Because you already defined a default value for it. You can simply focus on inserting onto other columns, and postgresql takes care of your unique_id. Here is a sample insert statement:
INSERT INTO table_name (first_name, last_name, email, phone)
VALUES (
'Beki',
'Otaev',
'beki#bekhruz.com',
'123-456-123'
)
Notice there is no inserting into unique_id as it is already taken care of.
About other extensions like uuid-ossp, you can bring them on if you are not satisfied with postgres's standard gen_random_uuid () function. Most of the time, you should be fine without them on

ALTER TABLE table_name ALTER COLUMN id SET DEFAULT uuid_in((md5((random())::text))::cstring);
After reading #ZuzEL's answer, i used the above code as the default value of the column id and it's working fine.

The uuid-ossp module provides functions to generate universally unique identifiers (UUIDs)
uuid_generate_v1() This function generates a version 1 UUID.
Add Extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
Verify Extension
SELECT * FROM pg_extension;
Run Query
INSERT INTO table_name(id, column1, column2 , column3, ...) VALUES
(uuid_generate_v1(), value1, value2, value3...);
Verify table data

SELECT uuid_generate_v5(uuid_ns_url (), 'test');

Related

Postgresql14.5 Data Masking With PostgreSQL Anonymizer 1.0

I'm trying to understand data masking in Postgresql and implement it to my database. Firstly i tried on windows and mac but it is unsucessfull. On PostgreSQL Anonymizer 1.0, they said they will not support windows and osx platform. This extension seems like works great on Read Hat and Centos. So i created a virual machine with using Vmware and installed Centos Stream 9. I installed Pgadmin4 and postgresql 14.5... I also installed PostgreSQL Anonymizer 1.0. I activated anon extension successfully on Centos and i am able to use static masking correctly. But it removes data.I need role based data masking like dynamic masking. But when i try to use Dynaming Masking with roles,it is not working. I need to protect personel informations from everyone. I read too many articles but they wont work.Please help me.Thanks.
-Firstly i created 2 roles
CREATE ROLE admin1 LOGIN SUPERUSER;
CREATE ROLE maskedRole1 LOGIN;
-Than,i created Posgresql db which is named testdb with this command on Pgadmin
CREATE DATABASE testdb OWNER admin1;
-Than i activated installed anon extension
ALTER DATABASE testdb SET session_preload_libraries = 'anon';
Than i created a table
CREATE TABLE customer (
      id SERIAL PRIMARY KEY,
      firstname TEXT,
      lastname TEXT,
      phone TEXT,
      birth DATE,
      postcode TEXT
);
Than i add some datas to customer table
INSERT INTO customer(firstname,lastname,phone,birth,postcode) VALUES('Burak','Unal','060-911-0911', '1985-10-10', '90016');
INSERT INTO customer(firstname,lastname,phone,birth,postcode) VALUES ('Şerif','Aydın', NULL, '1981-09-25', '90120');
INSERT INTO customer(firstname,lastname,phone,birth,postcode) VALUES ('Talha','Ersoy','347-515-3423', '1996-04-03', '04520');
INSERT INTO customer(firstname,lastname,phone,birth,postcode) VALUES ('Mehmet','Altunel','347-515-3423', '1995-06-01', '04520');
Than i activated extensions.(anon extension needs pgcrypto is installed)
`CREATE EXTENSION IF NOT EXISTS pgcrypto CASCADE;`
`CREATE EXTENSION IF NOT EXISTS anon CASCADE;`
Than i executed these commands to init extensions.
`SELECT anon.init();`
`SELECT setseed(0);`
Than i activated dynamic masking
SELECT anon.start_dynamic_masking();
Than i made maskedRole1 to masked
SECURITY LABEL FOR anon ON ROLE maskedRole1 IS 'MASKED';
Than i gave select permission to maskedRole1
GRANT SELECT ON supplier TO maskedRole1;
Than i wanted to mask customers phone V1
SECURITY LABEL FOR anon ON COLUMN customer.phone IS 'MASKED WITH VALUE ''CONFIDENTIAL'' '; ($$CONFIDENTIAL$$ is same result)
Note: I found comment on instead of SECURITY LABEL FOR but result is same...Unsuccesfull...masking customers phone V2
comment on column company.name IS 'MASKED WITH VALUE ''CONFIDENTIAL'' '
Now i expect maskedRole1 cant see phone numbers but it is epic fail...Everything is open to see.
set role maskedRole1; select * from company;
I wasted my 1 week to handle this. Read many articles,documantations but nothing changed... Any advice please? I'm completely open any other extensions or solutions

How to automatically generate new UUID in PostgreSQL?

I'm using PostgreSQL version 14.4. I installed the uuid-ossp extension.
I created a table like this:
CREATE TABLE reserved_words
ADD id uuid NOT NULL DEFAULT uuid_generate_v1()
ADD word NOT NULL varchar(20);
Unfortunately, when I try adding a new record, rather than a new UUID being generated, instead the "uuid_generate_v1()" string is added in as the id!
I've scoured the Internet but can't find out how to alter things so that the function itself is executed. Any ideas?
My apologies, it actually does work. What's happening is that in DBeaver, the DB client I user, it does at first show the UUID generation function but then when you save the new record, it creates the UUID correctly.
Note: I don't really understand the difference between uuid_generate_v1 and uuid_generate_v4 but am going to opt to use the latter one.
uuid_generate_v1 () → uuid
Generates a version 1 UUID. This involves the MAC address of the computer and a time stamp. Note that UUIDs of this kind reveal the identity of the computer that created the identifier and the time at which it did so, which might make it unsuitable for certain security-sensitive applications.
uuid_generate_v4 () → uuid
Generates a version 4 UUID, which is derived entirely from random numbers.
source
The foremost point is that data type should be of uuid
The 'uuid-ossp' extension offers functions to generate UUID values.
To add the extension to the database run the following command
CREATE EXTENSION "uuid-ossp";
you can use the core function gen_random_uuid() to generate version-4 UUIDs.
To make use of this function in dbeaver ,follow the steps:
1.Go to table in which you want to generate UUID's
2.In the table properties tab find the column to which you need to apply the
uuid function
3.Double click on the column name and it will show expanded view of it's
properties
4.Under default value of that particular column properties, write the
function name as shown in the image
gen_random_uuid()
Dbeaver illustration

Postgres complains about geometry type doesn't exist during docker startup, then decides it exists later

I'm trying to use a PostGIS geometry column with a docker build.
When docker starts up the container I get the following logs (abbreviated for clarity):
Loading PostGIS extensions into template_postgis
CREATE EXTENSION
CREATE EXTENSION
CREATE EXTENSION
CREATE EXTENSION
Loading PostGIS extensions into postgres
CREATE EXTENSION
CREATE EXTENSION
CREATE EXTENSION
CREATE EXTENSION
/usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/script.sql
where script.sql contains the following:
CREATE TABLE public.spatial_data_wfs (
id int4 NOT NULL,
name varchar(255) NOT NULL,
featureid varchar(255) NOT NULL,
geofeature jsonb NOT NULL,
coordinates geometry NOT NULL
);
Despite loading the PostGIS extensions before the script, it gives the following error:
psql:/docker-entrypoint-initdb.d/script.sql:238: ERROR: type "geometry" does not exist
LINE 6: coordinates geometry NOT NULL,
If I remove the geometry column and wait for the container to start up, I can use an alter table statement to add the geometry column, and it works fine.
The script also defines a function that generates a polygon, which doesn't pose any problem. I have tried the following based on other SO questions:
Create the postgis extension: complains it has already been created.
Use ALTER DATABASE to SET search_path TO include postgis. No complaint, same problem.
I can only assume the following from the logs:
There is some order of operations problem where despite the fact that postgis is installed, I still can't use a geometry column because something else has to complete first. Whatever it is, it has completed by the time postgres accepts connections.
The function is only validated for syntax - the fact the function code refers to the geometry type in the function body doesn't matter until someone calls it.
Has anyone else seen this? We're expecting all our stuff to build using Docker and Jenkins.
I figured out the problem. The database script was originally created by some tool (I think it might be pgdump) and then manual changes were added. The tool that adds a bunch of statements to the beginning of the script that aren't really necessary. One of those statements is the following:
SELECT pg_catalog.set_config('search_path', '', false);
I guess this setting overrides "ALTER DATABASE to SET search_path". Once I removed that statement, the script works fine, and the table is created.

Can any one explain me Dblink query format

I need to retrieve data from tables which is located in two different database
so need to use dblink , but not able to understand its format
dblink(???) as(??)
Do you mean you're on one database and you want to query another?
First of all you'll need to make sure that postgresql-contrib is installed
in my case
dnf install postgresql-contrib-9.4.6-1.fc23.x86_64
Then you need to create the extension in postgresql to use dblink.
create extension dblink;
Here's is a simple example
SELECT * FROM dblink('dbname=Test','SELECT date1, int2 FROM test1') AS test(date1 date, int2 integer);
I've tested this and it works fine.
All the best
Ref Postgresql dblink

Unable to use crosstab in Postgres

Postgres 9.2.1 on OSX 10.9.2.
If I run the following crosstab example query:
CREATE EXTENSION tablefunc;
CREATE TABLE ct(id SERIAL, rowid TEXT, attribute TEXT, value TEXT);
INSERT INTO ct(rowid, attribute, value) VALUES('test1','att1','val1');
SELECT *
FROM crosstab(
'select rowid, attribute, value
from ct
where attribute = ''att2'' or attribute = ''att3''
order by 1,2')
AS ct(row_name text, category_1 text, category_2 text, category_3 text);
I get: ERROR: extension "tablefunc" already exists
But if I comment out CREATE EXTENSION
I get: ERROR: function crosstab(unknown) does not exist
How can I get out of this vicious circle? Is it a known issue?
You can change the first line into:
CREATE EXTENSION IF NOT EXISTS tablefunc;
the problem in my case was that the 'tablefunc' extension was defined on one specific schema in my DB, and not accessible to all schemas in it.
[edit: as explained above, 'not accessible to all schemas' should read 'cannot be loaded on all schemas']
I learned that:
the Extension can only be loaded into one schema - so load it into 'public'
you have to manually drop the extension from one schema before you can load it in another
you can list the loaded extensions per schema in pqsl using the command: \df *.crosstab
[edit: 4. you can access the extension either by search_path, by loading it on public schema or by explicitly specifying a schema]
There's a misconception in your answer:
and not accessible to all schemas in it.
All schemas inside the same database are accessible to all sessions in that same database, (as long as privileges are given). It's a matter of setting the search_path. Schemas work much like directories / folders in the file system.
Alternatively, you can schema-qualify the function (and even operators) to access it independently of the search_path:
SELECT *
FROM my_extension_schema.crosstab(
$$select rowid, attribute, "value"
from ct
where attribute IN ('att2', 'att3')
order by 1,2$$
,$$VALUES ('att2'), ('att3')$$
) AS ct(row_name text, category_2 text, category_3 text);
More:
How to use % operator from the extension pg_trgm?
Dubious crosstab()
Your query returned attributes 'att2' and 'att3', but the column definition list had three categories (category_1, category_2, category_3) that do not match the query.
I removed category_1 and added the second parameter to crosstab() - the "safe" version. More details here:
PostgreSQL Crosstab Query
Aside:
Don't use value as column name, even if Postgres allows it. It's a reserved word in standard SQL.