Vous êtes sur la page 1sur 29

EnterpriseDB PostgreSQL Exercises

From Artesano
Jump to: navigation, search

Contents
[hide]

 1 Module 4: Configuration
o 1.1 Lab Exercise 1
o 1.2 Lab Exercise 2
 2 Module 5: Creating and managing databases
o 2.1 Lab exercise 1
o 2.2 Lab exercise 2
o 2.3 Lab exercise 3
 3 Module 6 - PSQL
o 3.1 Lab exercise 1
 4 Module 8 - Security
o 4.1 Lab exercise 1
o 4.2 Lab exercise 2
o 4.3 Lab exercise 3
o 4.4 Lab exercise 4
 5 Module 9: SQL Primer
o 5.1 Lab exercise 1
o 5.2 Lab exercise 2
o 5.3 Lab exercise 3
o 5.4 Lab exercise 4
o 5.5 Lab exercise 5
 6 Module 10: Backup/Restore and PITR
o 6.1 Lab exercise 1
o 6.2 Lab exercise 2
o 6.3 Lab exercise 3
o 6.4 Lab exercise 4
o 6.5 Lab exercise 5
 7 Module 11: Routine Maintenance Tasks
o 7.1 Lab exercise 1
o 7.2 Lab exercise 2
 8 Module 13: Moving Data
o 8.1 Lab exercise 1
o 8.2 Lab exercise 2
Module 4: Configuration
Lab Exercise 1

Changes is server parameter file:

- Server must allow up to 200 connected users

max_connections = 200

- Server should reserve 10 connections slots for DBA

superuser_reserved_connections = 10

- Maximum time to complete client authentication will be 10 seconds

authentication_timeout = 10s

Note: The change to max_connections forced me to increase the kernel variable shmmax and
shmall (shared memory).

HowTo:

In the shell (temporarily):

$ sysctl -w kernel.shmmax=134217728
$ sysctl -w kernel.shmall=2097152

Or

$ echo 134217728 >/proc/sys/kernel/shmmax


$ echo 2097152 >/proc/sys/kernel/shmall

To make the change permanent:

Add these lines to /etc/sysctl.conf

kernel.shmmax=134217728
kernel.shmall=2097152

Lab Exercise 2

Go through server parameters for logging and implement the following:

- Save all error messages in a file inside pg_log folder in your cluster data directory
logging_collector = on -- Needed for redirecting the stderr to a file log_directory =
'/var/lib/postgresql/9.1/main/pg_log' -- Absolute because PGDATA is not set

- Log all queries and their time which are taking more than 5 seconds to execute

log_min_duration_statement = 5s -- or using the default unit ms log_min_duration_statement =


5000

- Log the users who are connecting to the database cluster

log_connections = on

- Make changes and verify them. Here is the verification:

$ sudo service postgresql restart


* Restarting PostgreSQL 9.1 database server
$ sudo ls -al /var/lib/postgresql/9.1/main/pg_log
[...]
-rw------- 1 postgres postgres 789 Feb 14 13:02 postgresql-2013-02-
14_130159.log
$ psql charles
psql# SELECT pg_sleep(6);
psql# SELECT pg_sleep(4);
psql# SELECT pg_sleep(7);
psql# \q
$ sudo view /var/lib/postgresql/9.1/main/pg_log/postgresql-2013-02-
14_130159.log
2013-02-14 13:26:43 CET LOG: database system was shut down at 2013-02-14
13:26:41 CET
2013-02-14 13:26:43 CET LOG: autovacuum launcher started
2013-02-14 13:26:43 CET LOG: database system is ready to accept connections
2013-02-14 13:27:30 CET LOG: connection received: host=[local]
2013-02-14 13:27:30 CET LOG: connection authorized: user=charles
database=charles
2013-02-14 13:27:50 CET LOG: duration: 6002.420 ms statement: SELECT
pg_sleep(6);
2013-02-14 13:28:10 CET LOG: duration: 7001.457 ms statement: SELECT
pg_sleep(7);

Note: Alternatively it is possible to restart the server using:

$ sudo -u postgres pg_ctl restart -D /var/lib/postgresql/9.1/main/ -m fast


waiting for server to shut down.... done
server stopped
server starting

Additional note: The first trying to start the database using pg_ctl brought an error, because the
server was looking for the postgresql.conf file in the data directory. On my (Ubuntu) installation
the file is located in /etc/postgresql/9.1/main/. For the server to start up I added a simlink in the
data directory pointing to the conf file:
$ sudo ln -s /etc/postgresql/9.1/main/postgresql.conf
/var/lib/postgresql/9.1/main/postgresql.conf

Module 5: Creating and managing databases


Lab exercise 1

- Create a database user edbstore in your existing cluster

charles=# CREATE ROLE edbstore LOGIN;

Or

charles=# CREATE USER edbstore;

Note: The exercise does not explicitly require to create a password for the user. Later, in order to
login, we will have do alter the role and add a password. This could have been done already
explicitly now:

charles=# CREATE ROLE edbstore LOGIN PASSWORD '12345';

- Create a edbstore database with ownership of edbstore user

charles=# CREATE DATABASE edbstore OWNER edbstore;


charles=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access
privileges
-----------+----------+----------+-------------+-------------+---------------
--------
charles | charles | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
edbstore | edbstore | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
+
| | | | |
postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
+
| | | | |
postgres=CTc/postgres

- Login inside edbstore database using edbstore user and create edbstore schema

We must first assign a password to role edbstore

