Equivalent to UNIQUE IDENTIFIER in PostgreSQL - postgresql

I was tryiong to switch from MSSQL to PostgreSQL and hence trying to convert queries to PostgreSQL equivalent. However running PostgreSQL query is giving an error:
ERROR: type "uniqueidentifier" does not exist LINE 3: ID
UNIQUEIDENTIFIER DEFAULT UUID_GENERATE_V4()::VARCHAR NO...
^ SQL state: 42704 Character: 38
MSSQL
CREATE TABLE [dbo].[ISS_AUDIT]
(
[ID] UNIQUEIDENTIFIER DEFAULT NEWID() NOT NULL,
[GRAPH_ID] [varchar](196)
PRIMARY KEY(ID)
);
PostgreSQL
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE public.ISS_AUDIT
(
ID UNIQUEIDENTIFIER DEFAULT UUID_GENERATE_V4()::VARCHAR NOT NULL,
GRAPH_ID VARCHAR(196),
PRIMARY KEY(ID)
);
Am I missing something on UNIQUEIDENTIFIER ?

This is the correct script:
CREATE TABLE public.ISS_AUDIT
(
ID uuid PRIMARY KEY DEFAULT UUID_GENERATE_V4(),
GRAPH_ID VARCHAR(196)
);
See this link. Extract:
SQL Server calls the type UniqueIdentifier and PostgreSQL calls the
type uuid. Both types occupy 16-bytes of storage. For compatibility
reasons with other software or databases, many use some stanardized
text representation of them particularly for transport rather than
using the native type.

We need UUID which can be used as below:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE public.ISS_AUDIT(
ID UUID DEFAULT UUID_GENERATE_V4()::UUID NOT NULL,
GRAPH_ID VARCHAR(196),
PRIMARY KEY(ID)
);

Related

PSQL throwing error: relation "serial" does not exist, when creating a table

It happens when i run this code:
CREATE TABLE distributors (
did integer PRIMARY KEY DEFAULT nextval('serial'),
name varchar(40) NOT NULL CHECK (name <> '')
);
I have tried remover the nextval('serial') but to no avail
You want to do this:
CREATE TABLE distributors (
did serial PRIMARY KEY DEFAULT,
name varchar(40) NOT NULL CHECK (name <> '')
);
The serial type is actually a macro. That per docs (Serial) does:
CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
Assuming you are on a recent version(10+) of Postgres generated always as identity(see Create Table) is the preferred alternative these days.
nextval('someseries') relies on having an existing series. You can create that with:
CREATE SEQUENCE someseries;
When you removed the nextval, you probably still had the DEFAULT keyword there, which expects a value afterward to define what the default for the column is.

Why SERIAL is not working on this simple table in Postgres?

I'm using Postgres 9.1. and the auto_increment (serial) is not working. I've just found this about 'serial':
https://www.postgresql.org/docs/current/static/datatype-numeric.html#DATATYPE-SERIAL
CREATE TYPE FAMILY AS(
id int,
name VARCHAR(35),
img_address VARCHAR(150));
CREATE TABLE FAMILIES of FAMILY(
id SERIAL primary key NOT NULL,
name NOT NULL
);
ERROR: syntax error at or near "SERIAL"
LINE 7: id SERIAL primary key NOT NULL,
^
********** Error **********
ERROR: syntax error at or near "SERIAL"
SQL state: 42601
When you create a table using the syntax:
CREATE TABLE xxx OF yyyy
you can add default values and constraints, but not alter or specify the type of the columns.
The type SERIAL is in effect a combination of a data type, NOT NULL constraint and default value specification. It is equivalent to:
integer NOT NULL DEFAULT nextval('tablename_colname_seq')
See: documentation for SERIAL
So, instead you would have to use:
CREATE SEQUENCE families_id_seq;
CREATE TABLE FAMILIES of FAMILY(
id WITH OPTIONS NOT NULL DEFAULT nextval('families_id_seq'),
name WITH OPTIONS NOT NULL
);
ALTER SEQUENCE families_id_seq OWNED BY FAMILIES.id;
You would have to create the sequence families_id_seq manually as well, as shown above.

PostgreSQL bigserial & nextval

