DB Development in SQL

by K. Yue

1. Introduction

2. System Catalog

Example:


mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sakila             |
| test               |
| world              |
| yue_exp            |
+--------------------+
7 rows in set (0.00 sec)

mysql database

Example:

Try to add a new user by inserting into the user table: http://dev.mysql.com/doc/refman/5.6/en/adding-users.html. There are problems.

use mysql;

INSERT INTO user
VALUES('localhost','abcde',PASSWORD('IloveDBMS'),
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
'','','','',0,0,0,0);

FLUSH PRIVILEGES;

Try:

describe user;

What do we learn?

Try:

INSERT INTO user (Host,User,Password,select_priv, insert_priv,     update_priv,ssl_cipher,x509_issuer,x509_subject)
VALUES ('localhost', 'abcde', PASSWORD('IloveDBMS'), 'Y', 'Y', 'Y', 'NULL', 'NULL', 'NULL');

FLUSH PRIVILEGES;

information_schema database

Example:

mysql> SELECT table_name, table_type, row_format, table_rows, avg_row_length
    -> FROM information_schema.tables
    -> WHERE table_schema = 'information_schema'
    -> ORDER BY table_name DESC;
+---------------------------------------+-------------+------------+------------+----------------+
| table_name                            | table_type  | row_format | table_rows | avg_row_length |
+---------------------------------------+-------------+------------+------------+----------------+
| VIEWS                                 | SYSTEM VIEW | Dynamic    |       NULL |              0 |
| USER_PRIVILEGES                       | SYSTEM VIEW | Fixed      |       NULL |           1986 |
| TRIGGERS                              | SYSTEM VIEW | Dynamic    |       NULL |              0 |
| TABLE_PRIVILEGES                      | SYSTEM VIEW | Fixed      |       NULL |           2372 |
| TABLE_CONSTRAINTS                     | SYSTEM VIEW | Fixed      |       NULL |           2504 |
| TABLESPACES                           | SYSTEM VIEW | Fixed      |       NULL |           6951 |
| TABLES                                | SYSTEM VIEW | Fixed      |       NULL |           9450 |
| STATISTICS                            | SYSTEM VIEW | Fixed      |       NULL |           5753 |
| SESSION_VARIABLES                     | SYSTEM VIEW | Fixed      |       NULL |           3268 |
| SESSION_STATUS                        | SYSTEM VIEW | Fixed      |       NULL |           3268 |
| SCHEMA_PRIVILEGES                     | SYSTEM VIEW | Fixed      |       NULL |           2179 |
| SCHEMATA                              | SYSTEM VIEW | Fixed      |       NULL |           3464 |
| ROUTINES                              | SYSTEM VIEW | Dynamic    |       NULL |              0 |
| REFERENTIAL_CONSTRAINTS               | SYSTEM VIEW | Fixed      |       NULL |           4814 |
| PROFILING                             | SYSTEM VIEW | Fixed      |       NULL |            308 |
| PROCESSLIST                           | SYSTEM VIEW | Dynamic    |       NULL |              0 |
| PLUGINS                               | SYSTEM VIEW | Dynamic    |       NULL |              0 |
| PARTITIONS                            | SYSTEM VIEW | Dynamic    |       NULL |              0 |
| PARAMETERS                            | SYSTEM VIEW | Dynamic    |       NULL |              0 |
| KEY_COLUMN_USAGE                      | SYSTEM VIEW | Fixed      |       NULL |           4637 |
| INNODB_TRX                            | SYSTEM VIEW | Fixed      |       NULL |           4534 |
| INNODB_LOCK_WAITS                     | SYSTEM VIEW | Fixed      |       NULL |            599 |
| INNODB_LOCKS                          | SYSTEM VIEW | Fixed      |       NULL |          31244 |
| INNODB_CMP_RESET                      | SYSTEM VIEW | Fixed      |       NULL |             25 |
| INNODB_CMPMEM_RESET                   | SYSTEM VIEW | Fixed      |       NULL |             29 |
| INNODB_CMPMEM                         | SYSTEM VIEW | Fixed      |       NULL |             29 |
| INNODB_CMP                            | SYSTEM VIEW | Fixed      |       NULL |             25 |
| GLOBAL_VARIABLES                      | SYSTEM VIEW | Fixed      |       NULL |           3268 |
| GLOBAL_STATUS                         | SYSTEM VIEW | Fixed      |       NULL |           3268 |
| FILES                                 | SYSTEM VIEW | Fixed      |       NULL |           2677 |
| EVENTS                                | SYSTEM VIEW | Dynamic    |       NULL |              0 |
| ENGINES                               | SYSTEM VIEW | Fixed      |       NULL |            490 |
| COLUMN_PRIVILEGES                     | SYSTEM VIEW | Fixed      |       NULL |           2565 |
| COLUMNS                               | SYSTEM VIEW | Dynamic    |       NULL |              0 |
| COLLATION_CHARACTER_SET_APPLICABILITY | SYSTEM VIEW | Fixed      |       NULL |            195 |
| COLLATIONS                            | SYSTEM VIEW | Fixed      |       NULL |            231 |
| CHARACTER_SETS                        | SYSTEM VIEW | Fixed      |       NULL |            384 |
+---------------------------------------+-------------+------------+------------+----------------+
37 rows in set (0.08 sec)

 

performance_schema database

sakila database

3. Views

Example:

The Sakila database comes preloaded with MySQL installation using XAMPP. Refer to the documentation at: http://dev.mysql.com/doc/sakila/en/sakila.html. Download the database at downloads.mysql.com/docs/sakila-db.zip to review the SQL statements for declaring and populating the database.