charles=# ALTER USER edbstore PASSWORD '12345';


charles=# \q
charles@charles-development:~$ psql -U edbstore -h localhost
Password for user edbstore:
psql (9.1.8)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

edbstore=> select current_user;


current_user
--------------
edbstore

edbstore=# CREATE SCHEMA edbstore;


CREATE SCHEMA
edbstore=# \dn
List of schemas
Name | Owner
----------+----------
edbstore | edbuser
public | postgres

Note: The creation of the schema is possible, because edbstore is the owner of the database.

Since the role name and the schema name are the same and search_path has as a first entry $user,
any new objects will be created in schema edbstore:

edbstore=> show search_path;


search_path
----------------
"$user",public
edbstore=> CREATE TABLE test (id int);
CREATE TABLE
edbstore=> \dt
List of relations
Schema | Name | Type | Owner
----------+------+-------+----------
edbstore | test | table | edbstore
edbstore=> drop table test;
DROP TABLE

Lab exercise 2

- Create an ebuy user with password 'lion'

The role edbuser has no permissions to create users. Either we assign that role to it or we create
the user with another superuser (e.g. postgres).

edbstore=> CREATE ROLE ebuy LOGIN PASSWORD 'lion'; ERROR: permission denied to
create role

We opt for variant 1

edbstore=> \q
charles@charles-development:~$ psql edbstore
psql (9.1.8)
Type "help" for help.
edbstore=# select current_user;
current_user
--------------
charles

edbstore=# ALTER ROLE edbstore CREATEROLE;


ALTER ROLE

Now we can login again as edbstore and do the rest.

edbstore=# \q
charles@charles-development:~$ psql -U edbstore -h localhost
Password for user edbstore:
psql (9.1.8)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

edbstore=> select current_user;


current_user
--------------
edbstore
edbstore=> CREATE ROLE ebuy LOGIN PASSWORD 'lion';
CREATE ROLE

- Create an ebuy schema which can be used by ebuy user.

Being logged in as edbstore we can create a schema with the same name as the user.

edbstore=> CREATE SCHEMA ebuy;


CREATE SCHEMA
edbstore=> \dn
List of schemas
Name | Owner
----------+----------
ebuy | edbstore
edbstore | edbstore
public | postgres

And grant create and usage on it to ebuy:

edbstore=> GRANT CREATE, USAGE ON SCHEMA ebuy TO ebuy;

- Login as ebuy user, create a table sample1 and check whether that table belongs to ebuy
schema or not.

edbstore=> \q
charles@charles-development:~$ psql -d edbstore -U ebuy -h localhost
Password for user ebuy:
psql (9.1.8)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.
edbstore=> CREATE TABLE sample1 (id int);
CREATE TABLE
edbstore=> \dt
List of relations
Schema | Name | Type | Owner
--------+---------+-------+-------
ebuy | sample1 | table | ebuy

The table was created in schema ebuy, because it matches $user, i.e. the first entry in
search_path.

Note: If you are logged in as an admin you can create the role and the schema directly and assign
the ownership of the schema to ebuy:

charles=# CREATE ROLE ebuy LOGIN PASSWORD 'lion';


charles=# CREATE SCHEMA ebuy AUTHORIZATION ebuy;

If you do it that way then the list of schemas looks as follows:

edbstore=# \dn
List of schemas
Name | Owner
----------+----------
ebuy | ebuy
edbstore | edbstore
public | postgres

Lab exercise 3

- Retrieve a list of databases using an SQL query and psql meta command.

edbstore=> select datname from pg_database;


datname
-----------
template1
template0
postgres
charles
edbstore
edbstore=> \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access
privileges
-----------+----------+----------+-------------+-------------+---------------
--------
charles | charles | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
edbstore | edbstore | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
+
| | | | |
postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
+
| | | | |
postgres=CTc/postgres

- Retrieve a list of tables in edbstore database and check which schema and owner they have.

edbstore=> \dn
List of schemas
Name | Owner
----------+----------
ebuy | edbstore
edbstore | edbstore
public | postgres

Module 6 - PSQL
Lab exercise 1

- Connect to a database using psql

dbname = edbstore, dbuser = charles

$ psql -d edbstore -U charles -h localhost

- Switch databases

edbstore=# \c charles charles localhost 5432


SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
You are now connected to database "charles" as user "charles".

- Describe the customers table

No such table. I install first the database delivered with the course. After that

edbstore=# \d customers
Table "edbstore.customers"
Column | Type |
Modifiers
----------------------+-----------------------+------------------------------
----------------------------------
customerid | integer | not null default
nextval('customers_customerid_seq'::regclass)
firstname | character varying(50) | not null
lastname | character varying(50) | not null
address1 | character varying(50) | not null
address2 | character varying(50) |
city | character varying(50) | not null
state | character varying(50) |
zip | integer |
country | character varying(50) | not null
region | smallint | not null
email | character varying(50) |
phone | character varying(50) |
creditcardtype | integer | not null
creditcard | character varying(50) | not null
creditcardexpiration | character varying(50) | not null
username | character varying(50) | not null
password | character varying(50) | not null
age | smallint |
income | integer |
gender | character varying(1) |
Indexes:
"customers_pkey" PRIMARY KEY, btree (customerid)
"ix_cust_username" UNIQUE, btree (username)
Referenced by:
TABLE "cust_hist" CONSTRAINT "fk_cust_hist_customerid" FOREIGN KEY
(customerid) REFERENCES customers(customerid) ON DELETE CASCADE
TABLE "orders" CONSTRAINT "fk_customerid" FOREIGN KEY (customerid)
REFERENCES customers(customerid) ON DELETE SET NULL

