EnterpriseDB PostgreSQL Exercises
EnterpriseDB PostgreSQL Exercises
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
max_connections = 200
superuser_reserved_connections = 10
authentication_timeout = 10s
Note: The change to max_connections forced me to increase the kernel variable shmmax and
shmall (shared memory).
HowTo:
$ sysctl -w kernel.shmmax=134217728
$ sysctl -w kernel.shmall=2097152
Or
kernel.shmmax=134217728
kernel.shmall=2097152
Lab Exercise 2
- 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_connections = on
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
Or
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:
- Login inside edbstore database using edbstore user and create edbstore schema
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:
Lab exercise 2
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
edbstore=> \q
charles@charles-development:~$ psql edbstore
psql (9.1.8)
Type "help" for help.
edbstore=# select current_user;
current_user
--------------
charles
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.
Being logged in as edbstore we can create a schema with the same name as the user.
- 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:
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.
- 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
- Switch databases
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
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
edbstore=# \dn
List of schemas
Name | Owner
----------+----------
edbstore | edbstore
public | postgres
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
[...]
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=# \!
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
[...]
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
- 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?
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.
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.
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.
This will enable the user to connect using his username and password.
True.
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
True.
Correct statement
Lab exercise 2
- 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.
None. So we can make a simple join on dept. Also there are no requirements for grouping or
ordering.
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:
- 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#.
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.
- 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.
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.
Change the salary to $1000 for all employees who have a salary less than $900.
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.
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.
- Confirm that the view works. Display the contents of the empvu view.
- 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.
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.
For this we create a partial index for customers in the US (who happen to be the highest
number).
- 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.
- 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.
Lab exercise 2
- Take a schema-only dump of the edbstore database and name the file as 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
- 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
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
- Take a full database cluster dump using pg_dumpall. Remember pg_dumpall supports only
plain text format; name the file edbdata.sql
Summary check
Lab exercise 4
- 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.
- Restore the full dump from compressed file edbstore_full_fc.dmp and verify all the objects and
their ownership.
Lab exercise 5
- 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'
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=# \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.
None.
Lab exercise 2
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.
- Unload a table in the edbstore schema to a csv file, with a header and using a pipe (|) delimiter.
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.