Define a view to provide information of all paying customers: thier id, the total sum of their payment, and the total sum of their payment towards film rentals.

DROP VIEW customer_payment;

CREATE DEFINER=CURRENT_USER SQL SECURITY INVOKER VIEW customer_payment
AS
SELECT
   p.customer_id AS customer,
   sum(p.amount) AS "Total Payment",
   sum(IF(p.rental_id IS NULL, 0, p.amount)) AS "File Rental Payment"
FROM payment as p
GROUP BY p.customer_id;

SELECT * FROM customer_payment LIMIT 20;

Note:

4. Stored Procedures

Example:

DROP PROCEDURE AllSuppliers;

--  A very simple stored procedure
DELIMITER //

CREATE PROCEDURE AllSuppliers()
BEGIN
   SELECT *  FROM Supplier;
END //

DELIMITER ;

--  Call
CALL AllSuppliers;


Note:

Example:

DROP FUNCTION GetAllSuppliers;

--  A very simple stored function
DELIMITER //

CREATE FUNCTION GetAllSuppliers() RETURNS INT
BEGIN
   DECLARE count INT DEFAULT 0;
   SET count = 0;    -- Not really needed.
  
   SELECT COUNT(*) INTO count FROM Supplier;
  
   -- The following is not allowed as result set in function.
   -- SELECT *  FROM Supplier;
  
   RETURN count;
END //

DELIMITER ;

--  Call
SELECT GetAllSuppliers();

Note:

Example:

--  Parts supplied by a supplier

DROP PROCEDURE PartSupplied;
DELIMITER //

CREATE PROCEDURE PartSupplied(
   IN snum VARCHAR(9),        
   IN max INT,                  --  Maximum number of records shown
   OUT numberPartsSupplied INT  --  Number of different parts supplied
)
BEGIN
   SELECT COUNT(*) INTO numberPartsSupplied
   FROM Supply S
   WHERE S.SNUM = snum;
  
   SELECT P.PNUM, P.PNAME, S.Quantity 
   FROM Supply S, Part P
   WHERE S.SNUM = snum
   AND S.PNUM = P.PNUM
   LIMIT max;

END //

DELIMITER ;

--  Call

SET @numberPartsSupplied = 0;
CALL PartSupplied('S2', 2, @numberPartsSupplied);
SELECT @numberPartsSupplied;


 Note:

5. Triggers

Example:

Using the Sakila database, consider the tables inventory and rental.

inventory (inventory_id, film_id, store_id, last_update)
rental (rental_id, rental-date, inventory_id, customer_id, return_date, staff_id, last_update)

The stored function inventory_in_stock(p_inventory_id INT) checks whether an inventory item is in stock. Its logic:

"AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED."

This can be inefficient.

We consider modify the table inventory to speed up performance.

inventory (inventory_id, film_id, store_id, lost, in_stock, last_update)

Two columns are added:

We may consider that the column in_stock as a derived column. Its value can be derived from other columns and tables in the database. Maintaining data consistency of derived columns is a popular use of triggers.

ALTER TABLE inventory
ADD COLUMN lost BOOLEAN DEFAULT FALSE AFTER store_id;

ALTER TABLE inventory
ADD COLUMN in_stock BOOLEAN DEFAULT TRUE AFTER lost;
 

To reverse the operations:

ALTER TABLE inventory DROP COLUMN lost;
ALTER TABLE inventory DROP COLUMN in_stock;

To populate the columns initially:

UPDATE inventory
SET lost = FALSE;

UPDATE inventory
SET in_stock = inventory_in_stock(inventory_id);

-- checking
select * from inventory limit 5;


 We now need to define triggers when we insert or update a rental row. We assume that a rental row will never be deleted.

The trigger after inserting a rental row is shown below. There may be an error. Can you spot it?

DELIMITER $$
CREATE TRIGGER insert_rental AFTER INSERT ON rental FOR EACH ROW
BEGIN
   IF (new.return_date IS NULL)
   THEN
      UPDATE inventory
      SET in_stock = FALSE
      WHERE inventory.inventory_id = rental.inventory_id;
   END IF;
END$$
DELIMITER ;

Note:

Checking:

--  Checking insert trigger.
SELECT * FROM rental WHERE inventory_id = 1;
SELECT * FROM inventory WHERE inventory_id = 1;

--  Rent inventory_id 1 out.
INSERT INTO rental
VALUES (16050,'2011-11-11 22:53:30',1,130,NULL,1,'2011-11-11 23:30:53');

SELECT * FROM rental WHERE inventory_id = 1;
SELECT * FROM inventory WHERE inventory_id = 1;

For the update trigger:

DELIMITER $$
CREATE TRIGGER update_rental AFTER UPDATE ON rental FOR EACH ROW
BEGIN
   IF ((old.return_date IS NULL) and (new.return_date IS NOT NULL))
   THEN
      UPDATE inventory
      SET in_stock = TRUE
      WHERE inventory.inventory_id = new.inventory_id;
   END IF;
END$$
DELIMITER ;

To check:

--  Checking insert trigger.
SELECT * FROM rental WHERE inventory_id = 1;
SELECT * FROM inventory WHERE inventory_id = 1;

UPDATE rental
SET return_date = '2011-11-11 23:30:53'
WHERE rental_id = 16050;

SELECT * FROM rental WHERE inventory_id = 1;
SELECT * FROM inventory WHERE inventory_id = 1;

--  House keeping.
DELETE FROM rental WHERE rental_id = 16050;