- Describe the customer table including description

edbstore=# \d+ customers


Table
"edbstore.customers"
Column | Type |
Modifiers | Storage | Description
----------------------+-----------------------+------------------------------
----------------------------------+----------+-------------
customerid | integer | not null default
nextval('customers_customerid_seq'::regclass) | plain |
firstname | character varying(50) | not null
| extended |
lastname | character varying(50) | not null
| extended |
address1 | character varying(50) | not null
| extended |
address2 | character varying(50) |
| extended |
city | character varying(50) | not null
| extended |
state | character varying(50) |
| extended |
zip | integer |
| plain |
country | character varying(50) | not null
| extended |
region | smallint | not null
| plain |
email | character varying(50) |
| extended |
phone | character varying(50) |
| extended |
creditcardtype | integer | not null
| plain |
creditcard | character varying(50) | not null
| extended |
creditcardexpiration | character varying(50) | not null
| extended |
username | character varying(50) | not null
| extended |
password | character varying(50) | not null
| extended |
age | smallint |
| plain |
income | integer |
| plain |
gender | character varying(1) |
| extended |
Indexes:
"customers_pkey" PRIMARY KEY, btree (customerid)
"ix_cust_username" UNIQUE, btree (username)
Referenced by:
TABLE "cust_hist" CONSTRAINT "fk_cust_hist_customerid" FOREIGN KEY
(customerid) REFERENCES customers(customerid) ON DELETE CASCADE
TABLE "orders" CONSTRAINT "fk_customerid" FOREIGN KEY (customerid)
REFERENCES customers(customerid) ON DELETE SET NULL
Has OIDs: no

- List all databases

edbstore=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access
privileges
-----------+----------+----------+-------------+-------------+---------------
--------
charles | charles | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
edbstore | edbstore | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
+
| | | | |
postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
+
| | | | |
postgres=CTc/postgres

- List all schemas

edbstore=# \dn
List of schemas
Name | Owner
----------+----------
edbstore | edbstore
public | postgres

- List all tablespaces


edbstore=# \db
List of tablespaces
Name | Owner | Location
------------+----------+----------
pg_default | postgres |
pg_global | postgres |

- Execute an sql statement, saving the output to a file

edbstore=# \o output.txt
edbstore=# select * from customers limit 1;
edbstore=# \! ls -al | grep output
-rw-rw-r-- 1 charles charles 652 Feb 15 13:48 output.txt
edbstore=# \! cat output.txt
-[ RECORD 1 ]--------+--------------------
customerid | 1
firstname | VKUUXF
lastname | ITHOMQJNYX
[...]

Reset value to display results on screen

edbstore=# \o
edbstore=# select * from customers limit 1;
-[ RECORD 1 ]--------+--------------------
customerid | 1
firstname | VKUUXF
lastname | ITHOMQJNYX
[...]

- Do the same thing, just saving data, not the column header

The switch is \t. To write the output in a file is just like the previous exercise.

edbstore=# select * from inventory limit 1;


prod_id | quan_in_stock | sales
---------+---------------+-------
1 | 138 | 9
edbstore=# \t
Showing only tuples.
edbstore=# select * from inventory limit 1;
1 | 138 | 9

- Create a script via another method, and execute from psql

edbstore=# \!
charles@charles-development:~$ vi script.sql
[Write this in the file]
SELECT * FROM customers LIMIT 1;
[Esc :wq]
charles@charles-development:~$ exit
exit
edbstore=> \x
Expanded display is on.
[execute script]
edbstore=> \i script.sql
-[ RECORD 1 ]--------+--------------------
customerid | 1
firstname | VKUUXF
lastname | ITHOMQJNYX
[...]

- Display the dept table in extended format

edbstore=> \x
Expanded display is on.
edbstore=> select * from dept;
-[ RECORD 1 ]------
deptno | 10
dname | ACCOUNTING
loc | NEW YORK
-[ RECORD 2 ]------
deptno | 20
dname | RESEARCH
loc | DALLAS
-[ RECORD 3 ]------
deptno | 30
dname | SALES
loc | CHICAGO
-[ RECORD 4 ]------
deptno | 40
dname | OPERATIONS
loc | BOSTON

- Create a script that will not display all data but will echo the table, name and show how long
the statement took

edbstore=> \timing
Timing is on.
edbstore=> \o output.txt
edbstore=> select * from dept;
Time: 1.195 ms

Module 8 - Security
Lab exercise 1

- Your server box has 2 network cards:

1.1.1.1 = internal LAN


10.1.10.1 = Web server for external access

- Configure your server to accept connections from external and internal networks. This is done
in postgresql.conf
listen_addresses = '*'

Or

listen_addresses = '1.1.1.1,10.1.10.1'

Note: listen_addresse refers to the IP addresses that your server machine has, i.e. the IP addresses
that the server is going to bind to listen on your local machine. So if you have many network
cards and only want to accept connetions on some of them, then you would restrict the list to
those (instead of using *). In the exercise both network cards are used, so it makes no difference
which solution you choose.

Lab exercise 2
psql: could not connect to server: Connection refused
Is the server running on host "1.1.1.1" and accepting
TCP/IP connections on port 5432?

- Predict the problem and suggest a solution

Probably the server is not running or has not been restarted after the changes done in Lab
exercise 1 or the modifications have not been taken.

Check setting of listen_addresses