I've got a PgSQL 9.4.3 server setup and previously I was only using the public schema and for example I created a table like this:
CREATE TABLE ma_accessed_by_members_tracking (
reference bigserial NOT NULL,
ma_reference bigint NOT NULL,
membership_reference bigint NOT NULL,
date_accessed timestamp without time zone,
points_awarded bigint NOT NULL
);
Using the Windows Program PgAdmin III I can see it created the proper information and sequence.
However I've recently added another schema called "test" to the same database and created the exact same table, just like before.
However this time I see:
CREATE TABLE test.ma_accessed_by_members_tracking
(
reference bigint NOT NULL DEFAULT nextval('ma_accessed_by_members_tracking_reference_seq'::regclass),
ma_reference bigint NOT NULL,
membership_reference bigint NOT NULL,
date_accessed timestamp without time zone,
points_awarded bigint NOT NULL
);
My question / curiosity is why in a public schema the reference shows bigserial but in the test schema reference shows bigint with a nextval?
Both work as expected. I just do not understand why the difference in schema's would show different table creations. I realize that bigint and bigserial allow the same volume of ints to be used.
Merely A Notational Convenience
According to the documentation on Serial Types, smallserial, serial, and bigserial are not true data types. Rather, they are a notation to create at once both sequence and column with default value pointing to that sequence.
I created test table on schema public. The command psql \d shows bigint column type. Maybe it's PgAdmin behavior ?
Update
I checked PgAdmin source code. In function pgColumn::GetDefinition() it scans table pg_depend for auto dependency and when found it - replaces bigint with bigserial to simulate original table create code.
When you create a serial column in the standard way:
CREATE TABLE new_table (
new_id serial);
Postgres creates a sequence with commands:
CREATE SEQUENCE new_table_new_id_seq ...
ALTER SEQUENCE new_table_new_id_seq OWNED BY new_table.new_id;
From documentation: The OWNED BY option causes the sequence to be associated with a specific table column, such that if that column (or its whole table) is dropped, the sequence will be automatically dropped as well.
Standard name of a sequence is built from table name, column name and suffix _seq.
If a serial column was created in such a way, PgAdmin shows its type as serial.
If a sequence has non-standard name or is not associated with a column, PgAdmin shows nextval() as default value.

Postgresql User Defined Type in primary key constraint

I'm using postgresql 9.1 on Ubuntu 12.04. I have a user defined type as one column of a table. When I create a primary key constraint I get a syntax error.
Here is a sample sql script I'm using with psql to create the table:
CREATE TYPE my_type AS
(
field1 integer,
field2 integer
);
CREATE TABLE my_table
(
my_data my_type,
other_data integer
);
ALTER TABLE my_table ADD CONSTRAINT pk_my_table PRIMARY KEY (my_data.field1);
I get this error:
ERROR: syntax error at or near "."
LINE 1: ...ble ADD CONSTRAINT pk_my_table PRIMARY KEY (my_data.field1);
I've tried using (my_data).field1 but also get a syntax error.
If I just use my_data in the constraint there is no error:
ALTER TABLE my_table ADD CONSTRAINT pk_my_table PRIMARY KEY (my_data);
But I would like to use just one field as part of the constraint.
Thanks for any ideas.
I found this question using google and I'm pretty sure is dead but I still want to answer it cause someone else might see it.
Short answer is you have to use the field's name:
ALTER TABLE "public"."carga" ADD CONSTRAINT "pk_my_table" PRIMARY KEY ("field1");

PostgreSQL: NULL value in foreign key column

In my PostgreSQL database I have the following tables (simplified):
CREATE TABLE quotations (
receipt_id bigint NOT NULL PRIMARY KEY
);
CREATE TABLE order_confirmations (
receipt_id bigint NOT NULL PRIMARY KEY
fk_quotation_receipt_id bigint REFERENCES quotations (receipt_id)
);
My problem now reads as follows:
I have orders which relate to previous quotations (which is fine 'cause I can attach such an order to the quotation referenced by using the FK field), but I also have placed-from-scratch orders without a matching quotation. The FK field would then be NULL, if the database let me, of course. Unfortunately, I get an error when trying to set fk_quotation_receipt_id to NULL in an INSERT statement because of a violated foreign key constraint.
When designing these tables I was still using PgSQL 8.2, which allowed NULL values. Now I've got 9.1.6, which does not allow for this.
What I wish is an optional (or nullable) foreign key constraint order_confirmations (fk_quotation_receipt_id) → quotations (receipt_id). I can't find any hints in the official PgSQL docs, and similar issues posted by other users are already quite old.
Thank you for any useful hints.
Works for me in 9.3 after correcting a missing comma. I'm sure it will work also in 9.1
create table quotations (
receipt_id bigint not null primary key
);
create table order_confirmations (
receipt_id bigint not null primary key,
fk_quotation_receipt_id bigint references quotations (receipt_id)
);
insert into order_confirmations (receipt_id, fk_quotation_receipt_id) values
(1, null);
Confirmation will include:
INSERT 0 1