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;