Restart the database
Check firewalls between client and database server

Lab exercise 3

- New developer with ID = 89. Create a new user by name dev89 and password 'password89'.
Then assign the necessary privileges to dev89 so that he can connect to the edbstore database and
view all tables.

charles@charles-development:~$ psql edbstore


psql (9.1.8)
Type "help" for help.

edbstore=# select current_user;


current_user
--------------
charles
(1 row)
edbstore=# CREATE ROLE dev89 LOGIN PASSWORD 'password89';
edbstore=# GRANT CONNECT ON DATABASE edbstore TO dev89;
edbstore=# GRANT USAGE ON SCHEMA edbstore TO dev89;
edbstore=# GRANT SELECT ON ALL TABLES IN SCHEMA edbstore TO dev89;
edbstore=# ALTER ROLE dev89 SET search_path="$user",edbstore,public;
edbstore=> \q
charles@charles-development:~$ psql -d edbstore -U dev89 -h localhost
Password for user dev89:
psql (9.1.8)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

edbstore=> show search_path;


search_path
---------------------------
"$user", edbstore, public
edbstore=> \dt
List of relations
Schema | Name | Type | Owner
----------+------------+-------+----------
edbstore | categories | table | edbstore
edbstore | cust_hist | table | edbstore
edbstore | customers | table | edbstore
edbstore | dept | table | edbstore
edbstore | emp | table | edbstore
edbstore | inventory | table | edbstore
edbstore | job_grd | table | edbstore
edbstore | jobhist | table | edbstore
edbstore | locations | table | edbstore
edbstore | orderlines | table | edbstore
edbstore | orders | table | edbstore
edbstore | products | table | edbstore
edbstore | reorder | table | edbstore

Note: The modification of the search_path is just to make the life of dev89 easier.

Lab exercise 4

- New developer on client with IP 1.1.1.89 has a problem connecting to the database server.

FATAl: no pg_hba.conf entry for host "1.1.1.89", user "dev89", database


"edbstore", SSL off

Add this entry to the pg_hba.conf file:

# TYPE DATABASE USER ADDRESS METHOD


[...]
host edbstore dev89 1.1.1.89/32 md5
[...]

This will enable the user to connect using his username and password.

Module 9: SQL Primer


Lab exercise 1

- 1. Initiate a PSQL session

charles@charles-development:~$ psql -U edbstore -d edbstore -h localhost


- 2. PSQL commands access the database

True.

 SQL queries and DDL statements affect the database


 psql commands query e.g. the catalog tables to retrieve information on database objects.
Psql commands do not change the data in the database.

- 3. This executes correctly

SELECT ename, job, sal AS Salary FROM emp;

True, but the word "Salary" will be written in lower letters (SQL converts everything that is not
double quoted to lower letters). If you wanted to have the word starting with a capital letter you
should modify the statement to

SELECT ename, job, sal AS "Salary" FROM emp;

- 4. This executes correctly

SELECT * FROM emp;

True.

- 5. Find the coding errors in the statement

SELECT empno, ename, sal x 12 ANNUAL SALARY


