IF EXISTS and IF NOT EXISTS are clauses allowing to return a notice message instead of an error if a DDL query running on a given object already exists or not depending on the DDL action done. If a given query tries to create an object when IF NOT EXISTS is specified, a notice message is returned to client if the object has already been created and nothing is done on server side. If the object is altered or dropped when IF EXISTS is used, a notice message is returned back to client if the object does not exist and nothing is done.

Here is what simply happens when a table that exists is created:
postgres=# CREATE TABLE IF NOT EXISTS aa (a int);
CREATE TABLE
postgres=# CREATE TABLE IF NOT EXISTS aa (a int);
NOTICE: relation "aa" already exists, skipping
CREATE TABLE

Similarly, when dropping this table based on its existence.
postgres=# DROP TABLE IF EXISTS aa;
DROP TABLE
postgres=# DROP TABLE IF EXISTS aa;
NOTICE: table "aa" does not exist, skipping
DROP TABLE

Prior to 9.3, PostgreSQL already proposed this feature with many objects: tables, index, functions, triggers, language, etc. Such SQL extensions are useful when running several times the same script several times and avoiding errors on environments already installed.

9.3 introduces some new flavors of IF [NOT] EXISTS completing a bit more the set of objects already supported.

  • CREATE SCHEMA [IF NOT EXISTS]
  • ALTER TYPE ADD VALUE [IF NOT EXISTS]
  • Extension of DROP TABLE IF EXISTS such as it succeeds if the specified schema does not exists

Note also that the new materialized views are also supported with IF [NOT] EXISTS for CREATE, ALTER and DROP.

The extension of CREATE SCHEMA with IF NOT EXISTS is pretty simple. Similarly to the other objects, command succeeds if the schema already exists and a notice message about the existence of schema is sent back to client.
postgres=# CREATE SCHEMA foo;
ERROR: schema "foo" already exists
postgres=# CREATE SCHEMA IF NOT EXISTS foo;
NOTICE: schema "foo" already exists, skipping
CREATE SCHEMA

Note that subsequent schema elements cannot be used with this option.
postgres=# CREATE SCHEMA IF NOT EXISTS foo CREATE TABLE aa (a int);
ERROR: CREATE SCHEMA IF NOT EXISTS cannot include schema elements
LINE 1: CREATE SCHEMA IF NOT EXISTS foo CREATE TABLE aa (a int);

The second addition, ALTER TYPE ADD VALUE [IF NOT EXISTS] is useful in the case of enumeration types to condition the addition of new values.
postgres=# CREATE TYPE character_type AS ENUM ('warrior', 'priest', 'sorcerer');
CREATE TYPE
postgres=# ALTER TYPE character_type ADD VALUE IF NOT EXISTS 'magician';
ALTER TYPE
postgres=# ALTER TYPE character_type ADD VALUE IF NOT EXISTS 'magician';
NOTICE: enum label "magician" already exists, skipping
ALTER TYPE

The last improvement is also a nice thing to have. Here is what you could obtain prior to 9.3 when trying to use DROP TABLE IF EXISTS on a table using a schema that did not exist.
postgres=# DROP TABLE IF EXISTS foosch.foo;
ERROR: schema "foosch" does not exist

And here is what you get now:
postgres=# DROP TABLE IF EXISTS foosch.foo;
NOTICE: table "foo" does not exist, skipping
DROP TABLE

Those are definitely nice additions, especially the new extension of IF NOT EXISTS on schemas which was really missing in the existing set.

Collation is a new functionality of PostgreSQL 9.1 that allows to specify the sort order by table column or for an operation.

In Ubuntu, the collation types supported by your system are listed in /var/lib/locales/supported.d.
In case you installed support for language French, you can have a look at all the languages supported in the file fr.
$ cat /var/lib/locales/supported.d/fr
fr_LU.UTF-8 UTF-8
fr_CA.UTF-8 UTF-8
fr_CH.UTF-8 UTF-8
fr_BE.UTF-8 UTF-8
fr_FR.UTF-8 UTF-8

So here, this system supports French from Luxembourg, Belgium, France, Canada and Switzerland.

Here is an easy example of a table suing collated columns. First a local collation based on French is created. Then table is created and filled with data.
postgres=# create collation fr_FR (locale = 'fr_FR.utf8');
CREATE COLLATION
postgres=# create table test(french_name text collate "fr_FR", eng_name text collate "en_US");
CREATE TABLE
postgres=# insert into test values ('lé', 'la');
INSERT 0 1
postgres=# insert into test values ('là', 'le');
INSERT 0 1
postgres=# insert into test values ('lè', 'li');
INSERT 0 1
postgres=# insert into test values ('lë', 'lo');
INSERT 0 1
postgres=# insert into test values ('lê', 'lu');
INSERT 0 1
postgres=# \d test
Table "public.test"
Column | Type | Modifiers
-------------+------+---------------
french_name | text | collate fr_FR
eng_name | text | collate en_US

So column 1 is collated in French, column 2 in English.

What happens in the case of a order by?
postgres=# select * from test order by 1;
french_name | eng_name
-------------+----------
là | le
lé | la
lè | li
lê | lu
lë | lo
(5 rows)

In this case the strings are classified in French.

postgres=# select * from test order by 2;
french_name | eng_name
-------------+----------
lé | la
là | le
lè | li
lë | lo
lê | lu
(5 rows)

Here the American English order is used.

However collation is very useful when doing string comparisons in different languages. Of course you cannot compare columns that have different collations.
postgres=# select * from test where french_name < eng_name;
ERROR: could not determine which collation to use for string comparison
HINT: Use the COLLATE clause to set the collation explicitly.

But you can enforce the order by the another collation in a kind of cast style.
postgres=# select * from test where french_name < (eng_name collate fr_FR);
french_name | eng_name
-------------+----------
là | le
lè | li
lë | lo
lê | lu
(4 rows)

You can do a lot of things with such features, just never forget that an ORDER BY always needs a collation or you will get an error.
postgres=# select * from test order by french_name || eng_name;
ERROR: collation mismatch between implicit collations "fr_FR" and "en_US"
LINE 1: select * from test order by french_name || eng_name;
postgres=# select * from test order by french_name || eng_name collate fr_FR;
french_name | eng_name
-------------+----------
là | le
lé | la
lè | li
lë | lo
lê | lu
(5 rows)

©2010-2013 Michael Paquier All content is ©Copyright of Otacoo.com 2010-2013. Privacy Policy - Terms of Use