SlideShare a Scribd company logo
Syntactic sugar in PostgreSQL
by Anton Abramchenko
Serial Data Type & Sequence
-- Create autoincrement
CREATE SEQUENCE example_seq
START WITH 3
INCREMENT BY 3
MINVALUE 3
NO MAXVALUE;
-- After table creation, the sequence entity_id_seq will be created
CREATE TABLE entity (
id SERIAL PRIMARY KEY,
value VARCHAR(255)
);
-- Check available sequences
SELECT * FROM pg_statio_user_sequences;
Sequence Control
-- Set next increment as current and return it
SELECT nextval('entity_id_seq'); -- 1
SELECT nextval('entity_id_seq'); -- 2
SELECT nextval('entity_id_seq'); -- 3
INSERT INTO entity(value) VALUES ('some foo') RETURNING id; -- 4
-- Update sequence and return updated value;
SELECT nextval('entity_id_seq');
-- Get current value
SELECT currval('entity_id_seq');
-- Get last inserted value
SELECT lastval();
-- Update sequence value
SELECT setval('entity_id_seq', 99);
One Sequence for Two Tables
CREATE SEQUENCE multi_entity_seq;
CREATE TABLE multi_entity_a(
id INTEGER DEFAULT nextval('multi_entity_seq') PRIMARY KEY,
value VARCHAR(255)
);
CREATE TABLE multi_entity_b(
id INTEGER DEFAULT nextval('multi_entity_seq') PRIMARY KEY,
value VARCHAR(255)
);
INSERT INTO multi_entity_a (value) VALUES ('some value of ' || currval('multi_entity_seq'))
RETURNING id; -- 1
INSERT INTO multi_entity_a (value) VALUES ('some value of ' || currval('multi_entity_seq'))
RETURNING id; -- 2
Reset Sequence
-- Truncate operation does not update the sequence
TRUNCATE TABLE entity;
-- Reset sequence
TRUNCATE TABLE entity RESTART IDENTITY;
-- Alter reset sequence
ALTER SEQUENCE entity_id_seq RESTART;
-- or
SELECT setval('entity_id_seq', 1, false);
Array Data Type
CREATE TABLE book (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
tags VARCHAR(255) [],
authors INT []
);
INSERT INTO book (title, tags, authors)
VALUES ( 'PostgreSQL 9.6 High Performance', '{PostgreSQL,9.6,High,Performance}', '{1, 2}'),
( 'Mastering PostgreSQL 9.6', '{PostgreSQL,9.6,Mastering}', '{10,12,3}'),
('PostgreSQL Administration Cookbook', 'Some info', '{9.5,Administration}', '{29,41,36}'),
( 'PostgreSQL High Performance Cookbook', '{PostgreSQL,High,Performance}','{18,35}');
Array Functions and Operands
-- in array
SELECT * FROM book WHERE '9.6' = ANY (tags);
-- not in array
SELECT * FROM book WHERE id != ALL (SELECT eq FROM (VALUES (1), (2)) AS t(eq));
-- select all rows with ‘high’ or 9.5 version
SELECT * FROM book WHERE '{9.5,High}' && tags;
-- select all rows with ‘high’ and 9.6 version
SELECT * FROM book WHERE '{9.6,High}' <@ tags;
-- Get books where title is like one of array title values
SELECT * FROM book WHERE book.title ~~* ANY (ARRAY ['%Perfor%', '%Admin%']);
-- Array to string conversion
SELECT array_to_string(tags, ',') FROM book;
-- Array to json conversion
SELECT array_to_json(tags) FROM book;
Extension hStore
CREATE EXTENSION hstore;
CREATE TABLE product (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT,
price DECIMAL(12, 2) NOT NULL,
attributes HSTORE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'UTC'),
updated_at TIMESTAMP
);
Adding data to hStore
INSERT INTO product (title, description, price, attributes)
VALUES ('Product A', 'Description', 35.00, 'color => red, weight => 1000, sku => LPT123'),
('Product B', 'Description', 70.00, 'color => blue, weight => 2500, sku => LPT145'),
('Product C', 'Description', 100.00, 'color => withe, weight => 1500, sku => LPT245,
is_something => true'),
('Product D', 'Description', 85.00,
'color => withe, weight => 3500, sku => LPT125, is_something => false, hidden => true'),
('Product E', 'Description', 10.00, 'color => red, weight => 1500, sku => LPT37')
RETURNING *;
Retrieving data from hStore
SELECT
title,
price :: MONEY,
attributes -> 'color' AS color,
attributes -> 'weight' AS weight,
attributes -> 'sku' AS sku
FROM product
WHERE (attributes -> 'weight') :: INT > 1500
ORDER BY replace(attributes -> 'sku', 'LPT', ' ');
hStore Data Manipulation
-- hstore key exists
SELECT * FROM product WHERE attributes ? 'is_something';
-- hstore contains all specified keys
SELECT * FROM product WHERE attributes ?& string_to_array('is_something,hidden', ',');
-- hstore to data records
SELECT
id,
(each(attributes)).key AS attribute,
(each(attributes)).value AS value
FROM product;
Creating XML data
-- Books to xml
CREATE TABLE book_as_xml (
id SERIAL PRIMARY KEY,
content XML NOT NULL
);
-- Transform all books to xml
INSERT INTO book_as_xml (content)
SELECT xmlroot(
xmlelement(NAME book, xmlforest(id, title, authors, tags)),
VERSION '1.1',
STANDALONE YES
) FROM book
RETURNING content;
XML2 - Transform XML to Presentable view
CREATE EXTENSION xml2;
CREATE OR REPLACE FUNCTION xml_pretty(TEXT)
RETURNS XML AS $body$
SELECT xslt_process($1,
'<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*" />
<xsl:output method="xml" indent="yes" />
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>' :: TEXT) :: XML
$body$ LANGUAGE SQL IMMUTABLE STRICT;
XML Manipulation
-- Show pretty xml
SELECT xml_pretty(content) FROM book_as_xml;
-- Xpath
SELECT array_to_string(xpath('//title/text()', content), '; ') FROM book_as_xml;
-- Get all tags values
SELECT array_to_string(xpath('//tags/element/text()', content), '; ') FROM book_as_xml;
-- Return all table content as xml
SELECT xmlroot(
xmlelement(name body, table_to_xml('book', TRUE, TRUE, '')),
VERSION '1.1',
STANDALONE YES
) FROM book;
JSON & JSONB
CREATE TABLE entity_as_jsonb (
id SERIAL PRIMARY KEY,
content JSONB
);
INSERT INTO entity_as_jsonb (type, content)
SELECT json_build_object(
'title', title,
id', id,
'description', description,
'price', price :: MONEY,
'attributes', attributes
) FROM product RETURNING * ;
JSON Data Retrieving
SELECT
content ->> 'id' AS id, -- like text
content ->> 'title' AS title, -- like text
content -> 'attributes' AS attributes, -- like json
content #>> '{attributes,sku}' AS sky -- by path
FROM entity_as_json
WHERE type = 'product' AND content #>> '{attributes,sku}' LIKE '%45';
-- Aggregate all table data
SELECT json_agg(content) FROM entity_as_json;
-- Array to json conversion
SELECT array_to_json(tags) FROM book;
JSON Append Function
CREATE OR REPLACE FUNCTION json_append(data JSON, insert_data JSON)
RETURNS JSON
IMMUTABLE LANGUAGE SQL AS $$
SELECT ('{' || string_agg(to_json(key) || ':' || value, ',') || '}') :: JSON
FROM (
SELECT * FROM json_each(data)
UNION ALL
SELECT * FROM json_each(insert_data)
) t;
$$;
JSON Merge Function
CREATE OR REPLACE FUNCTION json_merge(data JSON, merge_data JSON)
RETURNS JSON
IMMUTABLE LANGUAGE SQL AS $$
SELECT ('{' || string_agg(to_json(key) || ':' || value, ',') || '}') :: JSON
FROM (
WITH to_merge AS (
SELECT * FROM json_each(merge_data)
)
SELECT * FROM json_each(data) WHERE key NOT IN (SELECT key FROM to_merge)
UNION ALL
SELECT * FROM to_merge
) t;
$$;
Check Constraint
CREATE TABLE web_user (
id SERIAL PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL CHECK (trim(username) <> ''),
email VARCHAR(255) UNIQUE NOT NULL CHECK (valid_email(email)),
password CHARACTER(40) NOT NULL CHECK (char_length(password) = 40),
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated TIMESTAMP
);
CREATE EXTENSION pgcrypto;
INSERT INTO web_user VALUES (
'2', 'foo', 'abramchenkoa@bar.com', ENCODE(DIGEST('test', 'sha1'), 'hex')
);
Domain and Citext Extension
CREATE EXTENSION citext;
-- Create data type like email RFC5322
CREATE DOMAIN email AS citext
CHECK ( value ~ '^[a-zA-Z0-9.!#$%&''*+/=?^_`{|}~-]' ||
'+@[a-zA-Z0-9](?:[a-zA-Z0-9-]' ||
'{0,61}[a-zA-Z0-9])?(?:.[a-zA-Z0-9]' ||
'(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$'
);
Write functions on Perl, Python, JS, Ruby, PHP
CREATE EXTENSION plperlu;
CREATE FUNCTION valid_email(text)
RETURNS boolean
LANGUAGE plperlu
IMMUTABLE LEAKPROOF STRICT AS
$$
use Email::Valid;
my $email = shift;
Email::Valid->address($email) or die "Invalid email address: $emailn";
return 'true';
$$;
Full Text Search
-- Add a new column
ALTER TABLE book ADD COLUMN search_fields TSVECTOR;
-- Fill the column for searching
UPDATE book
SET search_fields = to_tsvector(
'english',
book.title || ' ' || array_to_string(book.tags, ' ')
);
-- Add index
CREATE INDEX textsearch_idx ON book USING GIN (search_fields);
Search Queries
-- Get current text search config
SELECT get_current_ts_config(); -- english
-- Show all available text search configs
SELECT * FROM pg_ts_config;
-- Search examples
SELECT * FROM book
WHERE search_fields @@ to_tsquery('high & postgre:* & 9.6');
SELECT * FROM book
WHERE search_fields @@ plainto_tsquery(get_current_ts_config(), 'postgresql performance') ;
-- Displays query matching, how title matches the query
SELECT id, title, ts_headline(title, q) FROM book, to_tsquery('postgre:* & performance') AS q
WHERE setweight(to_tsvector('english', title),'A')
|| setweight(to_tsvector('english', content), 'B') @@ q;
Search By Trigrams
-- Enable extension
CREATE EXTENSION pg_trgm;
-- Add index
CREATE INDEX trgm_idx ON book USING GIST (title gist_trgm_ops);
-- How similar are the arguments
SELECT title, similarity(title, 'Postgre') AS sml
FROM book WHERE title % 'Postgre'
ORDER BY sml DESC;
-- How similar are the first string and the most similar word of the second string
SELECT title, word_similarity(title, 'Postgre') AS sml
FROM book WHERE title %> 'Postgre'
ORDER BY sml DESC;
Ltree Hierarchical Data Type
-- Enable extension
CREATE EXTENSION ltree;
-- Store branch like
CREATE TABLE comment (
id SERIAL PRIMARY KEY,
message TEXT,
branch LTREE NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- Add index
CREATE INDEX ON comment USING GIST (branch);
Ltree Data Manipulation
INSERT INTO comment (message, branch) VALUES ('Comment 1', '0');
INSERT INTO comment (message, branch) VALUES ('Comment 1.1', '0.1');
INSERT INTO comment (message, branch) VALUES ('Comment 2', '0');
INSERT INTO comment (message, branch) VALUES ('Comment 2.1', '0.3');
INSERT INTO comment (message, branch) VALUES ('Comment 2.2', '0.3');
INSERT INTO comment (message, branch) VALUES ('Comment 2.2.1', '0.3.4');
-- Сhildren of the third message
SELECT * FROM comment WHERE branch <@ '0.3';
-- Get by lquery
SELECT * FROM comment WHERE branch ~ '*.3.*'::lquery;
Thank You For Attention!

More Related Content

PPTX
Syntactic sugar in postgre sql
PDF
A Tour to MySQL Commands
PPT
Managing category structures in relational databases
PDF
Python Ireland Nov 2010 Talk: Unit Testing
PDF
dcs plus Catalogue 2015
PPT
Oracle Sql & PLSQL Complete guide
PDF
Database Design Patterns
PDF
The History of PHPersistence
Syntactic sugar in postgre sql
A Tour to MySQL Commands
Managing category structures in relational databases
Python Ireland Nov 2010 Talk: Unit Testing
dcs plus Catalogue 2015
Oracle Sql & PLSQL Complete guide
Database Design Patterns
The History of PHPersistence

What's hot (20)

PDF
Silex meets SOAP & REST
PPTX
Async all around us (promises)
TXT
Sqlcusesprac
PDF
DBD::SQLite
PDF
Mysql Explain Explained
PPTX
Optimizing queries MySQL
PDF
PHP 5.3 and Lithium: the most rad php framework
PDF
The Zen of Lithium
PDF
Store and Process Big Data with Hadoop and Cassandra
PDF
Design Patterns avec PHP 5.3, Symfony et Pimple
PDF
PHP tips and tricks
PDF
Powerful Explain in MySQL 5.6
PDF
Lithium: The Framework for People Who Hate Frameworks
PDF
Table partitioning in PostgreSQL + Rails
PDF
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
PDF
Py spark cheat sheet by cheatsheetmaker.com
PPTX
vFabric SQLFire Introduction
PPT
MYSQL
PDF
Sql (Introduction to Structured Query language)
Silex meets SOAP & REST
Async all around us (promises)
Sqlcusesprac
DBD::SQLite
Mysql Explain Explained
Optimizing queries MySQL
PHP 5.3 and Lithium: the most rad php framework
The Zen of Lithium
Store and Process Big Data with Hadoop and Cassandra
Design Patterns avec PHP 5.3, Symfony et Pimple
PHP tips and tricks
Powerful Explain in MySQL 5.6
Lithium: The Framework for People Who Hate Frameworks
Table partitioning in PostgreSQL + Rails
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Py spark cheat sheet by cheatsheetmaker.com
vFabric SQLFire Introduction
MYSQL
Sql (Introduction to Structured Query language)
Ad

Similar to Syntactic sugar in Postgre SQL (20)

PDF
Stefan Hochdörfer - The NoSQL Store everyone ignores: PostgreSQL - NoSQL matt...
KEY
PostgreSQL
PDF
JDD 2016 - Tomasz Borek - DB for next project? Why, Postgres, of course
PPTX
PostgreSQL - It's kind've a nifty database
PDF
PerlApp2Postgresql (2)
PDF
NoSQL store everyone ignored - Postgres Conf 2021
PDF
Heroku Postgres Cloud Database Webinar
PDF
10 Reasons to Start Your Analytics Project with PostgreSQL
PDF
How to Handle NoSQL with a Relational Database
PDF
The NoSQL store everyone ignored
PDF
Moving to hybrid relational/JSON data models
PDF
Ten Reasons Why You Should Prefer PostgreSQL to MySQL
PDF
20080330 Postgresqlconference2008 Pg In Web2.0 Samokhvalov
PDF
Relational Database Design Bootcamp
PDF
Full Text Search in PostgreSQL
PDF
Полнотекстовый поиск в PostgreSQL / Александр Алексеев (Postgres Professional)
ODP
Meet the-other-elephant
PDF
PostgreSQL 9.0 & The Future
PDF
Using semi-structured data in modern applications
PDF
Mathias test
Stefan Hochdörfer - The NoSQL Store everyone ignores: PostgreSQL - NoSQL matt...
PostgreSQL
JDD 2016 - Tomasz Borek - DB for next project? Why, Postgres, of course
PostgreSQL - It's kind've a nifty database
PerlApp2Postgresql (2)
NoSQL store everyone ignored - Postgres Conf 2021
Heroku Postgres Cloud Database Webinar
10 Reasons to Start Your Analytics Project with PostgreSQL
How to Handle NoSQL with a Relational Database
The NoSQL store everyone ignored
Moving to hybrid relational/JSON data models
Ten Reasons Why You Should Prefer PostgreSQL to MySQL
20080330 Postgresqlconference2008 Pg In Web2.0 Samokhvalov
Relational Database Design Bootcamp
Full Text Search in PostgreSQL
Полнотекстовый поиск в PostgreSQL / Александр Алексеев (Postgres Professional)
Meet the-other-elephant
PostgreSQL 9.0 & The Future
Using semi-structured data in modern applications
Mathias test
Ad

Recently uploaded (20)

PPTX
Welding lecture in detail for understanding
PPTX
Recipes for Real Time Voice AI WebRTC, SLMs and Open Source Software.pptx
PDF
PPT on Performance Review to get promotions
PDF
Evaluating the Democratization of the Turkish Armed Forces from a Normative P...
PDF
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
PDF
The CXO Playbook 2025 – Future-Ready Strategies for C-Suite Leaders Cerebrai...
PPTX
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
PDF
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
PPT
Mechanical Engineering MATERIALS Selection
PDF
Embodied AI: Ushering in the Next Era of Intelligent Systems
PDF
Well-logging-methods_new................
PPTX
IOT PPTs Week 10 Lecture Material.pptx of NPTEL Smart Cities contd
PPTX
Lecture Notes Electrical Wiring System Components
PDF
Model Code of Practice - Construction Work - 21102022 .pdf
PDF
R24 SURVEYING LAB MANUAL for civil enggi
PPTX
Sustainable Sites - Green Building Construction
PPTX
additive manufacturing of ss316l using mig welding
PDF
Digital Logic Computer Design lecture notes
DOCX
ASol_English-Language-Literature-Set-1-27-02-2023-converted.docx
PPTX
FINAL REVIEW FOR COPD DIANOSIS FOR PULMONARY DISEASE.pptx
Welding lecture in detail for understanding
Recipes for Real Time Voice AI WebRTC, SLMs and Open Source Software.pptx
PPT on Performance Review to get promotions
Evaluating the Democratization of the Turkish Armed Forces from a Normative P...
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
The CXO Playbook 2025 – Future-Ready Strategies for C-Suite Leaders Cerebrai...
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
Mechanical Engineering MATERIALS Selection
Embodied AI: Ushering in the Next Era of Intelligent Systems
Well-logging-methods_new................
IOT PPTs Week 10 Lecture Material.pptx of NPTEL Smart Cities contd
Lecture Notes Electrical Wiring System Components
Model Code of Practice - Construction Work - 21102022 .pdf
R24 SURVEYING LAB MANUAL for civil enggi
Sustainable Sites - Green Building Construction
additive manufacturing of ss316l using mig welding
Digital Logic Computer Design lecture notes
ASol_English-Language-Literature-Set-1-27-02-2023-converted.docx
FINAL REVIEW FOR COPD DIANOSIS FOR PULMONARY DISEASE.pptx

Syntactic sugar in Postgre SQL

  • 1. Syntactic sugar in PostgreSQL by Anton Abramchenko
  • 2. Serial Data Type & Sequence -- Create autoincrement CREATE SEQUENCE example_seq START WITH 3 INCREMENT BY 3 MINVALUE 3 NO MAXVALUE; -- After table creation, the sequence entity_id_seq will be created CREATE TABLE entity ( id SERIAL PRIMARY KEY, value VARCHAR(255) ); -- Check available sequences SELECT * FROM pg_statio_user_sequences;
  • 3. Sequence Control -- Set next increment as current and return it SELECT nextval('entity_id_seq'); -- 1 SELECT nextval('entity_id_seq'); -- 2 SELECT nextval('entity_id_seq'); -- 3 INSERT INTO entity(value) VALUES ('some foo') RETURNING id; -- 4 -- Update sequence and return updated value; SELECT nextval('entity_id_seq'); -- Get current value SELECT currval('entity_id_seq'); -- Get last inserted value SELECT lastval(); -- Update sequence value SELECT setval('entity_id_seq', 99);
  • 4. One Sequence for Two Tables CREATE SEQUENCE multi_entity_seq; CREATE TABLE multi_entity_a( id INTEGER DEFAULT nextval('multi_entity_seq') PRIMARY KEY, value VARCHAR(255) ); CREATE TABLE multi_entity_b( id INTEGER DEFAULT nextval('multi_entity_seq') PRIMARY KEY, value VARCHAR(255) ); INSERT INTO multi_entity_a (value) VALUES ('some value of ' || currval('multi_entity_seq')) RETURNING id; -- 1 INSERT INTO multi_entity_a (value) VALUES ('some value of ' || currval('multi_entity_seq')) RETURNING id; -- 2
  • 5. Reset Sequence -- Truncate operation does not update the sequence TRUNCATE TABLE entity; -- Reset sequence TRUNCATE TABLE entity RESTART IDENTITY; -- Alter reset sequence ALTER SEQUENCE entity_id_seq RESTART; -- or SELECT setval('entity_id_seq', 1, false);
  • 6. Array Data Type CREATE TABLE book ( id SERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, tags VARCHAR(255) [], authors INT [] ); INSERT INTO book (title, tags, authors) VALUES ( 'PostgreSQL 9.6 High Performance', '{PostgreSQL,9.6,High,Performance}', '{1, 2}'), ( 'Mastering PostgreSQL 9.6', '{PostgreSQL,9.6,Mastering}', '{10,12,3}'), ('PostgreSQL Administration Cookbook', 'Some info', '{9.5,Administration}', '{29,41,36}'), ( 'PostgreSQL High Performance Cookbook', '{PostgreSQL,High,Performance}','{18,35}');
  • 7. Array Functions and Operands -- in array SELECT * FROM book WHERE '9.6' = ANY (tags); -- not in array SELECT * FROM book WHERE id != ALL (SELECT eq FROM (VALUES (1), (2)) AS t(eq)); -- select all rows with ‘high’ or 9.5 version SELECT * FROM book WHERE '{9.5,High}' && tags; -- select all rows with ‘high’ and 9.6 version SELECT * FROM book WHERE '{9.6,High}' <@ tags; -- Get books where title is like one of array title values SELECT * FROM book WHERE book.title ~~* ANY (ARRAY ['%Perfor%', '%Admin%']); -- Array to string conversion SELECT array_to_string(tags, ',') FROM book; -- Array to json conversion SELECT array_to_json(tags) FROM book;
  • 8. Extension hStore CREATE EXTENSION hstore; CREATE TABLE product ( id SERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, description TEXT, price DECIMAL(12, 2) NOT NULL, attributes HSTORE, created_at TIMESTAMP WITH TIME ZONE DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'UTC'), updated_at TIMESTAMP );
  • 9. Adding data to hStore INSERT INTO product (title, description, price, attributes) VALUES ('Product A', 'Description', 35.00, 'color => red, weight => 1000, sku => LPT123'), ('Product B', 'Description', 70.00, 'color => blue, weight => 2500, sku => LPT145'), ('Product C', 'Description', 100.00, 'color => withe, weight => 1500, sku => LPT245, is_something => true'), ('Product D', 'Description', 85.00, 'color => withe, weight => 3500, sku => LPT125, is_something => false, hidden => true'), ('Product E', 'Description', 10.00, 'color => red, weight => 1500, sku => LPT37') RETURNING *;
  • 10. Retrieving data from hStore SELECT title, price :: MONEY, attributes -> 'color' AS color, attributes -> 'weight' AS weight, attributes -> 'sku' AS sku FROM product WHERE (attributes -> 'weight') :: INT > 1500 ORDER BY replace(attributes -> 'sku', 'LPT', ' ');
  • 11. hStore Data Manipulation -- hstore key exists SELECT * FROM product WHERE attributes ? 'is_something'; -- hstore contains all specified keys SELECT * FROM product WHERE attributes ?& string_to_array('is_something,hidden', ','); -- hstore to data records SELECT id, (each(attributes)).key AS attribute, (each(attributes)).value AS value FROM product;
  • 12. Creating XML data -- Books to xml CREATE TABLE book_as_xml ( id SERIAL PRIMARY KEY, content XML NOT NULL ); -- Transform all books to xml INSERT INTO book_as_xml (content) SELECT xmlroot( xmlelement(NAME book, xmlforest(id, title, authors, tags)), VERSION '1.1', STANDALONE YES ) FROM book RETURNING content;
  • 13. XML2 - Transform XML to Presentable view CREATE EXTENSION xml2; CREATE OR REPLACE FUNCTION xml_pretty(TEXT) RETURNS XML AS $body$ SELECT xslt_process($1, '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:strip-space elements="*" /> <xsl:output method="xml" indent="yes" /> <xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="node() | @*" /> </xsl:copy> </xsl:template> </xsl:stylesheet>' :: TEXT) :: XML $body$ LANGUAGE SQL IMMUTABLE STRICT;
  • 14. XML Manipulation -- Show pretty xml SELECT xml_pretty(content) FROM book_as_xml; -- Xpath SELECT array_to_string(xpath('//title/text()', content), '; ') FROM book_as_xml; -- Get all tags values SELECT array_to_string(xpath('//tags/element/text()', content), '; ') FROM book_as_xml; -- Return all table content as xml SELECT xmlroot( xmlelement(name body, table_to_xml('book', TRUE, TRUE, '')), VERSION '1.1', STANDALONE YES ) FROM book;
  • 15. JSON & JSONB CREATE TABLE entity_as_jsonb ( id SERIAL PRIMARY KEY, content JSONB ); INSERT INTO entity_as_jsonb (type, content) SELECT json_build_object( 'title', title, id', id, 'description', description, 'price', price :: MONEY, 'attributes', attributes ) FROM product RETURNING * ;
  • 16. JSON Data Retrieving SELECT content ->> 'id' AS id, -- like text content ->> 'title' AS title, -- like text content -> 'attributes' AS attributes, -- like json content #>> '{attributes,sku}' AS sky -- by path FROM entity_as_json WHERE type = 'product' AND content #>> '{attributes,sku}' LIKE '%45'; -- Aggregate all table data SELECT json_agg(content) FROM entity_as_json; -- Array to json conversion SELECT array_to_json(tags) FROM book;
  • 17. JSON Append Function CREATE OR REPLACE FUNCTION json_append(data JSON, insert_data JSON) RETURNS JSON IMMUTABLE LANGUAGE SQL AS $$ SELECT ('{' || string_agg(to_json(key) || ':' || value, ',') || '}') :: JSON FROM ( SELECT * FROM json_each(data) UNION ALL SELECT * FROM json_each(insert_data) ) t; $$;
  • 18. JSON Merge Function CREATE OR REPLACE FUNCTION json_merge(data JSON, merge_data JSON) RETURNS JSON IMMUTABLE LANGUAGE SQL AS $$ SELECT ('{' || string_agg(to_json(key) || ':' || value, ',') || '}') :: JSON FROM ( WITH to_merge AS ( SELECT * FROM json_each(merge_data) ) SELECT * FROM json_each(data) WHERE key NOT IN (SELECT key FROM to_merge) UNION ALL SELECT * FROM to_merge ) t; $$;
  • 19. Check Constraint CREATE TABLE web_user ( id SERIAL PRIMARY KEY, username VARCHAR(255) UNIQUE NOT NULL CHECK (trim(username) <> ''), email VARCHAR(255) UNIQUE NOT NULL CHECK (valid_email(email)), password CHARACTER(40) NOT NULL CHECK (char_length(password) = 40), created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated TIMESTAMP ); CREATE EXTENSION pgcrypto; INSERT INTO web_user VALUES ( '2', 'foo', 'abramchenkoa@bar.com', ENCODE(DIGEST('test', 'sha1'), 'hex') );
  • 20. Domain and Citext Extension CREATE EXTENSION citext; -- Create data type like email RFC5322 CREATE DOMAIN email AS citext CHECK ( value ~ '^[a-zA-Z0-9.!#$%&''*+/=?^_`{|}~-]' || '+@[a-zA-Z0-9](?:[a-zA-Z0-9-]' || '{0,61}[a-zA-Z0-9])?(?:.[a-zA-Z0-9]' || '(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$' );
  • 21. Write functions on Perl, Python, JS, Ruby, PHP CREATE EXTENSION plperlu; CREATE FUNCTION valid_email(text) RETURNS boolean LANGUAGE plperlu IMMUTABLE LEAKPROOF STRICT AS $$ use Email::Valid; my $email = shift; Email::Valid->address($email) or die "Invalid email address: $emailn"; return 'true'; $$;
  • 22. Full Text Search -- Add a new column ALTER TABLE book ADD COLUMN search_fields TSVECTOR; -- Fill the column for searching UPDATE book SET search_fields = to_tsvector( 'english', book.title || ' ' || array_to_string(book.tags, ' ') ); -- Add index CREATE INDEX textsearch_idx ON book USING GIN (search_fields);
  • 23. Search Queries -- Get current text search config SELECT get_current_ts_config(); -- english -- Show all available text search configs SELECT * FROM pg_ts_config; -- Search examples SELECT * FROM book WHERE search_fields @@ to_tsquery('high & postgre:* & 9.6'); SELECT * FROM book WHERE search_fields @@ plainto_tsquery(get_current_ts_config(), 'postgresql performance') ; -- Displays query matching, how title matches the query SELECT id, title, ts_headline(title, q) FROM book, to_tsquery('postgre:* & performance') AS q WHERE setweight(to_tsvector('english', title),'A') || setweight(to_tsvector('english', content), 'B') @@ q;
  • 24. Search By Trigrams -- Enable extension CREATE EXTENSION pg_trgm; -- Add index CREATE INDEX trgm_idx ON book USING GIST (title gist_trgm_ops); -- How similar are the arguments SELECT title, similarity(title, 'Postgre') AS sml FROM book WHERE title % 'Postgre' ORDER BY sml DESC; -- How similar are the first string and the most similar word of the second string SELECT title, word_similarity(title, 'Postgre') AS sml FROM book WHERE title %> 'Postgre' ORDER BY sml DESC;
  • 25. Ltree Hierarchical Data Type -- Enable extension CREATE EXTENSION ltree; -- Store branch like CREATE TABLE comment ( id SERIAL PRIMARY KEY, message TEXT, branch LTREE NOT NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); -- Add index CREATE INDEX ON comment USING GIST (branch);
  • 26. Ltree Data Manipulation INSERT INTO comment (message, branch) VALUES ('Comment 1', '0'); INSERT INTO comment (message, branch) VALUES ('Comment 1.1', '0.1'); INSERT INTO comment (message, branch) VALUES ('Comment 2', '0'); INSERT INTO comment (message, branch) VALUES ('Comment 2.1', '0.3'); INSERT INTO comment (message, branch) VALUES ('Comment 2.2', '0.3'); INSERT INTO comment (message, branch) VALUES ('Comment 2.2.1', '0.3.4'); -- Сhildren of the third message SELECT * FROM comment WHERE branch <@ '0.3'; -- Get by lquery SELECT * FROM comment WHERE branch ~ '*.3.*'::lquery;
  • 27. Thank You For Attention!