FROM emp;
Error 1: The operator for multiplication is "*".
Error 2: If the new name for a column result must be returned as indicated
(capital letters and two words) then you must double quote (") it.

Correct statement

SELECT empno, ename, sal * 12 AS "ANNUAL SALARY"


FROM emp;

Note: the "AS" for aliasing the column name is optional.

Lab exercise 2

Write a statement for following:

- Create a list of employees with the name, department number, and department name for all
employees.

We need to explore the database a little. We know that employees are in the table emp. Parts of
the description that are not relevant for the exercise are cut out (indicated by [...]).
edbstore=> \d emp
Table "edbstore.emp"
Column | Type | Modifiers
----------+-----------------------------+-----------
ename | character varying(10) |
deptno | numeric(2,0) |
[...]
Foreign-key constraints:
"emp_ref_dept_fk" FOREIGN KEY (deptno) REFERENCES dept(deptno)
[...]

We see that the department name is not available and we assume that it is in table dept.

edbstore=> \d dept
Table "edbstore.dept"
Column | Type | Modifiers
--------+-----------------------+-----------
deptno | numeric(2,0) | not null
dname | character varying(14) |
[...]
Referenced by:
TABLE "emp" CONSTRAINT "emp_ref_dept_fk" FOREIGN KEY (deptno) REFERENCES
dept(deptno)
[...]

Since we must list all employees let's check if there are any that do not belong to any department.

edbstore=> SELECT COUNT(*) FROM emp WHERE deptno IS NULL;


count
-------
0

None. So we can make a simple join on dept. Also there are no requirements for grouping or
ordering.

edbstore=> SELECT emp.ename, emp.deptno, dept.dname


edbstore-> FROM emp
edbstore-> JOIN dept ON (emp.deptno = dept.deptno);
ename | deptno | deptno
--------+--------+--------
SMITH | 20 | RESEARCH
ALLEN | 30 | SALES
WARD | 30 | SALES
[...]

If we had any employee without a department we would need another join.

edbstore=> SELECT emp.ename, emp.deptno, dept.dname


edbstore=> FROM emp
edbstore=> LEFT JOIN dept ON (emp.deptno = dept.deptno);

The left join indicates that all employees (left side of the join) must be retrieved, even if deptno
is null.
Alterntive from EnterpriseDB solution video:

edbstore=> SELECT e.ename, e.deptno, d.dname


edbstore-> FROM emp e
edbstore-> JOIN dept d ON e.deptno = d.deptno;

- Create a report to display employees' name and number along with their manager's name and
number. Label the columns Employee, Emp#, Manager and Mgr#.

edbstore=> SELECT emp.ename AS "Employee", emp.empno AS "Emp#", emp.mgr AS


"Emp#", emp2.ename AS "Manager"
edbstore-> FROM emp emp2
edbstore-> RIGHT JOIN emp ON (emp2.empno = emp.mgr);
Employee | Emp# | Emp# | Manager
----------+------+------+---------
SMITH | 7369 | 7902 | FORD
ALLEN | 7499 | 7698 | BLAKE
WARD | 7521 | 7698 | BLAKE
JONES | 7566 | 7839 | KING
[...]

Notice that we are now right joining to get all employees (one of them has no boss).

Alternative I did after seeing solution to the first part of this lab.

SELECT e.ename AS "Employee", e.empno AS "Emp#", e.mgr AS "Mgr#", m.ename AS


"Manager"
FROM emp e
LEFT JOIN emp m ON (m.empno = e.mgr);

- Create a report with employee names, deparment number and all the employees that work in
the same department as a given employee. Give the columns an appropriate name.

Let's assume that the given employee is SMITH. Now we need a list of all employees working in
the same department as SMITH.

edbstore=> SELECT ename, deptno


edbstore-> FROM emp
edbstore-> WHERE deptno IN (SELECT deptno FROM emp WHERE ename = 'SMITH');
ename | deptno
---------+--------
SCOTT | 20
ADAMS | 20
FORD | 20
JONES | 20
SMITH | 20

Lab exercise 3

- Write a query that displays the employee number and name of all employees who work in a
department with any employee whose name contains a "u" (use subquery).
edbstore=> SELECT emp.empno, emp.ename
edbstore-> FROM emp
edbstore-> WHERE emp.deptno IN (SELECT emp.deptno FROM emp WHERE
strpos(lower(emp.ename),'u') > 0);
empno | ename
-------+--------
7499 | ALLEN
7521 | WARD
7654 | MARTIN
7698 | BLAKE
7844 | TURNER
7900 | JAMES
(6 rows)

The solution on the video is much less flexible because it assumes that names are alway written
in capital letters.

SELECT empno, ename


FROM emp
WHERE deptno IN (SELECT deptno FROM emp WHERE ename LIKE '%U%');

- Update and delete data in the emp table.

Change the name of the employee 7566 to Drexler.

UPDATE emp SET ename = 'Drexler' WHERE empno = 7566;

Change the salary to $1000 for all employees who have a salary less than $900.

UPDATE emp SET sal = 1000 WHERE sal < 900;

Verify your changes in the table

edbstore=> SELECT empno, ename, sal FROM emp;


empno | ename | sal
-------+---------+---------
7499 | ALLEN | 1600.00
7521 | WARD | 1250.00
7654 | MARTIN | 1250.00
7698 | BLAKE | 2850.00
7782 | CLARK | 2450.00
7788 | SCOTT | 3000.00
7839 | KING | 5000.00
7844 | TURNER | 1500.00
7876 | ADAMS | 1100.00
7900 | JAMES | 950.00
7902 | FORD | 3000.00
7934 | MILLER | 1300.00
7566 | Drexler | 2975.00
7369 | SMITH | 1000.00

- Delete MILLER from the emp table.


DELETE FROM emp WHERE ename = 'MILLER';

Lab exercise 4

- Create the emp2 table based on the structure of the emp table. Include only the employee_id,
name, salary and department_id columns. Name the columns in the new table id, first_name,
salary and deptid.

edbstore=> CREATE TABLE emp2 AS


edbstore-> SELECT empno AS id, ename AS first_name, sal AS salary, deptno AS
deptid
edbstore-> FROM emp LIMIT 0;
edbstore=> \d emp2
Table "edbstore.emp2"
Column | Type | Modifiers
------------+-----------------------+-----------
id | numeric(4,0) |
first_name | character varying(10) |
salary | numeric(7,2) |
deptid | numeric(2,0) |

Note: Only create structure, don't include data. For that reason we use limit 0.

- Create a view empvu including employee number, name and department number from emp
table. The heading for the employee name must be employee.

edbstore=> CREATE VIEW empvu AS


edbstore-> SELECT empno, ename AS employee, deptno
edbstore-> FROM emp;
CREATE VIEW

- Confirm that the view works. Display the contents of the empvu view.

edbstore=> SELECT * FROM empvu;


empno | employee | deptno
-------+----------+--------
7499 | ALLEN | 30
7521 | WARD | 30
7654 | MARTIN | 30
7698 | BLAKE | 30
7782 | CLARK | 10
7788 | SCOTT | 20
7839 | KING | 10
7844 | TURNER | 30
7876 | ADAMS | 20
7900 | JAMES | 30
7902 | FORD | 20
7566 | Drexler | 20
7369 | SMITH | 20
(13 rows)

- Using empvu, write a query to display all employee names and department numbers.
edbstore=> SELECT employee, deptno
edbstore-> FROM empvu;
employee | deptno
----------+--------
ALLEN | 30
WARD | 30
MARTIN | 30
BLAKE | 30
CLARK | 10
SCOTT | 20
KING | 10
TURNER | 30
ADAMS | 20
JAMES | 30
FORD | 20
Drexler | 20
SMITH | 20
(13 rows)

Lab exercise 5

- Create a sequence for deptno of table dept. Start at 60, max at 90, increment 10 and name
dept_id_seq.

First create a sequence.

edbstore=> CREATE SEQUENCE dept_id_seq


edbstore-> INCREMENT 10 MINVALUE 60 MAXVALUE 90 START 60
edbstore-> OWNED BY dept.deptno;
CREATE SEQUENCE

NB: owned by associates the sequence with the table column and is used, e.g. in a cascaded drop
of the table. It does not automatically assign the sequence to the column as default value.

Then associate the sequence to the column. Set it as its defaut.

edbstore=> ALTER TABLE dept


edbstore-> ALTER COLUMN deptno SET DEFAULT nextval('dept_id_seq');
ALTER TABLE
edbstore=> \d dept
Table "edbstore.dept"
Column | Type | Modifiers
--------+-----------------------+--------------------------------------------
-------
deptno | numeric(2,0) | not null default
nextval('dept_id_seq'::regclass)
[...]

- Test your sequence, inster two rows in dept.

edbstore=> INSERT INTO dept VALUES (DEFAULT, 'IT','DENVER');


INSERT 0 1
edbstore=> INSERT INTO dept VALUES (DEFAULT, 'RELATIONS','WASHINGTON');
INSERT 0 1
edbstore=> SELECT * FROM dept;
deptno | dname | loc
--------+------------+------------
10 | ACCOUNTING | NEW YORK
20 | RESEARCH | DALLAS
30 | SALES | CHICAGO
40 | OPERATIONS | BOSTON
60 | IT | DENVER
70 | RELATIONS | WASHINGTON
(6 rows)

- Create an index on deptno of table dept.

edbstore=> CREATE INDEX deptno_idx ON dept(deptno);


CREATE INDEX
edbstore=> \d dept
Table "edbstore.dept"
Column | Type | Modifiers
--------+-----------------------+--------------------------------------------
-------
deptno | numeric(2,0) | not null default
nextval('dept_id_seq'::regclass)
[...]
Indexes:
[...]
"deptno_idx" btree (deptno)
[...]

- Create and test a partial index.

For this we create a partial index for customers in the US (who happen to be the highest
number).

edbstore=> CREATE INDEX custid_us_idx ON customers(customerid)


edbstore-> WHERE country = 'US';
CREATE INDEX
edbstore=> \d customers
Table "edbstore.customers"
Column | Type |
Modifiers
----------------------+-----------------------+------------------------------
----------------------------------
customerid | integer | not null default
nextval('customers_customerid_seq'::regclass)
[...]
country | character varying(50) | not null
[...]
Indexes:
[...]
"custid_us_idx" btree (customerid) WHERE country::text = 'US'::text

Module 10: Backup/Restore and PITR


Lab exercise 1

- As the root user, create a folder /PostgreSQL_backup and assign ownership to PostgreSQL user
using chown utility or windows security tab in folder properties.

Note: For the sake of consistence I will use a different naming and location for the backup
directory. On Ubuntu backups are usually stored in the directory /var/backups. The name of
the directory itself will simply be postgresql.

charles@charles-development:~$ sudo mkdir /var/backups/postgresql


charles@charles-development:~$ sudo chown postgres /var/backups/postgresql
charles@charles-development:~$ sudo chmod 0700 /var/backups/postgresql
charles@charles-development:~$ sudo -i su - postgres
postgres@charles-development:~$ ls -al /var/backups | grep postgres
drwx------ 2 postgres root 4096 Feb 18 08:14 postgresql
postgres@charles-development:~$ ls -al /var/backups/postgresql/
total 8
drwx------ 2 postgres root 4096 Feb 18 08:14 .
drwxr-xr-x 3 root root 4096 Feb 18 08:14 ..

- Take a full database dump of the edbstore database with the pg_dump utility. The dump should
be in plain text format. - Name the dump file as edbstore_full.sql and store it in the
PostgreSQL_backup folder.

Remember: Our backup dir is /var/backups/postgresql

postgres@charles-development:~$ pg_dump edbstore >


/var/backups/postgresql/edbstore_full.sql
postgres@charles-development:~$ ls -al /var/backups/postgresql/
total 5592
drwx------ 2 postgres root 4096 Feb 18 08:18 .
drwxr-xr-x 3 root root 4096 Feb 18 08:14 ..
-rw-rw-r-- 1 postgres postgres 5716100 Feb 18 08:18 edbstore_full.sql

Lab exercise 2

- Take a schema-only dump of the edbstore database and name the file as edbstore_schema.sql

postgres@charles-development:~$ pg_dump -s edbstore >


/var/backups/postgresql/edbstore_schema.sql

- Take a data-only dump of the edbstore database, disable all triggers for faster restore, use the
insert command instead of copy, and name the file as edbstore_data.sql

postgres@charles-development:~$ pg_dump -a --disable-triggers --inserts


edbstore > /var/backups/postgresql/edbstore_data.sql

- Take a full dump of only the customers table and name the file as edbstore_customers.sql
postgres@charles-development:~$ pg_dump -t edbstore.customers edbstore >
/var/backups/postgresql/edbstore_customers.sql

Summary check

postgres@charles-development:~$ ls -al /var/backups/postgresql


-rw-rw-r-- 1 postgres postgres 3127531 Feb 18 08:44 edbstore_customers.sql
-rw-rw-r-- 1 postgres postgres 10839954 Feb 18 08:41 edbstore_data.sql
-rw-rw-r-- 1 postgres postgres 5716100 Feb 18 08:18 edbstore_full.sql
-rw-rw-r-- 1 postgres postgres 18317 Feb 18 08:38 edbstore_schema.sql

Lab exercise 3

- Take a full database dump of the edbstore in compressed format using the pg_dump utility,
name the file as edbstore_full_fc.dmp

postgres@charles-development:~$ pg_dump -Fc edbstore >


/var/backups/postgresql/edbstore_full_fc.dmp

- Take a full database cluster dump using pg_dumpall. Remember pg_dumpall supports only
plain text format; name the file edbdata.sql

postgres@charles-development:~$ pg_dumpall >


/var/backups/postgresql/edbdata.sql

Summary check

postgres@charles-development:~$ ls -al /var/backups/postgresql


-rw-rw-r-- 1 postgres postgres 19131909 Feb 18 09:17 edbdata.sql
-rw-rw-r-- 1 postgres postgres 3127531 Feb 18 08:44 edbstore_customers.sql
-rw-rw-r-- 1 postgres postgres 10839954 Feb 18 08:41 edbstore_data.sql
-rw-rw-r-- 1 postgres postgres 1998165 Feb 18 09:14 edbstore_full_fc.dmp
-rw-rw-r-- 1 postgres postgres 5716100 Feb 18 08:18 edbstore_full.sql
-rw-rw-r-- 1 postgres postgres 18317 Feb 18 08:38 edbstore_schema.sql

Lab exercise 4

- Drop database edbstore.

postgres@charles-development:~$ dropdb edbstore


postgres@charles-development:~$ psql -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access
privileges
-----------+----------+----------+-------------+-------------+---------------
--------
charles | charles | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
+
| | | | |
postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
+

- Create database edbstore with edbstore owner.

postgres@charles-development:~$ createdb -O edbstore edbstore


postgres@charles-development:~$ psql -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access
privileges
-----------+----------+----------+-------------+-------------+---------------
--------
charles | charles | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
edbstore | edbstore | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
+
| | | | |
postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
+
| | | | |
postgres=CTc/postgres

- Restore the full dump from edbstore_full.sql and verify all the objects and their ownership.

postgres@charles-development:~$ psql -f
/var/backups/postgresql/edbstore_full.sql -d edbstore
postgres@charles-development:~$ psql edbstore
edbstore=# set search_path=edbstore;
SET
edbstore=# show search_path;
search_path
-------------
edbstore
(1 row)

edbstore=# \dt
List of relations
Schema | Name | Type | Owner
----------+------------+-------+----------
edbstore | categories | table | edbstore
edbstore | cust_hist | table | edbstore
edbstore | customers | table | edbstore
edbstore | dept | table | edbstore
edbstore | emp | table | edbstore
edbstore | emp2 | table | edbstore
edbstore | inventory | table | edbstore
edbstore | job_grd | table | edbstore
edbstore | jobhist | table | edbstore
edbstore | locations | table | edbstore
edbstore | orderlines | table | edbstore
edbstore | orders | table | edbstore
edbstore | products | table | edbstore
edbstore | reorder | table | edbstore
- Drop database edbstore.

postgres@charles-development:~$ dropdb edbstore

- Create database edbstore with edbstore owner.

postgres@charles-development:~$ createdb -O edbstore edbstore

- Restore the full dump from compressed file edbstore_full_fc.dmp and verify all the objects and
their ownership.

postgres@charles-development:~$ pg_restore -Fc -d edbstore


/var/backups/postgresql/edbstore_full_fc.dmp

Lab exercise 5

- Create a directory /opt/arch or c:\arch and give ownership to PostgreSQL user.

charles@charles-development:~$ sudo mkdir /opt/arch


charles@charles-development:~$ sudo chown postgres /opt/arch/
charles@charles-development:~$ sudo chmod 0700 /opt/arch/
charles@charles-development:~$ ls -al /opt | grep arch
drwx------ 2 postgres root 4096 Feb 18 09:39 arch

- Open postgresql.conf file of your edbdata cluster and configure your cluster to run in archive
mode and archive log location to be /opt/arch or c:\arch.

charles@charles-development:~$ vi /etc/postgresql/9.1/main/postgresql.conf
wal_level = archive
archive_mode = on
archive_command = 'cp -i %p /opt/arch/ < /dev/null'

- Take a full online base backup of your cluster in PostgreSQL_backup directory.

charles@charles-development:~$ sudo service postgresql restart


* Restarting PostgreSQL 9.1 database server
charles@charles-development:~$ sudo -i su - postgres
postgres@charles-development:~$ psql
psql (9.1.8)
Type "help" for help.

postgres=# select pg_start_backup('2013-02-18');


pg_start_backup
-----------------
0/11000020
(1 row)

postgres=# \q
postgres@charles-development:~$ cd /var/lib/postgresql/9.1/
postgres@charles-development:~/9.1$ tar -cf /opt/arch/pg_archive.tar main
postgres@charles-development:~/9.1$ ls /opt/arch/
-rw------- 1 postgres postgres 16777216 Feb 18 10:01
00000002000000000000000F
-rw------- 1 postgres postgres 16777216 Feb 18 10:02
000000020000000000000010
-rw-rw-r-- 1 postgres postgres 154839040 Feb 18 10:02 pg_archive.tar
postgres@charles-development:~/9.1$ psql
psql (9.1.8)
Type "help" for help.

postgres=# select pg_stop_backup();


NOTICE: pg_stop_backup complete, all required WAL segments have been
archived
pg_stop_backup
----------------
0/110000A0
(1 row)

postgres=# \q
postgres@charles-development:~$ ls -al /opt/arch
-rw------- 1 postgres postgres 16777216 Feb 18 10:01
00000002000000000000000F
-rw------- 1 postgres postgres 16777216 Feb 18 10:02
000000020000000000000010
-rw------- 1 postgres postgres 16777216 Feb 18 10:02
000000020000000000000011
-rw------- 1 postgres postgres 277 Feb 18 10:02
000000020000000000000011.00000020.backup
-rw-rw-r-- 1 postgres postgres 154839040 Feb 18 10:02 pg_archive.tar

Note: The calls to pg_start_backup and pg_stop_backup could have been done also directly from
the linux shell.

charles@charles-development:~$ psql -c "select pg_start_backup('2013-02-17')"


charles@charles-development:~$ psql -c "select pg_stop_backup()"

Module 11: Routine Maintenance Tasks


Lab exercise 1

- Create an explain plan for following query

o Select * from emp where empno = 1


o Select * from emp where empno > 1
o Select * from emp where empno is not null
edbstore=# EXPLAIN SELECT * FROM emp WHERE empno = 1;
QUERY PLAN
-----------------------------------------------------
Seq Scan on emp (cost=0.00..1.16 rows=1 width=146)
Filter: (empno = 1::numeric)
(2 rows)

edbstore=# EXPLAIN SELECT * FROM emp WHERE empno > 1;


QUERY PLAN
-----------------------------------------------------
Seq Scan on emp (cost=0.00..1.16 rows=4 width=146)
Filter: (empno > 1::numeric)
(2 rows)

edbstore=# EXPLAIN SELECT * FROM emp WHERE empno IS NOT NULL;


QUERY PLAN
------------------------------------------------------
Seq Scan on emp (cost=0.00..1.13 rows=13 width=146)
Filter: (empno IS NOT NULL)
(2 rows)

- What is difference between different explain plans.

None.

Lab exercise 2

- Write a statement to vacuum whole database including all tables.

edbstore=# VACUUM;

- The “customers” table is very heavily used in DML operations which results in lots of obsolete
rows in the table. Execute a command to remove all such rows in order to improve performance.

edbstore=# VACUUM FULL customers;

Module 13: Moving Data


Lab exercise 1

- Unload a table in the edbstore schema to a csv file, with a header and using a pipe (|) delimiter.

We use table emp.

edbstore=# COPY emp TO '/var/backups/postgresql/emp.csv' (FORMAT CSV,


DELIMITER '|', HEADER);

