{"id":21481296,"url":"https://github.com/arafat-hasan/postgres-notes","last_synced_at":"2026-02-22T13:34:35.371Z","repository":{"id":225497813,"uuid":"287190727","full_name":"arafat-hasan/postgres-notes","owner":"arafat-hasan","description":"Notes on PostgreSQL","archived":false,"fork":false,"pushed_at":"2020-11-03T13:03:12.000Z","size":36,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-23T18:49:04.480Z","etag":null,"topics":["drop-database","drop-table","mockaroo","notes","posgresql","posgress","postgres-role","sql"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arafat-hasan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2020-08-13T05:36:23.000Z","updated_at":"2023-05-04T22:35:54.000Z","dependencies_parsed_at":"2024-03-02T14:27:52.153Z","dependency_job_id":"6a28ce9b-8bd4-47f6-9fb4-49bdbaf7e601","html_url":"https://github.com/arafat-hasan/postgres-notes","commit_stats":null,"previous_names":["arafat-hasan/postgres-notes"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arafat-hasan%2Fpostgres-notes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arafat-hasan%2Fpostgres-notes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arafat-hasan%2Fpostgres-notes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arafat-hasan%2Fpostgres-notes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arafat-hasan","download_url":"https://codeload.github.com/arafat-hasan/postgres-notes/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244006398,"owners_count":20382443,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drop-database","drop-table","mockaroo","notes","posgresql","posgress","postgres-role","sql"],"created_at":"2024-11-23T12:23:11.234Z","updated_at":"2025-10-23T14:50:22.186Z","avatar_url":"https://github.com/arafat-hasan.png","language":null,"readme":"\n\n\u003cp align=\"center\"\u003e\n\u003cimg align=\"center\" width=\"250\" height=\"250\" alt=\"PostgreSQL Logo\" src=\"https://imgur.com/JL46J3e.jpg\"\u003e\n\u003cp\u003e\n\n\n\n\u003ch1 align=\"center\"\u003e PostgreSQL Notes \u003c/h1\u003e\n\n\n\n\n\n\n\u003cbr\u003e\n\n### Table of Content\n\n- [Introduction to PostgreSQL](#introduction-to-postgresql)\n- [🚧 Installation](#---installation)\n  * [Install PostgreSQL in Ubuntu](#install-postgresql-in-ubuntu)\n  * [Install PostgreSQL in CentOS](#install-postgresql-in-centos)\n    + [Method 1: PostgreSQL Yum Repository](#method-1--postgresql-yum-repository)\n    + [Method 2: Using DNF](#method-2--using-dnf)\n- [Initial Configuration](#initial-configuration)\n  * [Creating a New PostgreSQL Database Cluster](#creating-a-new-postgresql-database-cluster)\n  * [Understanding PostgreSQL Roles and Databases](#understanding-postgresql-roles-and-databases)\n  * [Creating a New Postgres Role](#creating-a-new-postgres-role)\n- [Some Very First Commands](#some-very-first-commands)\n  * [Examples](#examples)\n  * [CREATE DATABASE](#create-database)\n  * [DROP DATABASE](#drop-database)\n  * [CREATE TABLE](#create-table)\n  * [Table Definition](#table-definition)\n  * [INSERT INTO](#insert-into)\n  * [SELECT](#select)\n  * [DROP TABLE](#drop-table)\n- [The Surface Sea](#the-surface-sea)\n  * [Mockaroo Data Generator](#mockaroo-data-generator)\n  * [ORDER BY](#order-by)\n    + [ASC](#asc)\n    + [DESC](#desc)\n    + [ORDER BY with Two-parameter](#order-by-with-two-parameter)\n  * [DISTINCT](#distinct)\n  * [WHERE](#where)\n    + [BETWEEN](#between)\n    + [LIKE](#like)\n  * [GROUP BY](#group-by)\n    + [GROUP BY with ORDER BY](#group-by-with-order-by)\n    + [GROUP BY HAVING](#group-by-having)\n  * [COALESCE](#coalesce)\n  * [Another Table Called `car`](#another-table-called--car-)\n  * [Basic Functions](#basic-functions)\n    + [MAX](#max)\n    + [MIN](#min)\n    + [AVG](#avg)\n    + [ROUND](#round)\n    + [COUNT](#count)\n    + [SUM](#sum)\n  * [Basic Arithmetic Operations](#basic-arithmetic-operations)\n  * [Discount Calculation](#discount-calculation)\n  * [ALIAS](#alias)\n  * [NULLIF](#nullif)\n  * [DATE](#date)\n    + [NOW](#now)\n    + [Addition and Subtraction of Date](#addition-and-subtraction-of-date)\n      - [INTERVAL](#interval)\n    + [EXTRACT](#extract)\n    + [AGE](#age)\n- [The Shallow Sea](#the-shallow-sea)\n  * [PRIMARY KEY](#primary-key)\n  * [CONSTRAINTS](#constraints)\n    + [UNIQUE constraint](#unique-constraint)\n    + [CHECK Constraint](#check-constraint)\n  * [DELETE](#delete)\n  * [UPDATE](#update)\n  * [ON CONFLICT](#on-conflict)\n    + [DO NOTHING](#do-nothing)\n    + [DO UPDATE SET](#do-update-set)\n  * [Foreign Keys, Joins and Relationships](#foreign-keys--joins-and-relationships)\n    + [Delete Record with Foreign Keys](#delete-record-with-foreign-keys)\n  * [JOIN](#join)\n    + [INNER JOIN](#inner-join)\n    + [LEFT JOIN](#left-join)\n    + [RIGHT JOIN](#right-join)\n    + [FULL OUTER JOIN](#full-outer-join)\n  * [Exporting Query Results to CSV](#exporting-query-results-to-csv)\n  * [Serials and Sequences](#serials-and-sequences)\n  * [Extensions](#extensions)\n  * [UUID Datatype](#uuid-datatype)\n    + [UUID as Primary Key](#uuid-as-primary-key)\n\n\n\n\n\n\n\u003cbr\u003e\n\n# Introduction to PostgreSQL\n\nPostgreSQL is a powerful, open source object-relational database system with over 30 years of active development that has earned it a strong reputation for reliability, feature robustness, and performance. \n\nPostgreSQL has earned a strong reputation for its proven architecture, reliability, data integrity, robust feature set, extensibility, and the dedication of the open source community behind the software to consistently deliver performant and innovative solutions. PostgreSQL runs on all major operating systems, including Linux, UNIX (AIX, BSD, HP-UX, SGI IRIX, Mac OS X, Solaris, Tru64), and Windows.\n\n\nFrom Wikipedia:\n\u003e PostgreSQL (/ˈpoʊstɡrɛs ˌkjuː ˈɛl/), also known as Postgres, is a free and open-source relational database management system (RDBMS) emphasizing extensibility and SQL compliance. It was originally named POSTGRES, referring to its origins as a successor to the Ingres database developed at the University of California, Berkeley. In 1996, the project was renamed to PostgreSQL to reflect its support for SQL. After a review in 2007, the development team decided to keep the name PostgreSQL and the alias Postgres.\n\n\n\n\n# 🚧 Installation\n\n\n## Install PostgreSQL in Ubuntu\n\nTo install PostgreSQL in ubuntu, we have first to refresh our server’s local package index:\n```\n$ sudo apt update\n```\nThen, install the Postgres package along with a -contrib package that adds some additional utilities and functionality:\n```\n$ sudo apt install postgresql postgresql-contrib\n```\n\nSee More: [How To Install PostgreSQL on Ubuntu 20.04 ](https://www.digitalocean.com/community/tutorials/how-to-install-postgresql-on-ubuntu-20-04-quickstart)\n\n\n## Install PostgreSQL in CentOS\n\n\n### Method 1: PostgreSQL Yum Repository\n\nInstall the repository RPM:\n```\n$ sudo dnf install https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm\n```\nDisable the built-in PostgreSQL module:\n```\n$ sudo dnf -qy module disable postgresql\n```\nInstall PostgreSQL:\n```\n$ sudo dnf install postgresql12-server\n```\n\nNow PostgreSQL is installed, we have to perform some initialization steps to prepare a new database cluster for PostgreSQL.\n\nSee More:  [Linux downloads (Red Hat family)](https://www.postgresql.org/download/linux/redhat/)\n\n### Method 2: Using DNF\n\nIn DNF, CentOS 8’s default package manager, _modules_ are special collections of RPM packages that together make up a larger application. This is intended to make installing packages and their dependencies more intuitive for users.\n\nList out the available streams for the `postgresql` module using the `dnf` command:\n\n```\n$ sudo dnf module list postgresql\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\npostgresql                           9.6                             client, server [d]                          PostgreSQL server and client module                         \npostgresql                           10 [d]                          client, server [d]                          PostgreSQL server and client module                         \npostgresql                           12                              client, server                              PostgreSQL server and client module\n```\n\nIn this output, we can see three versions of PostgreSQL available from the **AppStream** repository: `9.6`, `10`, and `12`. The stream that provides Postgres version 10 is the default, as indicated by the `[d]` following it. If we want to install that version, we could just run `sudo dnf install postgresql-server` and move on to the next step.\n\nTo install PostgreSQL version 12, we have to enable that version’s module stream. When we enable a module stream, we override the default stream and make all of the packages related to the enabled stream available on the system.\n\nTo enable the module stream for Postgres version 12, run the following command:\n```\n$ sudo dnf module enable postgresql:12\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n====================================================================\n Package        Architecture  Version          Repository      Size\n====================================================================\nEnabling module streams:\n postgresql                   12                                   \n\nTransaction Summary\n====================================================================\n\nIs this ok [y/N]: y\n\n```\n\nAfter enabling the version 12 module stream, we can install the `postgresql-server` package to install PostgreSQL 12 and all of its dependencies:\n\n```\n$ sudo dnf install postgresql-server\n```\n\nWhen given the prompt, confirm the installation by pressing `y` then `ENTER`:\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n. . .\nInstall  4 Packages\n\nTotal download size: 16 M\nInstalled size: 62 M\nIs this ok [y/N]: y\n\n```\nNow PostgreSQL is installed, we have to perform some initialization steps to prepare a new database cluster for PostgreSQL.\n\nSee More:  [How To Install and Use PostgreSQL on CentOS 8](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-centos-8)\n\n\n\n# Initial Configuration\n## Creating a New PostgreSQL Database Cluster\n\nWe have to create a new PostgreSQL database cluster before we can start creating tables and loading them with data. A database cluster is a collection of databases that are managed by a single server instance. Creating a database cluster consists of creating the directories in which the database data will be placed, generating the shared catalog tables, and creating the `template1` and `postgres` databases.\n\nThe `template1` database is a template of sorts used to create new databases; everything that is stored in `template1`, even objects we add ourselves, will be placed in new databases when they’re created. The `postgres` database is a default database designed for use by users, utilities, and third-party applications.\n\nThe Postgres package we installed in the previous step comes with a handy script called `postgresql-setup` which helps with low-level database cluster administration.\n\nTo create a database cluster, run the script using `sudo` and with the `--initdb` option.\n\n\n_If PostgreSQL is installed using the PostgreSQL Yum repository:_\n```\n$ /usr/pgsql-12/bin/postgresql-12-setup initdb\n```\n\n_If PostgreSQL is installed using DNF:_\n```\n$ sudo postgresql-setup --initdb\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n * Initializing database in '/var/lib/pgsql/data'\n * Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log\n```\n\n\nNow start and enable PostgreSQL using `systemctl`.\n\n\n_If PostgreSQL is installed using the PostgreSQL Yum repository:_\n\n```\n$ systemctl enable postgresql-12\n$ systemctl start postgresql-12\n```\n_If PostgreSQL is installed using DNF:_\n```\n$ sudo systemctl start postgresql\n$ sudo systemctl enable postgresql\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\nCreated symlink /etc/systemd/system/multi-user.target.wants/postgresql.service → /usr/lib/systemd/system/postgresql.service.\n```\n\nNow that PostgreSQL is up and running, we will go over using roles to learn how Postgres works and how it is different from similar database management systems.\n\n\n\n\n## Understanding PostgreSQL Roles and Databases\n\n\nBy default, Postgres uses a concept called roles to handle authentication and authorization. These are, in some ways, similar to regular Unix-style accounts, but Postgres does not distinguish between users and groups and instead prefers the more flexible term role.\n\nUpon installation, Postgres is set up to use `ident` authentication, meaning that it associates Postgres roles with a matching Unix/Linux system account. If a role exists within Postgres, a Unix/Linux username with the same name can sign in as that role.\n\nThe installation procedure created a user account called `postgres` that is associated with the default Postgres role. To use Postgres, at first, we have to log in using that role.\n\nSo we have to switch over to the `postgres` UNIX user, which is created upon installation of Postgres, and then from the `postgres` UNIX user, we will able to log on Postgres server.\n```\n[arafat@server ~]$ sudo -i -u postgres\n[postgres@server ~]$ psql\n```\n\nAlternatively, to access a Postgres prompt without switching users\n```\n[arafat@server ~]$ sudo -u postgres psql\n```\n\n\n\n\n## Creating a New Postgres Role\n\n\nTo log in with ident-based authentication, we will need a Linux user with the same name as our Postgres role and database.\n\nIf we don’t have a matching Linux user available, we must create one with the `adduser` command.\n```\n[arafat@server ~]$ sudo adduser postgresuser\n```\n\nWe showed how to create a UNIX user named `postgresuser` here, but we will not use it. Instead, we will use the existing `arafat` user for a new Postgres roll.\n\nNow we will create a Postgres role. After switching to `postgres` Linux user:\n```\npostgres@server:~$ createuser --interactive\nEnter name of role to add: arafat\nShall the new role be a superuser? (y/n) y\n```\n\n\nAnother assumption that the Postgres authentication system makes by default is that for any role used to log in, that role will have a database with the same name which it can access.\n\nThis means that if the user we created in the last section is called `arafat`, that role will attempt to connect to a database which is also called `arafat` by default. We can create such a database with the `createdb` command.\n\nIf we are logged in as the `postgres` user, we would type something like:\n\n```\npostgres@server:~$ createdb arafat\n```\n\nNow we will able to connect to `psql` from unix user `arafat` to Postgres role `arafat`. \n```\n[arafat@server ~]$ psql\npsql (12.3)\nType \u0026quot;help\u0026quot; for help.\n\narafat=#\n```\n\n\n\n\n\n# Some Very First Commands\n\n\n- `\\q`: Quit/Exit\n- `\\l`:  List all databases in the current PostgreSQL database server\n- `\\h`: Show the list of SQL commands\n- `\\c __database__`:  Connect to a database\n- `\\d`: To describe (list) what tables are in the database\n- `\\d __table__`: Show table definition (columns, etc.) including triggers\n- `\\i __filename__`: to run (include) a script file of SQL commands\n- `\\w __filename__`: To write the last SQL command to a file\n- `\\h _command_`: Show syntax on this SQL command\n- `\\?`: Show the list of postgres commands\n\n\n\n## Examples\n\n```\n[arafat@server ~]$ psql\npsql (12.3)\nType \u0026quot;help\u0026quot; for help.\n\narafat=# \\l\n                                   List of databases\n     Name     |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   \n--------------+----------+----------+-------------+-------------+-----------------------\n arafat       | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | \n postgres     | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | \n template0    | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +\n              |          |          |             |             | postgres=CTc/postgres\n template1    | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +\n              |          |          |             |             | postgres=CTc/postgres\n(4 rows)\n\narafat=# \\h CREATE DATABASE;\nCommand:     CREATE DATABASE\nDescription: create a new database\nSyntax:\nCREATE DATABASE name\n    [ [ WITH ] [ OWNER [=] user_name ]\n           [ TEMPLATE [=] template ]\n           [ ENCODING [=] encoding ]\n           [ LC_COLLATE [=] lc_collate ]\n           [ LC_CTYPE [=] lc_ctype ]\n           [ TABLESPACE [=] tablespace_name ]\n           [ ALLOW_CONNECTIONS [=] allowconn ]\n           [ CONNECTION LIMIT [=] connlimit ]\n           [ IS_TEMPLATE [=] istemplate ] ]\n\nURL: https://www.postgresql.org/docs/12/sql-createdatabase.html\n\n```\n\n\n\n## CREATE DATABASE\n```\narafat=# CREATE DATABASE test;\nCREATE DATABASE\narafat=# \\l\n                                     List of databases\n     Name     |    Owner     | Encoding |   Collate   |    Ctype    |   Access privileges   \n--------------+--------------+----------+-------------+-------------+-----------------------\n arafat       | postgres     | UTF8     | en_US.UTF-8 | en_US.UTF-8 | \n postgres     | postgres     | UTF8     | en_US.UTF-8 | en_US.UTF-8 | \n template0    | postgres     | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +\n              |              |          |             |             | postgres=CTc/postgres\n template1    | postgres     | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +\n              |              |          |             |             | postgres=CTc/postgres\n test         | arafat       | UTF8     | en_US.UTF-8 | en_US.UTF-8 | \n(5 rows)\n\narafat=# \\c test;\nYou are now connected to database \u0026quot;test\u0026quot; as user \u0026quot;arafat\u0026quot;.\n```\n\n\n## DROP DATABASE\n```\narafat_hasan=# DROP DATABASE test;\nDROP DATABASE\n```\n\n\n## CREATE TABLE\n\nWe have to create a database again as we deleted the `test` database in the previous step. Here `\\d` a list of tables, and there is no table in our newly created database.\n```\narafat=# CREATE DATABASE test;\nCREATE DATABASE\ntest=# \\d\nDid not find any relations.\n```\n\nNow here we are creating a new table named `person`:\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nCREATE TABLE person (\n id BIGSERIAL NOT NULL PRIMARY KEY,\n first_name VARCHAR(50) NOT NULL,\n last_name VARCHAR(50) NOT NULL,\n gender VARCHAR(50) NOT NULL,\n date_of_birth DATE NOT NULL,\n email VARCHAR(150));\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\nCREATE TABLE\n```\n\nNow check the list of tables:\n```\ntest=# \\d\n                List of relations\n Schema |     Name      |   Type   |    Owner     \n--------+---------------+----------+--------------\n public | person        | table    | arafat_hasan\n public | person_id_seq | sequence | arafat_hasan\n(2 rows)\n```\n\n`person_id_seq` is not a table, it is a sequence to maintain and increment the `BIGSERIAL` value in the `person` table. The keyword `NOT NULL` means that this field can not be null or blank, we must have enter data for that field. Someone may not have email, so have kept the field as optional.\n\n\n\n## Table Definition\n```\ntest=#  \\d person;\n                                       Table \"public.person\"\n    Column     |          Type          | Collation | Nullable |              Default               \n---------------+------------------------+-----------+----------+------------------------------------\n id            | bigint                 |           | not null | nextval('person_id_seq'::regclass)\n first_name    | character varying(50)  |           | not null | \n last_name     | character varying(50)  |           | not null | \n gender        | character varying(50)  |           | not null | \n date_of_birth | date                   |           | not null | \n email         | character varying(150) |           |          | \nIndexes:\n    \"person_pkey\" PRIMARY KEY, btree (id)\n\n```\n\n\n## INSERT INTO\nNotice that, as email is not `NOT NULL` so it is optional to insert into the table.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nINSERT INTO person (first_name, last_name, gender, date_of_birth)\n VALUES('Anne', 'Smith', 'female', DATE '1988-01-09');\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\nINSERT 0 1\n```\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nINSERT INTO person (first_name, last_name, gender, date_of_birth, email)\n VALUES('Jack', 'Doe', 'male', DATE '1985-11-03', 'jack@example.com');\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\nINSERT 0 1\n```\n\n\n## SELECT\nFetch all data from table:\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT * FROM person;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n id | first_name | last_name | gender | date_of_birth |      email       \n----+------------+-----------+--------+---------------+------------------\n  1 | Anne       | Smith     | female | 1988-01-09    | \n  2 | Jack       | Doe       | male   | 1985-11-03    | jack@example.com\n(2 rows)\n```\n\n\n## DROP TABLE\nNow we want to delete our table `person`.\n```\ntest=# DROP TABLE person;\nDROP TABLE\n```\n\n\n\n#  The Surface Sea\n\n\n## Mockaroo Data Generator\nWe will use a site named [Mockaroo](https://mockaroo.com/) to insert a lot of data into our table for our learning convenience. Mockaroo is an online realist test data generator. We will download a bunch of dummy but realistic data in SQL format and execute the SQL file in the terminal.\n\n![Generate data using Mockaroo](https://imgur.com/rLGnx8z.jpg, \"Generate data using Mockaroo\")\n\nNotes:\n- Field Names and types in Mockaroo according to the image above.\n-  For our learning convenience, make sure 30% blank in the `email` field.\n- Set a  acceptable nice range for data of birth.\n- To find the type of each field, we have to search with the appropriate keyword.\n- Tick the _include create table_ option.\n\nDownload the data as a file named `person.sql`.\n\n\nNow we will do some tweaking in `person.sql`, according to our needs. Open this file in the preferred editor, I'm using vs code. Then make the following changes to the CREATE TABLE command at the top of the file.  Notice that we have added `id BIGSERIAL NOT NULL PRIMARY KEY`, changed `VARCHAR` sizes, and specified the `NOT NULL` fields.\n\n\n```sql\ncreate table person (\n\tid BIGSERIAL NOT NULL PRIMARY KEY,\n\tfirst_name VARCHAR(50) NOT NULL,\n\tlast_name VARCHAR(50) NOT NULL,\n\temail VARCHAR(150),\n\tgender VARCHAR(7) NOT NULL,\n\tdate_of_birth DATE NOT NULL,\n\tcountry_of_birth VARCHAR(50) NOT NULL\n);\n-- More lines containing INSERT command, We are not showing them here.\n```\n\nAfter saving our changed `person.sql` file, now we will execute it. We can copy the whole file and paste it into Postgres terminal, that will work too, but we are going to do it in a better way. `\\i` executes a script file of SQL commands.\n```\ntest=# \\i /path/to/person.sql \n```\nNow the script `person.sql` is executed, and there are 1000 rows in the `person` table.\n\nOur table description look like this:\n```\ntest=# \\d person;\n                           Table \"public.person\"\n      Column      |          Type          | Collation | Nullable | Default \n------------------+------------------------+-----------+----------+---------\n first_name       | character varying(50)  |           | not null | \n last_name        | character varying(50)  |           | not null | \n email            | character varying(150) |           |          | \n gender           | character varying(7)   |           | not null | \n date_of_birth    | date                   |           | not null | \n country_of_birth | character varying(50)  |           | not null | \n\n```\n\n\nHere we have made a query to fetch all the data from the `person` table.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT * FROM person;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n  id  |   first_name   |      last_name      |                  email                  | gender | date_of_birth |         country_of_birth         \n------+----------------+---------------------+-----------------------------------------+--------+---------------+----------------------------------\n    1 | Ronda          | Skermer             | rskermer0@arstechnica.com               | Female | 1993-06-30    | Argentina\n    2 | Hamid          | Abbett              | habbett1@cbc.ca                         | Male   | 1995-08-31    | Ethiopia\n    3 | Francis        | Nickerson           | fnickerson2@mac.com                     | Male   | 1998-03-16    | Portugal\n    4 | Erminie        | M'Quharg            | emquharg3@e-recht24.de                  | Female | 1999-03-13    | Mozambique\n    5 | Teodoro        | Trimmill            |                                         | Male   | 1982-04-30    | China\n    6 | Reilly         | Amesbury            | ramesbury5@businessinsider.com          | Male   | 1990-12-31    | China\n    7 | West           | Elphey              |                                         | Male   | 2004-03-29    | Indonesia\n    8 | Letta          | Caurah              | lcaurah7@yale.edu                       | Female | 1994-09-09    | Indonesia\n    9 | Elset          | Agass               | eagass8@rambler.ru                      | Female | 2004-06-26    | China\n   10 | Aurore         | Drillingcourt       | adrillingcourt9@cnet.com                | Female | 1977-10-19    | China\n   11 | Ilse           | Goldman             | igoldmana@ihg.com                       | Female | 2001-07-31    | Mongolia\n   12 | Penny          | Nayer               | pnayerb@harvard.edu                     | Female | 1969-02-05    | Colombia\n   13 | Neale          | Dubery              | nduberyc@soundcloud.com                 | Male   | 1975-12-22    | Portugal\n   14 | Gnni           | Dickman             | gdickmand@people.com.cn                 | Female | 1977-10-12    | Guatemala\n   15 | Flori          | Giroldi             | fgiroldie@ameblo.jp                     | Female | 1975-11-14    | China\n--More--\n```\n\nAlternatively, we can specify our required field names:\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT id, first_name, last_name FROM person;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n  id  |   first_name   |      last_name      \n------+----------------+---------------------\n    1 | Ronda          | Skermer\n    2 | Hamid          | Abbett\n    3 | Francis        | Nickerson\n    4 | Erminie        | M'Quharg\n    5 | Teodoro        | Trimmill\n    6 | Reilly         | Amesbury\n    7 | West           | Elphey\n    8 | Letta          | Caurah\n    9 | Elset          | Agass\n   10 | Aurore         | Drillingcourt\n--More--\n```\n\n\n\n## ORDER BY\n\nThe ORDER BY keyword is used to sort the result-set in ascending (`ASC`) or descending (`DESC`) order. The ORDER BY keyword sorts the records in ascending order by default. To sort the records in ascending order, use the DESC keyword.\n\n\n\n### ASC\nFor ascending order:\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT * FROM person ORDER BY country_of_birth;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n  id  |   first_name   |      last_name      |                  email                  | gender | date_of_birth |         country_of_birth         \n------+----------------+---------------------+-----------------------------------------+--------+---------------+----------------------------------\n  475 | Koren          | Burgen              |                                         | Female | 1985-09-16    | Afghanistan\n  223 | Collen         | Raubheim            | craubheim66@gravatar.com                | Female | 1968-01-31    | Afghanistan\n  331 | Vaughan        | Borles              | vborles96@behance.net                   | Male   | 1987-09-08    | Albania\n  831 | Cordy          | Aries               |                                         | Male   | 2007-07-06    | Albania\n  662 | Una            | Chevis              | uchevisid@whitehouse.gov                | Female | 2001-10-03    | Albania\n  993 | Delmar         | Sparham             |                                         | Male   | 2000-01-24    | Albania\n  583 | Nikolia        | Whodcoat            | nwhodcoatg6@army.mil                    | Female | 1993-01-01    | Albania\n  751 | Kyrstin        | Wimpenny            | kwimpennyku@slideshare.net              | Female | 1986-07-12    | Algeria\n  837 | Dalis          | McLinden            |                                         | Male   | 1989-09-24    | Angola\n--More--\n```\n\n\n### DESC\nFor dscending order:\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT * FROM person ORDER BY country_of_birth DESC;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n  id  |   first_name   |      last_name      |                  email                  | gender | date_of_birth |         country_of_birth         \n------+----------------+---------------------+-----------------------------------------+--------+---------------+----------------------------------\n  563 | Meredeth       | Pantin              |                                         | Male   | 1971-02-22    | Zambia\n  173 | Pennie         | Christauffour       | pchristauffour4s@scientificamerican.com | Male   | 2004-04-16    | Zambia\n  947 | Saidee         | Daffern             | sdaffernqa@barnesandnoble.com           | Female | 1973-03-11    | Yemen\n  742 | Lacee          | Sumner              | lsumnerkl@icio.us                       | Female | 2007-03-31    | Yemen\n  520 | Clerissa       | Mockett             |                                         | Female | 1980-12-08    | Yemen\n   89 | Robinson       | Tichner             |                                         | Male   | 2005-12-09    | Yemen\n  754 | Oren           | Eidler              | oeidlerkx@typepad.com                   | Male   | 1969-02-23    | Yemen\n  725 | Sadye          | Garman              |                                         | Female | 1985-11-05    | Yemen\n  537 | Isadore        | Tasker              | itaskerew@example.com                   | Male   | 1977-03-05    | Vietnam\n  602 | Nevins         | Blenkinship         | nblenkinshipgp@psu.edu                  | Male   | 2010-02-04    | Vietnam\n--More--\n\n```\n\nDate of birth in dscending order:\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT * FROM person ORDER BY date_of_birth DESC;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n\n```\n  id  |   first_name   |      last_name      |                  email                  | gender | date_of_birth |         country_of_birth         \n------+----------------+---------------------+-----------------------------------------+--------+---------------+----------------------------------\n  307 | Penni          | Privost             |                                         | Female | 2010-08-07    | Indonesia\n   43 | Kathye         | Bottleson           | kbottleson16@google.pl                  | Female | 2010-06-27    | China\n  616 | Darryl         | Craw                | dcrawh3@nba.com                         | Male   | 2010-05-30    | Guatemala\n  549 | Paulie         | Durante             | pdurantef8@go.com                       | Female | 2010-05-09    | Russia\n  983 | Elka           | Chyuerton           |                                         | Female | 2010-04-28    | China\n  533 | Leslie         | Lusgdin             | llusgdines@creativecommons.org          | Female | 2010-04-20    | Bosnia and Herzegovina\n  248 | Shurwood       | Vezey               | svezey6v@amazon.com                     | Male   | 2010-04-15    | Indonesia\n  974 | Noll           | Pidgin              | npidginr1@wiley.com                     | Male   | 2010-04-13    | Indonesia\n  676 | Edwina         | Presdee             | epresdeeir@icio.us                      | Female | 2010-04-10    | China\n  813 | Terri          | Blockey             | tblockeymk@gnu.org                      | Female | 2010-04-08    | China\n--More--\n```\n\n\n\n### ORDER BY with Two-parameter\nThis means that if `country_of_birth` is the same, then the rows will be sorted according to the `id` column. Check the difference with the previous one and this.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT * FROM person ORDER BY country_of_birth, id;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n  id  |   first_name   |      last_name      |                  email                  | gender | date_of_birth |         country_of_birth         \n------+----------------+---------------------+-----------------------------------------+--------+---------------+----------------------------------\n  223 | Collen         | Raubheim            | craubheim66@gravatar.com                | Female | 1968-01-31    | Afghanistan\n  475 | Koren          | Burgen              |                                         | Female | 1985-09-16    | Afghanistan\n  331 | Vaughan        | Borles              | vborles96@behance.net                   | Male   | 1987-09-08    | Albania\n  583 | Nikolia        | Whodcoat            | nwhodcoatg6@army.mil                    | Female | 1993-01-01    | Albania\n  662 | Una            | Chevis              | uchevisid@whitehouse.gov                | Female | 2001-10-03    | Albania\n  831 | Cordy          | Aries               |                                         | Male   | 2007-07-06    | Albania\n--More--\n```\n\n## DISTINCT\nThe `SELECT DISTINCT` statement is used to return only distinct (different) values.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT DISTINCT country_of_birth FROM person ORDER BY country_of_birth;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n         country_of_birth         \n----------------------------------\n Afghanistan\n Albania\n Algeria\n Angola\n Argentina\n Armenia\n Australia\n Azerbaijan\n Bangladesh\n Belarus\n Benin\n Bolivia\n Bosnia and Herzegovina\n Brazil\n--More--\n```\n## WHERE\nThe `WHERE` clause is used to extract only those records that fulfill a specified condition.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT * FROM person WHERE gender='Female';\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n id  |   first_name   |      last_name      |                 email                 | gender | date_of_birth |     country_of_birth     \n-----+----------------+---------------------+---------------------------------------+--------+---------------+--------------------------\n   1 | Ronda          | Skermer             | rskermer0@arstechnica.com             | Female | 1993-06-30    | Argentina\n   4 | Erminie        | M'Quharg            | emquharg3@e-recht24.de                | Female | 1999-03-13    | Mozambique\n   8 | Letta          | Caurah              | lcaurah7@yale.edu                     | Female | 1994-09-09    | Indonesia\n   9 | Elset          | Agass               | eagass8@rambler.ru                    | Female | 2004-06-26    | China\n  10 | Aurore         | Drillingcourt       | adrillingcourt9@cnet.com              | Female | 1977-10-19    | China\n  11 | Ilse           | Goldman             | igoldmana@ihg.com                     | Female | 2001-07-31    | Mongolia\n  12 | Penny          | Nayer               | pnayerb@harvard.edu                   | Female | 1969-02-05    | Colombia\n--More--\n```\n\n\n\n### BETWEEN\nThe `BETWEEN` operator selects values within a given range. The values can be numbers, text, or dates.\n\nThe `BETWEEN` operator is inclusive: begin and end values are included.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT * FROM person WHERE date_of_birth BETWEEN '1985-02-02' AND '1986-06-04';\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n id  | first_name |  last_name   |            email             | gender | date_of_birth |   country_of_birth    \n-----+------------+--------------+------------------------------+--------+---------------+-----------------------\n  25 | Billi      | Dybbe        | bdybbeo@samsung.com          | Female | 1986-02-22    | Brazil\n  37 | Sorcha     | Tunesi       | stunesi10@adobe.com          | Female | 1986-04-12    | Philippines\n  45 | Carleen    | Dzeniskevich | cdzeniskevich18@disqus.com   | Female | 1985-06-18    | China\n 103 | Oberon     | Sparry       | osparry2u@yellowbook.com     | Male   | 1985-09-22    | China\n 125 | Cal        | Shurville    | cshurville3g@1und1.de        | Male   | 1986-01-29    | Qatar\n 157 | Juline     | Wanek        |                              | Female | 1985-11-30    | Sweden\n 162 | Amelia     | Braferton    |                              | Female | 1986-05-03    | New Zealand\n 168 | West       | Glowacz      | wglowacz4n@yolasite.com      | Male   | 1985-12-02    | Canada\n--More--\n```\n\n### LIKE\nThe `LIKE` operator is used in a `WHERE` clause to search for a specified pattern in a column.\n\nThere are two wildcards often used in conjunction with the LIKE operator:\n\n- `%`: The percent sign represents zero, one, or multiple characters\n- `_`: The underscore represents a single character\n\nFind all emails ending with `disqus.com`:\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT * FROM person WHERE email LIKE '%disqus.com';\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n id  | first_name |  last_name   |           email            | gender | date_of_birth | country_of_birth \n-----+------------+--------------+----------------------------+--------+---------------+------------------\n  45 | Carleen    | Dzeniskevich | cdzeniskevich18@disqus.com | Female | 1985-06-18    | China\n 852 | Alex       | Garmans      | agarmansnn@disqus.com      | Male   | 1990-11-08    | China\n(2 rows)\n```\n\n\n## GROUP BY\nThe `GROUP BY` statement groups rows that have the same values into summary rows, like \"find the number of persons in each country\".\n\nThe `GROUP BY` statement is often used with aggregate functions (`COUNT`, `MAX`, `MIN`, `SUM`, `AVG`) to group the result-set by one or more columns.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT country_of_birth, COUNT(*) FROM person GROUP BY country_of_birth;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n\n```\n         country_of_birth         | count \n----------------------------------+-------\n Bangladesh                       |     1\n Indonesia                        |   109\n Venezuela                        |     5\n Cameroon                         |     3\n Czech Republic                   |    18\n Sweden                           |    31\n Dominican Republic               |     7\n Ireland                          |     3\n Macedonia                        |     4\n Papua New Guinea                 |     2\n Sri Lanka                        |     1\n--More--\n```\n### GROUP BY with ORDER BY\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT country_of_birth, COUNT(*) FROM person GROUP BY country_of_birth ORDER BY country_of_birth;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n         country_of_birth         | count \n----------------------------------+-------\n Afghanistan                      |     2\n Albania                          |     5\n Algeria                          |     1\n Angola                           |     2\n Argentina                        |    20\n Armenia                          |     5\n Australia                        |     1\n Azerbaijan                       |     3\n Bangladesh                       |     1\n--More--\n```\n\n### GROUP BY HAVING\nThe HAVING clause was added to SQL because the WHERE keyword could not be used with aggregate functions.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT country_of_birth, COUNT(*) FROM person GROUP BY country_of_birth HAVING COUNT(*) \u003e 50 ORDER BY country_of_birth;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n country_of_birth | count \n------------------+-------\n China            |   180\n Indonesia        |   109\n Russia           |    56\n(3 rows)\n```\n\n## COALESCE\nThe `COALESCE()` function returns the first non-null value in a list.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT COALESCE(email, 'Email not provided') FROM person;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n                coalesce                 \n-----------------------------------------\n rskermer0@arstechnica.com\n habbett1@cbc.ca\n fnickerson2@mac.com\n emquharg3@e-recht24.de\n Email not provided\n ramesbury5@businessinsider.com\n Email not provided\n lcaurah7@yale.edu\n eagass8@rambler.ru\n adrillingcourt9@cnet.com\n igoldmana@ihg.com\n pnayerb@harvard.edu\n--More--\n```\n\n## Another Table Called `car`\nNow we will download a new bunch of data to create another table called `car`. This table has these columns:\n- `id`: Primary key\n- `make`: Company name of the car\n- `model`: Model of the car\n- `price`: Price of the car, price between in a nice range\n\n![Generate data using Mockaroo](https://imgur.com/z93rIG7.jpg \":Generate data using Mockaroo\")\n\nNow edit the downloded file `car.sql` a bit—\n\n\n```sql\ncreate table car (\n\tid BIGSERIAL NOT NULL PRIMARY KEY,\n\tmake VARCHAR(100) NOT NULL,\n\tmodel VARCHAR(100) NOT NULL,\n\tprice NUMERIC(19, 2) NOT NULL\n);\n\n-- More lines containing INSERT command, We are not showing them here.\n```\nAfter saving our changed `car.sql` file, now we will execute it.\n```\ntest=# \\i /path/to/car.sql \n```\n\nHere is first 10 rows from `car` table. `LIMIT` is used to get only first 10 rows.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT * FROM car LIMIT 10;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n id |    make    |      model       |   price   \n----+------------+------------------+-----------\n  1 | Daewoo     | Leganza          | 241058.40\n  2 | Mitsubishi | Montero          | 269595.21\n  3 | Kia        | Rio              | 245275.16\n  4 | GMC        | Savana 1500      | 217435.26\n  5 | Jaguar     | X-Type           |  41665.96\n  6 | Lincoln    | Mark VIII        | 163843.38\n  7 | GMC        | Rally Wagon 3500 | 231169.05\n  8 | Cadillac   | Escalade ESV     | 279951.34\n  9 | Volvo      | XC70             | 269436.96\n 10 | Isuzu      | Rodeo            |  65421.58\n(10 rows)\n```\n\n\n## Basic Functions\n\n### MAX\n\nThe `MAX()` function returns the largest value of the selected column.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT MAX(price) FROM car;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n    max    \n-----------\n 299959.83\n(1 row)\n```\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT make, MAX(price) FROM car GROUP BY make LIMIT 5;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n   make   |    max    \n----------+-----------\n Ford     | 290993.39\n Smart    | 159887.95\n Maserati | 221349.10\n Dodge    | 299766.43\n Infiniti | 298245.19\n(5 rows)\n```\n\n### MIN\nThe `MIN()` function returns the smallest value of the selected column.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT MIN(price) FROM car;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n   min    \n----------\n 30348.16\n(1 row)\n```\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT make, MIN(price) FROM car GROUP BY make LIMIT 5;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n   make   |    min    \n----------+-----------\n Ford     |  31021.48\n Smart    | 159887.95\n Maserati |  38668.83\n Dodge    |  33495.17\n Infiniti |  47912.88\n(5 rows)\n```\n\n### AVG\nThe `AVG()` function returns the average value of a numeric column.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT AVG(price) FROM car;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n         avg         \n---------------------\n 164735.601300000000\n(1 row)\n```\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT make, AVG(price) FROM car GROUP BY make LIMIT 5;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n   make   |         avg         \n----------+---------------------\n Ford     | 171967.729473684211\n Smart    | 159887.950000000000\n Maserati | 122897.857500000000\n Dodge    | 166337.502307692308\n Infiniti | 179690.643846153846\n(5 rows)\n```\n\n\n### ROUND\nThe PostgreSQL `ROUND()` function rounds a numeric value to its nearest integer or a number with the number of decimal places.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT ROUND(AVG(price)) FROM car;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n round  \n--------\n 164736\n(1 row)\n```\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT make, ROUND(AVG(price)) FROM car GROUP BY make LIMIT 5;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n   make   | round  \n----------+--------\n Ford     | 171968\n Smart    | 159888\n Maserati | 122898\n Dodge    | 166338\n Infiniti | 179691\n(5 rows)\n\n\n```\n\n### COUNT\nThe `COUNT()` function returns the number of rows that match a specified criterion.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT COUNT(make) FROM car;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n count \n-------\n  1000\n(1 row)\n```\n\n### SUM\nThe `SUM()` function returns the total sum of a numeric column.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT SUM(price) FROM car;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n     sum      \n--------------\n 164735601.30\n(1 row)\n```\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT make, SUM(price) FROM car GROUP BY make LIMIT 5;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n   make   |     sum     \n----------+-------------\n Ford     | 16336934.30\n Smart    |   159887.95\n Maserati |   491591.43\n Dodge    |  8649550.12\n Infiniti |  2335978.37\n(5 rows)\n```\n\n## Basic Arithmetic Operations\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT 10 + 2;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n ?column? \n----------\n       12\n(1 row)\n```\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT 10 / 2;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n ?column? \n----------\n        5\n(1 row)\n```\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT 10^2;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n ?column? \n----------\n      100\n(1 row)\n```\n\n## Discount Calculation\nNow suppose the company offers a 10% discount on all cars. We will now calculate the amount of this 10%, and calculate the new price.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT id, make, model, price, ROUND(price * 0.10, 2), ROUND(price - (price * 0.10), 2) FROM car;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n  id  |     make      |        model         |   price   |  round   |   round   \n------+---------------+----------------------+-----------+----------+-----------\n    1 | Daewoo        | Leganza              | 241058.40 | 24105.84 | 216952.56\n    2 | Mitsubishi    | Montero              | 269595.21 | 26959.52 | 242635.69\n    3 | Kia           | Rio                  | 245275.16 | 24527.52 | 220747.64\n    4 | GMC           | Savana 1500          | 217435.26 | 21743.53 | 195691.73\n    5 | Jaguar        | X-Type               |  41665.96 |  4166.60 |  37499.36\n    6 | Lincoln       | Mark VIII            | 163843.38 | 16384.34 | 147459.04\n    7 | GMC           | Rally Wagon 3500     | 231169.05 | 23116.91 | 208052.15\n    8 | Cadillac      | Escalade ESV         | 279951.34 | 27995.13 | 251956.21\n    9 | Volvo         | XC70                 | 269436.96 | 26943.70 | 242493.26\n   10 | Isuzu         | Rodeo                |  65421.58 |  6542.16 |  58879.42\n--More--\n```\n\n`ROUND (source [ , n ] )` function rounds a numeric value to its nearest integer or a number with the number of decimal places. Where The source argument is a number or a numeric expression that is to be rounded and the n argument is an integer that determines the number of decimal places after rounding.\n\n\n\n## ALIAS\n\nSQL aliases are used to give a table, or a column in a table, a temporary name. Aliases are often used to make column names more readable. An alias only exists for the duration of the query.\n\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT id, make, model, price AS original_price,\n ROUND(price * 0.10, 2) AS ten_percent_discount,\n ROUND(price - (price * 0.10), 2) AS discounted_price\n FROM car;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n  id  |     make      |        model         | original_price | ten_percent_discount | discounted_price \n------+---------------+----------------------+----------------+----------------------+------------------\n    1 | Daewoo        | Leganza              |      241058.40 |             24105.84 |        216952.56\n    2 | Mitsubishi    | Montero              |      269595.21 |             26959.52 |        242635.69\n    3 | Kia           | Rio                  |      245275.16 |             24527.52 |        220747.64\n    4 | GMC           | Savana 1500          |      217435.26 |             21743.53 |        195691.73\n    5 | Jaguar        | X-Type               |       41665.96 |              4166.60 |         37499.36\n    6 | Lincoln       | Mark VIII            |      163843.38 |             16384.34 |        147459.04\n    7 | GMC           | Rally Wagon 3500     |      231169.05 |             23116.91 |        208052.15\n    8 | Cadillac      | Escalade ESV         |      279951.34 |             27995.13 |        251956.21\n    9 | Volvo         | XC70                 |      269436.96 |             26943.70 |        242493.26\n   10 | Isuzu         | Rodeo                |       65421.58 |              6542.16 |         58879.42\n--More--\n```\n\n\n## NULLIF\nThe NULLIF() function returns NULL if two expressions are equal. Otherwise, it returns the first expression.\n\n```\ntest=# SELECT NULLIF(2, 1);\n nullif \n--------\n      2\n(1 row)\n\ntest=# SELECT NULLIF('a', 'b');\n nullif \n--------\n a\n(1 row)\n\ntest=# SELECT NULLIF(0, 0);\n nullif \n--------\n       \n(1 row)\n\t\n```\n\n\n\n## DATE\nPostgreSQL provides several functions that return values related to the current date and time. These SQL-standard functions all return values based on the start time of the current transaction:\n\n```sql\nCURRENT_DATE\nCURRENT_TIME\nCURRENT_TIMESTAMP\nCURRENT_TIME(precision)\n\n```\n\n\n```\nSELECT CURRENT_TIME;\nResult: 14:39:53.662522-05\n\nSELECT CURRENT_DATE;\nResult: 2001-12-23\n\nSELECT CURRENT_TIMESTAMP;\nResult: 2001-12-23 14:39:53.662522-05\n```\n\n\nPostgreSQL also provides functions that return the start time of the current statement, as well as the actual current time at the instant the function is called. The complete list of non-SQL-standard time functions is:\n\n```sql\ntransaction_timestamp()\nstatement_timestamp()\nclock_timestamp()\ntimeofday()\nnow()\n\n```\n\n### NOW\n\n```\ntest=# SELECT NOW();\n             now              \n------------------------------\n 2020-08-19 23:39:49.18778+06\n(1 row)\n\ntest=# SELECT NOW()::DATE;\n    now     \n------------\n 2020-08-19\n(1 row)\n\ntest=# SELECT NOW()::TIME;\n       now       \n-----------------\n 23:40:44.645625\n(1 row)\n\n```\n\n### Addition and Subtraction of Date\n#### INTERVAL\n\n```\ntest=# SELECT NOW() - INTERVAL '1 YEAR';\n           ?column?            \n-------------------------------\n 2019-08-19 23:47:11.475305+06\n(1 row)\n\ntest=# SELECT NOW() - INTERVAL '10 YEAR';\n           ?column?            \n-------------------------------\n 2010-08-19 23:47:31.627347+06\n(1 row)\n\ntest=# SELECT NOW() - INTERVAL '3 MONTHS';\n           ?column?            \n-------------------------------\n 2020-05-19 23:47:53.403383+06\n(1 row)\n\ntest=# SELECT NOW() + INTERVAL '40 DAYS';\n           ?column?            \n-------------------------------\n 2020-09-28 23:48:31.419856+06\n(1 row)\n\n\n```\n\n\n\n### EXTRACT\nThe extract function retrieves subfields such as year or hour from date/time values. *source* must be a value expression of type `timestamp`, `time`, or `interval`. (Expressions of type date are cast to `timestamp` and can, therefore, be used as well.) *field* is an identifier or string that selects what field to extract from the source value. The extract function returns values of type double precision. \n\n```\nEXTRACT(field FROM source)\n```\n\n\n```\ntest=# SELECT NOW();\n             now              \n------------------------------\n 2020-08-19 23:55:42.13778+06\n(1 row)\n\ntest=# SELECT EXTRACT(YEAR FROM NOW());\n date_part \n-----------\n      2020\n(1 row)\n\ntest=# SELECT EXTRACT(MONTH FROM NOW());\n date_part \n-----------\n         8\n(1 row)\n\ntest=# SELECT EXTRACT(CENTURY FROM NOW());\n date_part \n-----------\n        21\n(1 row)\n\n\n```\n\n\n### AGE\n\n```\nage(timestamp, timestamp)\n```\nor\n```\nage(timestamp)\n```\nThe return type of both is an interval.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT first_name, last_name, gender, date_of_birth, AGE(NOW(), date_of_birth) AS age FROM person;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n   first_name   |      last_name      | gender | date_of_birth |                   age                    \n----------------+---------------------+--------+---------------+------------------------------------------\n Ronda          | Skermer             | Female | 1993-06-30    | 27 years 1 mon 19 days 23:56:04.414053\n Hamid          | Abbett              | Male   | 1995-08-31    | 24 years 11 mons 19 days 23:56:04.414053\n Francis        | Nickerson           | Male   | 1998-03-16    | 22 years 5 mons 3 days 23:56:04.414053\n Erminie        | M'Quharg            | Female | 1999-03-13    | 21 years 5 mons 6 days 23:56:04.414053\n Teodoro        | Trimmill            | Male   | 1982-04-30    | 38 years 3 mons 19 days 23:56:04.414053\n Reilly         | Amesbury            | Male   | 1990-12-31    | 29 years 7 mons 19 days 23:56:04.414053\n West           | Elphey              | Male   | 2004-03-29    | 16 years 4 mons 21 days 23:56:04.414053\n Letta          | Caurah              | Female | 1994-09-09    | 25 years 11 mons 10 days 23:56:04.414053\n Elset          | Agass               | Female | 2004-06-26    | 16 years 1 mon 23 days 23:56:04.414053\n--More--\n```\n\nSee More: [Date/Time Types](https://www.postgresql.org/docs/9.1/datatype-datetime.html)\n\n\n\n# The Shallow Sea\n\n## PRIMARY KEY\nThe `PRIMARY KEY` of a table is a combination of `NOT NULL` and `UNIQUE` constraint. \nHere we will see how to delete and add a primary key.\n\n\nAt first, we check the table description, and we have found that the `id` column is a `PRIMARY KEY`.\n\n```\n\\d person;\n```\n\n```\n                                         Table \"public.person\"\n      Column      |          Type          | Collation | Nullable |              Default               \n------------------+------------------------+-----------+----------+------------------------------------\n id               | bigint                 |           | not null | nextval('person_id_seq'::regclass)\n first_name       | character varying(50)  |           | not null | \n last_name        | character varying(50)  |           | not null | \n email            | character varying(150) |           |          | \n gender           | character varying(7)   |           | not null | \n date_of_birth    | date                   |           | not null | \n country_of_birth | character varying(50)  |           | not null | \nIndexes:\n    \"person_pkey\" PRIMARY KEY, btree (id)\n    \n```\n\nNow we will try to add a duplicate value to the table.\n\n```\ntest=# SELECT * FROM person WHERE id=1;\n id | first_name | last_name |           email           | gender | date_of_birth | country_of_birth \n----+------------+-----------+---------------------------+--------+---------------+------------------\n  1 | Ronda      | Skermer   | rskermer0@arstechnica.com | Female | 1993-06-30    | Argentina\n(1 row)\n\ntest=# INSERT INTO person (id, first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES (1, 'Ronda', 'Skermer', 'rskermer0@arstechnica.com', 'Female', '1993-06-30', 'Argentina');\nERROR:  duplicate key value violates unique constraint \"person_pkey\"\nDETAIL:  Key (id)=(1) already exists.\n```\n\n\nInsertion value is failed as the `id` column is primary, and it says _duplicate key value violates unique constraint_. Now we will drop the primary key constraint of the `id` column and will again try to insert duplicate data into the table.\n\n```\ntest=# ALTER TABLE person DROP CONSTRAINT person_pkey;\nALTER TABLE\ntest=# \\d person;\n                                         Table \"public.person\"\n      Column      |          Type          | Collation | Nullable |              Default               \n------------------+------------------------+-----------+----------+------------------------------------\n id               | bigint                 |           | not null | nextval('person_id_seq'::regclass)\n first_name       | character varying(50)  |           | not null | \n last_name        | character varying(50)  |           | not null | \n email            | character varying(150) |           |          | \n gender           | character varying(7)   |           | not null | \n date_of_birth    | date                   |           | not null | \n country_of_birth | character varying(50)  |           | not null | \n\ntest=# INSERT INTO person (id, first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES (1, 'Ronda', 'Skermer', 'rskermer0@arstechnica.com', 'Female', '1993-06-30', 'Argentina');\nINSERT 0 1\ntest=# SELECT * FROM person WHERE id=1;\n id | first_name | last_name |           email           | gender | date_of_birth | country_of_birth \n----+------------+-----------+---------------------------+--------+---------------+------------------\n  1 | Ronda      | Skermer   | rskermer0@arstechnica.com | Female | 1993-06-30    | Argentina\n  1 | Ronda      | Skermer   | rskermer0@arstechnica.com | Female | 1993-06-30    | Argentina\n(2 rows)\n```\n\nHere, as we can see that, after dropping the primary key constrains, we can insert a duplicate row in the table.\n\nNow we will try to add primary key constraint in the `id` column.\t\n\n```\ntest=# ALTER TABLE person ADD PRIMARY KEY(id);\nERROR:  could not create unique index \"person_pkey\"\nDETAIL:  Key (id)=(1) is duplicated.\n```\n\nBut we had failed, as there is two-row containing the same id. Now delete one of the duplicate ids and again try to add a primary key.\n\n```\ntest=# DELETE FROM person WHERE id=1;\nDELETE 2\ntest=# SELECT * FROM person WHERE id=1;\n id | first_name | last_name | email | gender | date_of_birth | country_of_birth \n----+------------+-----------+-------+--------+---------------+------------------\n(0 rows)\n\ntest=# INSERT INTO person (id, first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES (1, 'Ronda', 'Skermer', 'rskermer0@arstechnica.com', 'Female', '1993-06-30', 'Argentina');\nINSERT 0 1\ntest=# SELECT * FROM person WHERE id=1;\n id | first_name | last_name |           email           | gender | date_of_birth | country_of_birth \n----+------------+-----------+---------------------------+--------+---------------+------------------\n  1 | Ronda      | Skermer   | rskermer0@arstechnica.com | Female | 1993-06-30    | Argentina\n(1 row)\n\ntest=# ALTER TABLE person ADD PRIMARY KEY(id);\nALTER TABLE\ntest=# \\d person;\n                                         Table \"public.person\"\n      Column      |          Type          | Collation | Nullable |              Default               \n------------------+------------------------+-----------+----------+------------------------------------\n id               | bigint                 |           | not null | nextval('person_id_seq'::regclass)\n first_name       | character varying(50)  |           | not null | \n last_name        | character varying(50)  |           | not null | \n email            | character varying(150) |           |          | \n gender           | character varying(7)   |           | not null | \n date_of_birth    | date                   |           | not null | \n country_of_birth | character varying(50)  |           | not null | \nIndexes:\n    \"person_pkey\" PRIMARY KEY, btree (id)\n\ntest=# \n\n```\nOur primary key constraint in the `id` column is back again.\n\n\n## CONSTRAINTS\n### UNIQUE constraint\nThe PostgreSQL `UNIQUE` constraint ensures that the uniqueness of the values entered into a column or a field of a table.\n\nThe `UNIQUE` constraint in PostgreSQL can be applied as a column constraint or a group of column constraint or a table constraint.\n\nThe `UNIQUE` constraint in PostgreSQL is violated when more than one row for a column or combination of columns which have been used as a unique constraint in a table. Two `NULL` values for a column in different rows are different, and it does not violate the uniqueness of the UNIQUE constraint.\n\nWhen a `UNIQUE` constraint is adding, an index on a column or group of columns creates automatically.\n\n\nWe are going to add a `UNIQUE CONSTRAINT` in the email field, and after that, we will delete the constraint of the field.\n\n```\ntest=# ALTER TABLE person ADD CONSTRAINT unique_email_addr UNIQUE(email);\nALTER TABLE\ntest=# \\d person;\n                                         Table \"public.person\"\n      Column      |          Type          | Collation | Nullable |              Default               \n------------------+------------------------+-----------+----------+------------------------------------\n id               | bigint                 |           | not null | nextval('person_id_seq'::regclass)\n first_name       | character varying(50)  |           | not null | \n last_name        | character varying(50)  |           | not null | \n email            | character varying(150) |           |          | \n gender           | character varying(7)   |           | not null | \n date_of_birth    | date                   |           | not null | \n country_of_birth | character varying(50)  |           | not null | \nIndexes:\n    \"person_pkey\" PRIMARY KEY, btree (id)\n    \"unique_email_addr\" UNIQUE CONSTRAINT, btree (email)\n\ntest=# ALTER TABLE person DROP CONSTRAINT unique_email_addr;\nALTER TABLE\n\ntest=# \\d person;\n                                         Table \"public.person\"\n      Column      |          Type          | Collation | Nullable |              Default               \n------------------+------------------------+-----------+----------+------------------------------------\n id               | bigint                 |           | not null | nextval('person_id_seq'::regclass)\n first_name       | character varying(50)  |           | not null | \n last_name        | character varying(50)  |           | not null | \n email            | character varying(150) |           |          | \n gender           | character varying(7)   |           | not null | \n date_of_birth    | date                   |           | not null | \n country_of_birth | character varying(50)  |           | not null | \nIndexes:\n    \"person_pkey\" PRIMARY KEY, btree (id)\n\n```\n\nAgain we will add unique constraints in the email field, but without mentioning the name of our constraint, the name of the constraint will be set by Postgres itself automatically.\n\n```\ntest=# ALTER TABLE person ADD UNIQUE(email);\nALTER TABLE\ntest=# \\d person;\n                                         Table \"public.person\"\n      Column      |          Type          | Collation | Nullable |              Default               \n------------------+------------------------+-----------+----------+------------------------------------\n id               | bigint                 |           | not null | nextval('person_id_seq'::regclass)\n first_name       | character varying(50)  |           | not null | \n last_name        | character varying(50)  |           | not null | \n email            | character varying(150) |           |          | \n gender           | character varying(7)   |           | not null | \n date_of_birth    | date                   |           | not null | \n country_of_birth | character varying(50)  |           | not null | \nIndexes:\n    \"person_pkey\" PRIMARY KEY, btree (id)\n    \"person_email_key\" UNIQUE CONSTRAINT, btree (email)\n\n```\n\n### CHECK Constraint\nThe PostgreSQL `CHECK` constraint controls the value of a column(s) being inserted.\n\nPostgreSQL provides the `CHECK` constraint, which allows the user to define a condition that a value entered into a table, has to satisfy before it can be accepted. The `CHECK` constraint consists of the keyword `CHECK`, followed by parenthesized conditions. The attempt will be rejected when update or insert column values that will make the condition false.\n\nThe `CHECK` constraint in PostgreSQL can be defined as a separate name.\n\n\n```\ntest=# ALTER TABLE person ADD CONSTRAINT gender_constraint CHECK (gender = 'Female' OR gender = 'Male');\nALTER TABLE\ntest=# \\d person;\n                                         Table \"public.person\"\n      Column      |          Type          | Collation | Nullable |              Default               \n------------------+------------------------+-----------+----------+------------------------------------\n id               | bigint                 |           | not null | nextval('person_id_seq'::regclass)\n first_name       | character varying(50)  |           | not null | \n last_name        | character varying(50)  |           | not null | \n email            | character varying(150) |           |          | \n gender           | character varying(7)   |           | not null | \n date_of_birth    | date                   |           | not null | \n country_of_birth | character varying(50)  |           | not null | \nIndexes:\n    \"person_pkey\" PRIMARY KEY, btree (id)\n    \"person_email_key\" UNIQUE CONSTRAINT, btree (email)\nCheck constraints:\n    \"gender_constraint\" CHECK (gender::text = 'Female'::text OR gender::text = 'Male'::text)\n\n```\n\n## DELETE\nFollowing is the usage of the PostgreSQL `DELETE` command to delete data of a PostgreSQL table.\n\n```\nDELETE FROM table_name ;\n```\n\nWhere `table_name` is the associated table, executing this command will delete all the rows of the associated table.\n\n```\nDELETE FROM table_name WHERE condition;\n```\n\nIf we don't want to delete all of the rows of a table, but some specific rows which match the \"condition\", execute the above.\n\n\nFirst, try to delete all records from a table.\n\n```\ntest=# DELETE FROM person;\nDELETE 1000\ntest=# SELECT * FROM person;\n id | first_name | last_name | email | gender | date_of_birth | country_of_birth \n----+------------+-----------+-------+--------+---------------+------------------\n(0 rows)\n\n```\n\nThere is no record in the `person` table now. For our learning purpose, retrieve data from the SQL file for the table again.\n\n```\ntest=# \\i /path/to/person.sql \npsql:/path/to/person.sql:9: ERROR:  relation \"person\" already exists\nINSERT 0 1\n--More--\ntest=# \\d person;\n                                         Table \"public.person\"\n      Column      |          Type          | Collation | Nullable |              Default               \n------------------+------------------------+-----------+----------+------------------------------------\n id               | bigint                 |           | not null | nextval('person_id_seq'::regclass)\n first_name       | character varying(50)  |           | not null | \n last_name        | character varying(50)  |           | not null | \n email            | character varying(150) |           |          | \n gender           | character varying(7)   |           | not null | \n date_of_birth    | date                   |           | not null | \n country_of_birth | character varying(50)  |           | not null | \nIndexes:\n    \"person_pkey\" PRIMARY KEY, btree (id)\n    \"person_email_key\" UNIQUE CONSTRAINT, btree (email)\nCheck constraints:\n    \"gender_constraint\" CHECK (gender::text = 'Female'::text OR gender::text = 'Male'::text)\n\ntest=# SELECT * FROM person LIMIT 10;\n  id  | first_name |   last_name   |             email              | gender | date_of_birth | country_of_birth \n------+------------+---------------+--------------------------------+--------+---------------+------------------\n 1002 | Ronda      | Skermer       | rskermer0@arstechnica.com      | Female | 1993-06-30    | Argentina\n 1003 | Hamid      | Abbett        | habbett1@cbc.ca                | Male   | 1995-08-31    | Ethiopia\n 1004 | Francis    | Nickerson     | fnickerson2@mac.com            | Male   | 1998-03-16    | Portugal\n 1005 | Erminie    | M'Quharg      | emquharg3@e-recht24.de         | Female | 1999-03-13    | Mozambique\n 1006 | Teodoro    | Trimmill      |                                | Male   | 1982-04-30    | China\n 1007 | Reilly     | Amesbury      | ramesbury5@businessinsider.com | Male   | 1990-12-31    | China\n 1008 | West       | Elphey        |                                | Male   | 2004-03-29    | Indonesia\n 1009 | Letta      | Caurah        | lcaurah7@yale.edu              | Female | 1994-09-09    | Indonesia\n 1010 | Elset      | Agass         | eagass8@rambler.ru             | Female | 2004-06-26    | China\n 1011 | Aurore     | Drillingcourt | adrillingcourt9@cnet.com       | Female | 1977-10-19    | China\n(10 rows)\n```\n\nNow try to delete a specific row or rows with the matching condition.\n\n```\ntest=# DELETE FROM person WHERE id = 1002;\nDELETE 1\ntest=# SELECT * FROM person LIMIT 10;\n  id  | first_name |   last_name   |             email              | gender | date_of_birth | country_of_birth \n------+------------+---------------+--------------------------------+--------+---------------+------------------\n 1003 | Hamid      | Abbett        | habbett1@cbc.ca                | Male   | 1995-08-31    | Ethiopia\n 1004 | Francis    | Nickerson     | fnickerson2@mac.com            | Male   | 1998-03-16    | Portugal\n 1005 | Erminie    | M'Quharg      | emquharg3@e-recht24.de         | Female | 1999-03-13    | Mozambique\n 1006 | Teodoro    | Trimmill      |                                | Male   | 1982-04-30    | China\n 1007 | Reilly     | Amesbury      | ramesbury5@businessinsider.com | Male   | 1990-12-31    | China\n 1008 | West       | Elphey        |                                | Male   | 2004-03-29    | Indonesia\n 1009 | Letta      | Caurah        | lcaurah7@yale.edu              | Female | 1994-09-09    | Indonesia\n 1010 | Elset      | Agass         | eagass8@rambler.ru             | Female | 2004-06-26    | China\n 1011 | Aurore     | Drillingcourt | adrillingcourt9@cnet.com       | Female | 1977-10-19    | China\n 1012 | Ilse       | Goldman       | igoldmana@ihg.com              | Female | 2001-07-31    | Mongolia\n(10 rows)\n\ntest=# DELETE FROM person WHERE gender='Female' AND country_of_birth='China';\nDELETE 94\ntest=# SELECT * FROM person WHERE gender='Female' AND country_of_birth='China';\n id | first_name | last_name | email | gender | date_of_birth | country_of_birth \n----+------------+-----------+-------+--------+---------------+------------------\n(0 rows)\n\n```\n\nFor our learning purpose, now we will delete every record from the person table and restore it from our SQL file.\n\n```\ntest=# DELETE FROM person;\nDELETE 905\ntest=# \\i /path/to/person.sql\npsql:/path/to/person.sql:9: ERROR:  relation \"person\" already exists\nINSERT 0 1\n--More--\n```\n\n\n## UPDATE\nUPDATE command is used to modify existing data of a table. \n\n```\ntest=# SELECT * FROM person;\n  id  |   first_name   |      last_name      |                  email                  | gender | date_of_birth |         country_of_birth         \n------+----------------+---------------------+-----------------------------------------+--------+---------------+----------------------------------\n 2002 | Ronda          | Skermer             | rskermer0@arstechnica.com               | Female | 1993-06-30    | Argentina\n 2003 | Hamid          | Abbett              | habbett1@cbc.ca                         | Male   | 1995-08-31    | Ethiopia\n 2004 | Francis        | Nickerson           | fnickerson2@mac.com                     | Male   | 1998-03-16    | Portugal\n 2005 | Erminie        | M'Quharg            | emquharg3@e-recht24.de                  | Female | 1999-03-13    | Mozambique\n 2006 | Teodoro        | Trimmill            |                                         | Male   | 1982-04-30    | China\n 2007 | Reilly         | Amesbury            | ramesbury5@businessinsider.com          | Male   | 1990-12-31    | China\n 2008 | West           | Elphey              |                                         | Male   | 2004-03-29    | Indonesia\n--More--\n\ntest=# UPDATE person SET email  = 'teodoro@gmail.com' WHERE id = 2006;\nUPDATE 1\ntest=# SELECT * FROM person WHERE id = 2006;\n  id  | first_name | last_name |       email       | gender | date_of_birth | country_of_birth \n------+------------+-----------+-------------------+--------+---------------+------------------\n 2006 | Teodoro    | Trimmill  | teodoro@gmail.com | Male   | 1982-04-30    | China\n(1 row)\n\ntest=# UPDATE person SET last_name = 'Trimmil', email = 'teodoro@hotmail.com' WHERE id = 2006;\nUPDATE 1\ntest=# SELECT * FROM person WHERE id = 2006;\n  id  | first_name | last_name |        email        | gender | date_of_birth | country_of_birth \n------+------------+-----------+---------------------+--------+---------------+------------------\n 2006 | Teodoro    | Trimmil   | teodoro@hotmail.com | Male   | 1982-04-30    | China\n(1 row)\n\n\n```\n\n## ON CONFLICT\n### DO NOTHING\nThis means do nothing if the row already exists in the table. It handles duplicate key errors.\n\n\nFirst, we try to enter the duplicate record.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nINSERT INTO person (id, first_name, last_name, gender, email, date_of_birth, country_of_birth)\nVALUES (2002, 'Ronda', 'Dante', 'Male', 'dante@hotmaill.com', DATE '1980-03-12', 'Sri Lanka');\n```\n\nAs expected, an ERROR message is thrown.\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\nERROR:  duplicate key value violates unique constraint \"person_pkey\"\nDETAIL:  Key (id)=(2002) already exists.\n```\n\nNow we try to enter the duplicate record with `ON CONFLICT(id) DO NOTHING` and handle the error.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nINSERT INTO person (id, first_name, last_name, gender, email, date_of_birth, country_of_birth)\nVALUES (2002, 'Ronda', 'Dante', 'Male', 'dante@hotmaill.com', DATE '1980-03-12', 'Sri Lanka')\nON CONFLICT(id) DO NOTHING;\n```\n\nThe output message is saying `0 0`, which means no insert operation is held.\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\nINSERT 0 0\n```\n\n### DO UPDATE SET\nThis update some fields in the table.\n\nWe will update this record in a way that conflicts with it.\n\n```\ntest=# SELECT * FROM person WHERE id = 2002;\n  id  | first_name | last_name |             email         | gender | date_of_birth | country_of_birth \n------+------------+-----------+---------------------------+--------+---------------+------------------\n 2002 | Ronda      | Skermer   | rskermer0@arstechnica.com | Female | 1993-06-30    | Argentina\n(1 row)\n\n```\n\nHere `EXCLUDED` refers to the new conflicted record which is trying to be inserted.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nINSERT INTO person (id, first_name, last_name, gender, email, date_of_birth, country_of_birth)\nVALUES (2002, 'Rudi', 'Donte', 'Male', 'donte@hotmaill.com', DATE '1980-03-12', 'Sri Lanka')\nON CONFLICT(id) DO UPDATE SET first_name=EXCLUDED.first_name, last_name=EXCLUDED.last_name, email=EXCLUDED.email;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\nINSERT 0 1\n```\n\nDespite the conflict, the updated record is:\n\n```\ntest=# SELECT * FROM person WHERE id = 2002;\n  id  | first_name | last_name |       email        | gender | date_of_birth | country_of_birth \n------+------------+-----------+--------------------+--------+---------------+------------------\n 2002 | Rudi       | Donte     | donte@hotmaill.com | Female | 1993-06-30    | Argentina\n(1 row)\n\n```\n\n\n## Foreign Keys, Joins and Relationships\n![Forign Key, Primary Key and Relations](https://imgur.com/N0Qcfe8.jpg, \"Forign Key, Primary Key and Relations\")\n\n\nAdding relations between tables\nWe will now drop the previous tables and create new ones with relations.\n\n```\ntest=# \\dt\n           List of relations\n Schema |  Name  | Type  |    Owner     \n--------+--------+-------+--------------\n public | car    | table | arafat_hasan\n public | person | table | arafat_hasan\n(2 rows)\n\ntest=# DROP TABLE car;\nDROP TABLE\ntest=# DROP TABLE person;\nDROP TABLE\ntest=# \\dt\nDid not find any relations.  \ntest=# \\i /path/to/new/file/car-person.sql \nCREATE TABLE\nCREATE TABLE\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\nINSERT 0 1\ntest=# \\dt\n           List of relations\n Schema |  Name  | Type  |    Owner     \n--------+--------+-------+--------------\n public | car    | table | arafat_hasan\n public | person | table | arafat_hasan\n(2 rows)\n\n```\n\n\nOur new SQL file, which is named `car-person.sql` is in bellow:\n\n```sql\nCREATE TABLE car (\n\tid BIGSERIAL NOT NULL PRIMARY KEY,\n\tmake VARCHAR(100) NOT NULL,\n\tmodel VARCHAR(100) NOT NULL,\n\tprice NUMERIC(19, 2) NOT NULL\n);\n\n\nCREATE TABLE person (\n\tid BIGSERIAL NOT NULL PRIMARY KEY,\n\tfirst_name VARCHAR(50) NOT NULL,\n\tlast_name VARCHAR(50) NOT NULL,\n\temail VARCHAR(150),\n\tgender VARCHAR(7) NOT NULL,\n\tdate_of_birth DATE NOT NULL,\n\tcountry_of_birth VARCHAR(50) NOT NULL,\n\tcar_id BIGINT REFERENCES car(id),\n\tUNIQUE(car_id)\n);\n\n\nINSERT INTO car (make, model, price) VALUES ('Daewoo', 'Leganza', '241058.40');\nINSERT INTO car (make, model, price) VALUES ('Mitsubishi', 'Montero', '269595.21');\nINSERT INTO car (make, model, price) VALUES ('Kia', 'Rio', '245275.16');\nINSERT INTO car (make, model, price) VALUES ('Jaguar', 'X-Type', '41665.96');\nINSERT INTO car (make, model, price) VALUES ('Lincoln', 'Mark VIII', '163843.38');\nINSERT INTO car (make, model, price) VALUES ('GMC', 'Rally Wagon 3500', '231169.05');\nINSERT INTO car (make, model, price) VALUES ('Cadillac', 'Escalade ESV', '279951.34');\n\n\nINSERT INTO person (first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES ('Hamid', 'Abbett', 'habbett1@cbc.ca', 'Male', '1995-08-31', 'Ethiopia');\nINSERT INTO person (first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES ('Francis', 'Nickerson', 'fnickerson2@mac.com', 'Male', '1998-03-16', 'Portugal');\nINSERT INTO person (first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES ('Erminie', 'M''Quharg', 'emquharg3@e-recht24.de', 'Female', '1999-03-13', 'Mozambique');\nINSERT INTO person (first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES ('Teodoro', 'Trimmill', null, 'Male', '1982-04-30', 'China');\nINSERT INTO person (first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES ('Reilly', 'Amesbury', 'ramesbury5@businessinsider.com', 'Male', '1990-12-31', 'China');\nINSERT INTO person (first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES ('West', 'Elphey', null, 'Male', '2004-03-29', 'Indonesia');\nINSERT INTO person (first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES ('Letta', 'Caurah', 'lcaurah7@yale.edu', 'Female', '1994-09-09', 'Indonesia');\nINSERT INTO person (first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES ('Elset', 'Agass', 'eagass8@rambler.ru', 'Female', '2004-06-26', 'China');\nINSERT INTO person (first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES ('Aurore', 'Drillingcourt', 'adrillingcourt9@cnet.com', 'Female', '1977-10-19', 'China');\nINSERT INTO person (first_name, last_name, email, gender, date_of_birth, country_of_birth) VALUES ('Ilse', 'Goldman', 'igoldmana@ihg.com', 'Female', '2001-07-31', 'Mongolia');\n\n```\n\n\nLet's take a look at the two new tables to see what's inside.\n\n```\ntest=# SELECT * FROM person;\n id | first_name |   last_name   |             email              | gender | date_of_birth | country_of_birth | car_id \n----+------------+---------------+--------------------------------+--------+---------------+------------------+--------\n  1 | Hamid      | Abbett        | habbett1@cbc.ca                | Male   | 1995-08-31    | Ethiopia         |       \n  2 | Francis    | Nickerson     | fnickerson2@mac.com            | Male   | 1998-03-16    | Portugal         |       \n  3 | Erminie    | M'Quharg      | emquharg3@e-recht24.de         | Female | 1999-03-13    | Mozambique       |       \n  4 | Teodoro    | Trimmill      |                                | Male   | 1982-04-30    | China            |       \n  5 | Reilly     | Amesbury      | ramesbury5@businessinsider.com | Male   | 1990-12-31    | China            |       \n  6 | West       | Elphey        |                                | Male   | 2004-03-29    | Indonesia        |       \n  7 | Letta      | Caurah        | lcaurah7@yale.edu              | Female | 1994-09-09    | Indonesia        |       \n  8 | Elset      | Agass         | eagass8@rambler.ru             | Female | 2004-06-26    | China            |       \n  9 | Aurore     | Drillingcourt | adrillingcourt9@cnet.com       | Female | 1977-10-19    | China            |       \n 10 | Ilse       | Goldman       | igoldmana@ihg.com              | Female | 2001-07-31    | Mongolia         |       \n(10 rows)\n\ntest=# SELECT * FROM car;\n id |    make    |      model       |   price   \n----+------------+------------------+-----------\n  1 | Daewoo     | Leganza          | 241058.40\n  2 | Mitsubishi | Montero          | 269595.21\n  3 | Kia        | Rio              | 245275.16\n  4 | Jaguar     | X-Type           |  41665.96\n  5 | Lincoln    | Mark VIII        | 163843.38\n  6 | GMC        | Rally Wagon 3500 | 231169.05\n  7 | Cadillac   | Escalade ESV     | 279951.34\n(7 rows)\n\n```\n\n\nAs expected, there is no value in the `car_id` column in `person` as we did not insert any value there.\n\nAs can be seen below, we have set the foreign key correctly, and it has a UNIQUE constraint and `car_id` referencing to `car.id`.\n\n```\ntest=# \\d person;\n                                         Table \"public.person\"\n      Column      |          Type          | Collation | Nullable |              Default               \n------------------+------------------------+-----------+----------+------------------------------------\n id               | bigint                 |           | not null | nextval('person_id_seq'::regclass)\n first_name       | character varying(50)  |           | not null | \n last_name        | character varying(50)  |           | not null | \n email            | character varying(150) |           |          | \n gender           | character varying(7)   |           | not null | \n date_of_birth    | date                   |           | not null | \n country_of_birth | character varying(50)  |           | not null | \n car_id           | bigint                 |           |          | \nIndexes:\n    \"person_pkey\" PRIMARY KEY, btree (id)\n    \"person_car_id_key\" UNIQUE CONSTRAINT, btree (car_id)\nForeign-key constraints:\n    \"person_car_id_fkey\" FOREIGN KEY (car_id) REFERENCES car(id)\n\n\n```\n\n\nLet's assign the Mitsubishi, which ID is 2 from the car table to Hamid Abbett of the person table which ID is 1.\n\n```\ntest=# UPDATE person SET car_id = 2 WHERE id = 1;\nUPDATE 1\ntest=# SELECT * FROM person;\n id | first_name |   last_name   |             email              | gender | date_of_birth | country_of_birth | car_id \n----+------------+---------------+--------------------------------+--------+---------------+------------------+--------\n  2 | Francis    | Nickerson     | fnickerson2@mac.com            | Male   | 1998-03-16    | Portugal         |       \n  3 | Erminie    | M'Quharg      | emquharg3@e-recht24.de         | Female | 1999-03-13    | Mozambique       |       \n  4 | Teodoro    | Trimmill      |                                | Male   | 1982-04-30    | China            |       \n  5 | Reilly     | Amesbury      | ramesbury5@businessinsider.com | Male   | 1990-12-31    | China            |       \n  6 | West       | Elphey        |                                | Male   | 2004-03-29    | Indonesia        |       \n  7 | Letta      | Caurah        | lcaurah7@yale.edu              | Female | 1994-09-09    | Indonesia        |       \n  8 | Elset      | Agass         | eagass8@rambler.ru             | Female | 2004-06-26    | China            |       \n  9 | Aurore     | Drillingcourt | adrillingcourt9@cnet.com       | Female | 1977-10-19    | China            |       \n 10 | Ilse       | Goldman       | igoldmana@ihg.com              | Female | 2001-07-31    | Mongolia         |       \n  1 | Hamid      | Abbett        | habbett1@cbc.ca                | Male   | 1995-08-31    | Ethiopia         |      2\n(10 rows)\n\n```\n\nLet's also add a car to Francis Nickerson.\n\n```\nUPDATE person SET car_id = 1 WHERE id = 2;\n```\n\nLet's try to give one car to two people and see what happens.\n\n```\ntest=# UPDATE person SET car_id = 1 WHERE id = 3;\nERROR:  duplicate key value violates unique constraint \"person_car_id_key\"\nDETAIL:  Key (car_id)=(1) already exists.\n```\n\nOkay, now assign other cars to specific persons. This is the final table.\n\n```\n id | first_name |   last_name   |             email              | gender | date_of_birth | country_of_birth | car_id \n----+------------+---------------+--------------------------------+--------+---------------+------------------+--------\n  5 | Reilly     | Amesbury      | ramesbury5@businessinsider.com | Male   | 1990-12-31    | China            |       \n  9 | Aurore     | Drillingcourt | adrillingcourt9@cnet.com       | Female | 1977-10-19    | China            |       \n 10 | Ilse       | Goldman       | igoldmana@ihg.com              | Female | 2001-07-31    | Mongolia         |       \n  1 | Hamid      | Abbett        | habbett1@cbc.ca                | Male   | 1995-08-31    | Ethiopia         |      2\n  2 | Francis    | Nickerson     | fnickerson2@mac.com            | Male   | 1998-03-16    | Portugal         |      1\n  3 | Erminie    | M'Quharg      | emquharg3@e-recht24.de         | Female | 1999-03-13    | Mozambique       |      7\n  4 | Teodoro    | Trimmill      |                                | Male   | 1982-04-30    | China            |      5\n  8 | Elset      | Agass         | eagass8@rambler.ru             | Female | 2004-06-26    | China            |      4\n  7 | Letta      | Caurah        | lcaurah7@yale.edu              | Female | 1994-09-09    | Indonesia        |      6\n  6 | West       | Elphey        |                                | Male   | 2004-03-29    | Indonesia        |      3\n(10 rows)\n\n```\n\n### Delete Record with Foreign Keys\n\n\n```\ntest=# DELETE FROM car WHERE id = 7;\nERROR:  update or delete on table \"car\" violates foreign key constraint \"person_car_id_fkey\" on table \"person\"\nDETAIL:  Key (id)=(7) is still referenced from table \"person\".\ntest=# DELETE FROM person WHERE id = 3;\nDELETE 1\ntest=# SELECT * FROM person;\n id | first_name |   last_name   |             email              | gender | date_of_birth | country_of_birth | car_id \n----+------------+---------------+--------------------------------+--------+---------------+------------------+--------\n  5 | Reilly     | Amesbury      | ramesbury5@businessinsider.com | Male   | 1990-12-31    | China            |       \n  9 | Aurore     | Drillingcourt | adrillingcourt9@cnet.com       | Female | 1977-10-19    | China            |       \n 10 | Ilse       | Goldman       | igoldmana@ihg.com              | Female | 2001-07-31    | Mongolia         |       \n  1 | Hamid      | Abbett        | habbett1@cbc.ca                | Male   | 1995-08-31    | Ethiopia         |      2\n  2 | Francis    | Nickerson     | fnickerson2@mac.com            | Male   | 1998-03-16    | Portugal         |      1\n  4 | Teodoro    | Trimmill      |                                | Male   | 1982-04-30    | China            |      5\n  8 | Elset      | Agass         | eagass8@rambler.ru             | Female | 2004-06-26    | China            |      4\n  7 | Letta      | Caurah        | lcaurah7@yale.edu              | Female | 1994-09-09    | Indonesia        |      6\n  6 | West       | Elphey        |                                | Male   | 2004-03-29    | Indonesia        |      3\n(9 rows)\n```\n\nIt turns out that we can't delete a record which is assigned with the `person` table from the `car` table, but we can delete any record from the `person` table. This is because there is a relation from the `person` table to the `car` table.\n\nTo delete a record from the `car` table, we have to delete the corresponding record in the `person` table or set the `car_id` of that record to NULL.\n\n\n\n\n\n## JOIN\nA JOIN clause is used to combine rows from two or more tables, based on a related column between them.\n\n### INNER JOIN\n\nThe INNER JOIN keyword selects records that have matching values in both tables.\n\nThe INNER JOIN creates a new result table by combining column values of two tables (table1 and table2) based upon the join-predicate. The query compares each row of table1 with each row of table2 to find all pairs of rows which satisfy the join-predicate. When the join-predicate is satisfied, column values for each matched pair of rows of A and B are combined into a result row.\n\n```sql\nSELECT column_name(s)\nFROM table1\nINNER JOIN table2\nON table1.column_name = table2.column_name;\n```\n\n![INNER JOIN](https://imgur.com/oQjyWQa.jpg, \"INNER JOIN\")\n\n\nNow let's join our tables based on foreign keys.\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT * FROM person\nJOIN car ON person.car_id = car.id;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n id | first_name | last_name |         email          | gender | date_of_birth | country_of_birth | car_id | id |    make    |      model       |   price   \n----+------------+-----------+------------------------+--------+---------------+------------------+--------+----+------------+------------------+-----------\n  2 | Francis    | Nickerson | fnickerson2@mac.com    | Male   | 1998-03-16    | Portugal         |      1 |  1 | Daewoo     | Leganza          | 241058.40\n  1 | Hamid      | Abbett    | habbett1@cbc.ca        | Male   | 1995-08-31    | Ethiopia         |      2 |  2 | Mitsubishi | Montero          | 269595.21\n  6 | West       | Elphey    |                        | Male   | 2004-03-29    | Indonesia        |      3 |  3 | Kia        | Rio              | 245275.16\n  8 | Elset      | Agass     | eagass8@rambler.ru     | Female | 2004-06-26    | China            |      4 |  4 | Jaguar     | X-Type           |  41665.96\n  4 | Teodoro    | Trimmill  |                        | Male   | 1982-04-30    | China            |      5 |  5 | Lincoln    | Mark VIII        | 163843.38\n  7 | Letta      | Caurah    | lcaurah7@yale.edu      | Female | 1994-09-09    | Indonesia        |      6 |  6 | GMC        | Rally Wagon 3500 | 231169.05\n  3 | Erminie    | M'Quharg  | emquharg3@e-recht24.de | Female | 1999-03-13    | Mozambique       |      7 |  7 | Cadillac   | Escalade ESV     | 279951.34\n(7 rows)\n\n```\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT person.first_name, person.last_name, car.make, car.model, car.price\nFROM person\nJOIN car ON person.car_id = car.id;\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n first_name | last_name |    make    |      model       |   price   \n------------+-----------+------------+------------------+-----------\n Francis    | Nickerson | Daewoo     | Leganza          | 241058.40\n Hamid      | Abbett    | Mitsubishi | Montero          | 269595.21\n West       | Elphey    | Kia        | Rio              | 245275.16\n Elset      | Agass     | Jaguar     | X-Type           |  41665.96\n Teodoro    | Trimmill  | Lincoln    | Mark VIII        | 163843.38\n Letta      | Caurah    | GMC        | Rally Wagon 3500 | 231169.05\n Erminie    | M'Quharg  | Cadillac   | Escalade ESV     | 279951.34\n(7 rows)\n\n```\n\n### LEFT JOIN\n\nThe LEFT JOIN keyword returns all records from the left table (table1), and the matched records from the right table (table2). The result is NULL from the right side, if there is no match.\n\n![LEFT JOIN](https://imgur.com/sS5mapo.jpg, \"LEFT JOIN\")\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\nSELECT person.first_name, person.last_name, car.make, car.model, car.price\nFROM person\nLEFT JOIN car ON person.car_id = car.id;\n\n```\n\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\n first_name |   last_name   |    make    |      model       |   price   \n------------+---------------+------------+------------------+-----------\n Francis    | Nickerson     | Daewoo     | Leganza          | 241058.40\n Hamid      | Abbett        | Mitsubishi | Montero          | 269595.21\n West       | Elphey        | Kia        | Rio              | 245275.16\n Elset      | Agass         | Jaguar     | X-Type           |  41665.96\n Teodoro    | Trimmill      | Lincoln    | Mark VIII        | 163843.38\n Letta      | Caurah        | GMC        | Rally Wagon 3500 | 231169.05\n Erminie    | M'Quharg      | Cadillac   | Escalade ESV     | 279951.34\n Ilse       | Goldman       |            |                  |          \n Aurore     | Drillingcourt |            |                  |          \n Reilly     | Amesbury      |            |                  |          \n(10 rows)\n\n```\n\n\n### RIGHT JOIN\nThe RIGHT JOIN keyword returns all records from the right table (table2), and the matched records from the left table (table1). The result is NULL from the left side, when there is no match.\n\n\n![RIGHT JOIN](https://imgur.com/5ex2jIP.jpg, \"RIGHT JOIN\")\n\n\n\n### FULL OUTER JOIN\nThe FULL OUTER JOIN keyword returns all records when there are a match in left (table1) or right (table2) table records.\n\nNote: FULL OUTER JOIN can potentially return very large result-sets!\n\nFULL OUTER JOIN and FULL JOIN are the same.\n\n![FULL OUTER JOIN](https://imgur.com/AUaYHON.jpg, \"FULL OUTER JOIN\")\n\n\n## Exporting Query Results to CSV\n\n\nBy typing `\\?` and check the help. In the Input/Output section, it says that `\\copy ...    perform SQL COPY with data stream to the client host`.\n\n\nWe will save this query to a CSV file.\n\n```\ntest=# SELECT person.first_name, person.last_name, car.make, car.model, car.price\nFROM person\nLEFT JOIN car ON person.car_id = car.id;\n first_name |   last_name   |    make    |      model       |   price   \n------------+---------------+------------+------------------+-----------\n Francis    | Nickerson     | Daewoo     | Leganza          | 241058.40\n Hamid      | Abbett        | Mitsubishi | Montero          | 269595.21\n West       | Elphey        | Kia        | Rio              | 245275.16\n Elset      | Agass         | Jaguar     | X-Type           |  41665.96\n Teodoro    | Trimmill      | Lincoln    | Mark VIII        | 163843.38\n Letta      | Caurah        | GMC        | Rally Wagon 3500 | 231169.05\n Ilse       | Goldman       |            |                  |          \n Aurore     | Drillingcourt |            |                  |          \n Reilly     | Amesbury      |            |                  |          \n(9 rows)\n\n```\n\n\n\u003csub\u003e_Command_\u003c/sub\u003e\n```sql\n\\copy (SELECT person.first_name, person.last_name, car.make, car.model, car.price FROM person LEFT JOIN car ON car.id = person.car_id) TO '/home/arafat_hasan/Downloads/results.csv' DELIMITER ',' CSV HEADER\n\n```\n\u003csub\u003e_Output_\u003c/sub\u003e\n```\nCOPY 9\n\n```\nThe query is stored in the CSV file.\n\n\n\n## Serials and Sequences\n```\ntest=# \\d person;\n                                         Table \"public.person\"\n      Column      |          Type          | Collation | Nullable |              Default               \n------------------+------------------------+-----------+----------+------------------------------------\n id               | bigint                 |           | not null | nextval('person_id_seq'::regclass)\n first_name       | character varying(50)  |           | not null | \n last_name        | character varying(50)  |           | not null | \n email            | character varying(150) |           |          | \n gender           | character varying(7)   |           | not null | \n date_of_birth    | date                   |           | not null | \n country_of_birth | character varying(50)  |           | not null | \n car_id           | bigint                 |           |          | \nIndexes:\n    \"person_pkey\" PRIMARY KEY, btree (id)\n    \"person_car_id_key\" UNIQUE CONSTRAINT, btree (car_id)\nForeign-key constraints:\n    \"person_car_id_fkey\" FOREIGN KEY (car_id) REFERENCES car(id)\n\ntest=# SELECT * FROM person_id_seq ;\n last_value | log_cnt | is_called \n------------+---------+-----------\n         10 |      23 | t\n(1 row)\n\ntest=# SELECT nextval('person_id_seq'::regclass);\n nextval \n---------\n      11\n(1 row)\n\ntest=# SELECT nextval('person_id_seq'::regclass);\n nextval \n---------\n      12\n(1 row)\n\ntest=# SELECT * FROM person_id_seq ;\n last_value | log_cnt | is_called \n------------+---------+-----------\n         12 |      32 | t\n(1 row)\n\ntest=# ALTER SEQUENCE person_id_seq RESTART WITH 10;\nALTER SEQUENCE\ntest=# SELECT * FROM person_id_seq ;\n last_value | log_cnt | is_called \n------------+---------+-----------\n         10 |       0 | f\n(1 row)\n\n```\n\n\n\n## Extensions\n\nSimply extensions are functions that can add extra functionality to the database.\n\nList of available extensions\n\n```\ntest=# SELECT * FROM pg_available_extensions;\n  name   | default_version | installed_version |           comment            \n---------+-----------------+-------------------+------------------------------\n plpgsql | 1.0             | 1.0               | PL/pgSQL procedural language\n(1 row)\n\n```\n\n## UUID Datatype\n\nFrom wikipedia:\n    \u003e A universally unique identifier (UUID) is a 128-bit number used to identify information in computer systems. The term globally unique identifier (GUID) is also used, typically in software created by Microsoft.\n\n    \u003e When generated according to the standard methods, UUIDs are, for practical purposes, unique. Their uniqueness does not depend on a central registration authority or coordination between the parties generating them, unlike most other numbering schemes. While the probability that a UUID will be duplicated is not zero, it is close enough to zero to be negligible. \n\n\n\nWe have to add the uuid-ossp extension:\n```\nCREATE EXTENSION \"uuid-ossp\";\n```\n\nList of a available functions:\n\n```\n\\df\n```\n\nNow we have to invoke the function:\n```\nSELECT uuid_generate_v4();\n```\n\n```\nANLONGUUID\n```\n\n### UUID as Primary Key\n\nDrop `person` and `car` table and create another ones as below.\n\n\n```sql\nCREATE TABLE car (\n\tcar_uid UUID NOT NULL PRIMARY KEY,\n\tmake VARCHAR(100) NOT NULL,\n\tmodel VARCHAR(100) NOT NULL,\n\tprice NUMERIC(19, 2) NOT NULL\n);\n\n\nCREATE TABLE person (\n\tperson_uid UUID NOT NULL PRIMARY KEY,\n\tfirst_name VARCHAR(50) NOT NULL,\n\tlast_name VARCHAR(50) NOT NULL,\n\temail VARCHAR(150),\n\tgender VARCHAR(7) NOT NULL,\n\tdate_of_birth DATE NOT NULL,\n\tcountry_of_birth VARCHAR(50) NOT NULL,\n\tcar_uid UUID REFERENCES car(car_uid),\n\tUNIQUE(car_uid),\n\tUNIQUE(email)\n);\n\n\n\nINSERT INTO car (car_uid, make, model, price) \nVALUES (uuid_generate_v4(), uuid_generate_v4(), 'Mitsubishi', 'Montero', '269595.21');\n\nINSERT INTO car (car_uid, make, model, price) \nVALUES (uuid_generate_v4(), uuid_generate_v4(), 'Kia', 'Rio', '245275.16');\n\nINSERT INTO car (car_uid, make, model, price) \nVALUES (uuid_generate_v4(), uuid_generate_v4(), 'Jaguar', 'X-Type', '41665.96');\n\nINSERT INTO car (car_uid, make, model, price) \nVALUES (uuid_generate_v4(), uuid_generate_v4(), 'Lincoln', 'Mark VIII', '163843.38');\n\n\n\n\nINSERT INTO person (person_uid, first_name, last_name, email, gender, date_of_birth, country_of_birth) \nVALUES (uuid_generate_v4(), uuid_generate_v4(), 'Hamid', 'Abbett', 'habbett1@cbc.ca', 'Male', '1995-08-31', 'Ethiopia');\n\nINSERT INTO person (person_uid, first_name, last_name, email, gender, date_of_birth, country_of_birth) \nVALUES (uuid_generate_v4(), uuid_generate_v4(), 'Francis', 'Nickerson', 'fnickerson2@mac.com', 'Male', '1998-03-16', 'Portugal');\n\nINSERT INTO person (person_uid, first_name, last_name, email, gender, date_of_birth, country_of_birth) \nVALUES (uuid_generate_v4(), uuid_generate_v4(), 'Erminie', 'M''Quharg', 'emquharg3@e-recht24.de', 'Female', '1999-03-13', 'Mozambique');\n\nINSERT INTO person (person_uid, first_name, last_name, email, gender, date_of_birth, country_of_birth) \nVALUES (uuid_generate_v4(), uuid_generate_v4(), 'Teodoro', 'Trimmill', null, 'Male', '1982-04-30', 'China');\n\nINSERT INTO person (person_uid, first_name, last_name, email, gender, date_of_birth, country_of_birth) \nVALUES (uuid_generate_v4(), uuid_generate_v4(), 'Reilly', 'Amesbury', 'ramesbury5@businessinsider.com', 'Male', '1990-12-31', 'China');\n\nINSERT INTO person (person_uid, first_name, last_name, email, gender, date_of_birth, country_of_birth) \nVALUES (uuid_generate_v4(), uuid_generate_v4(), 'West', 'Elphey', null, 'Male', '2004-03-29', 'Indonesia');\n\nINSERT INTO person (person_uid, first_name, last_name, email, gender, date_of_birth, country_of_birth) \nVALUES (uuid_generate_v4(), uuid_generate_v4(), 'Letta', 'Caurah', 'lcaurah7@yale.edu', 'Female', '1994-09-09', 'Indonesia');\n\n```\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farafat-hasan%2Fpostgres-notes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farafat-hasan%2Fpostgres-notes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farafat-hasan%2Fpostgres-notes/lists"}