- Load the table to a temp tables of similar structure.

edbstore=# CREATE TABLE emp2 AS SELECT * FROM emp LIMIT 0;


SELECT 0
edbstore=# SELECT * FROM emp2;
empno | ename | job | mgr | hiredate | sal | comm | deptno
-------+-------+-----+-----+----------+-----+------+--------
(0 rows)

edbstore=# COPY emp2 FROM '/var/backups/postgresql/emp.csv' (FORMAT CSV,


DELIMITER '|', HEADER);
COPY 13
edbstore=# SELECT * FROM emp2;
empno | ename | job | mgr | hiredate | sal | comm
| deptno
-------+---------+-----------+------+---------------------+---------+--------
-+--------
7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 00:00:00 | 1600.00 | 300.00
| 30
7521 | WARD | SALESMAN | 7698 | 1981-02-22 00:00:00 | 1250.00 | 500.00
| 30
7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00
| 30
7698 | BLAKE | MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 |
| 30
7782 | CLARK | MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 |
| 10
7788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 |
| 20
7839 | KING | PRESIDENT | | 1981-11-17 00:00:00 | 5000.00 |
| 10
7844 | TURNER | SALESMAN | 7698 | 1981-09-08 00:00:00 | 1500.00 | 0.00
| 30
7876 | ADAMS | CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 |
| 20
7900 | JAMES | CLERK | 7698 | 1981-12-03 00:00:00 | 950.00 |
| 30
7902 | FORD | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 |
| 20
7369 | SMITH | CLERK | 7902 | 1980-12-17 00:00:00 | 1000.00 |
| 20
7566 | DREXLER | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 |
| 20
(13 rows)

- Try unloading and loading only using certain columns.

edbstore=# TRUNCATE TABLE emp2;


TRUNCATE TABLE
edbstore=# COPY emp2 (ename, job) FROM '/var/backups/postgresql/empsel.csv'
(FORMAT CSV, DELIMITER '|', HEADER);
COPY 13
edbstore=# SELECT * FROM emp2;
empno | ename | job | mgr | hiredate | sal | comm | deptno
-------+---------+-----------+-----+----------+-----+------+--------
| ALLEN | SALESMAN | | | | |
| WARD | SALESMAN | | | | |
| MARTIN | SALESMAN | | | | |
| BLAKE | MANAGER | | | | |
| CLARK | MANAGER | | | | |
| SCOTT | ANALYST | | | | |
| KING | PRESIDENT | | | | |
| TURNER | SALESMAN | | | | |
| ADAMS | CLERK | | | | |
| JAMES | CLERK | | | | |
| FORD | ANALYST | | | | |
| SMITH | CLERK | | | | |
| DREXLER | MANAGER | | | | |
(13 rows)

Note: This worked because the not null constraints of emp was not taken over into emp2.

Lab exercise 2

- Write a command to copy the customers table data in CSV format to a file.

edbstore=# COPY customers TO '/var/backups/postgresql/customers.sql' (FORMAT


CSV);
COPY 20000

Vous aimerez peut-être aussi