diff --git a/.github/Clarian_Triggers.sql b/.github/Clarian_Triggers.sql new file mode 100644 index 0000000..ec60266 --- /dev/null +++ b/.github/Clarian_Triggers.sql @@ -0,0 +1,171 @@ +-- List all the databases +SHOW DATABASES; +-- switch to the current database +USE 75855_lab2_triggers; +-- list of all tables +SHOW TABLES; + +-- STEP 1 +SHOW CREATE TABLE employees; +CREATE TABLE `employees` ( + `employeeNumber` int NOT NULL, + `lastName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `firstName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `extension` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `officeCode` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `reportsTo` int DEFAULT NULL, + `jobTitle` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + PRIMARY KEY (`employeeNumber`), + KEY `reportsTo` (`reportsTo`), + KEY `officeCode` (`officeCode`), + CONSTRAINT `employees_ibfk_1` FOREIGN KEY (`reportsTo`) REFERENCES `employees` (`employeeNumber`), + CONSTRAINT `employees_ibfk_2` FOREIGN KEY (`officeCode`) REFERENCES `offices` (`officeCode`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE `employees_undo` ( + `date_of_change` timestamp(2) NOT NULL DEFAULT CURRENT_TIMESTAMP(2), + `employeeNumber` int NOT NULL, + `lastName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `firstName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `extension` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `officeCode` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `reportsTo` int DEFAULT NULL, + `jobTitle` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `change_type` varchar(50) NOT NULL, + PRIMARY KEY (`date_of_change`), + UNIQUE KEY `date_of_change_UNIQUE` (`date_of_change`) + +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- STEP 2 +CREATE + + TRIGGER TRG_BEFORE_UPDATE_ON_employees + BEFORE UPDATE ON employees FOR EACH ROW + + INSERT INTO `employees_undo` SET + `date_of_change` = CURRENT_TIMESTAMP(2), + `employeeNumber` = OLD.`employeeNumber` , + `lastName` = OLD.`lastName` , + `firstName` = OLD.`firstName` , + `extension` = OLD.`extension` , + `email` = OLD.`email` , + `officeCode` = OLD.`officeCode` , + `reportsTo` = OLD.`reportsTo` , + `jobTitle` = OLD.`jobTitle` , + `change_type` = 'An update DML operation was executed'; + + -- STEP 4 + SHOW TRIGGERS; + UPDATE `employees` +SET +`lastName` = 'Muiruri' +WHERE + +`employeeNumber` = '1056'; +SELECT * FROM employees_undo; + +-- STEP 5 Create a table to store reminders +CREATE TABLE `customers_data_reminders` ( +`customerNumber` int NOT NULL COMMENT 'Identifies the customer whose data +is partly missing', +`customers_data_reminders_timestamp` timestamp(2) NOT NULL DEFAULT +CURRENT_TIMESTAMP(2) COMMENT 'Records the time when the missing data was +detected', +`customers_data_reminders_message` varchar(100) NOT NULL COMMENT 'Records +a message that helps the customer service personnel to know what data is +missing from the customer\'s record', +`customers_data_reminders_status` tinyint NOT NULL DEFAULT '0' COMMENT +'Used to record the status of a reminder (0 if it has not yet been +addressed and 1 if it has been addressed)', +PRIMARY KEY +(`customerNumber`,`customers_data_reminders_timestamp`,`customers_data_remi +nders_message`,`customers_data_reminders_status`), +CONSTRAINT `FK_1_customers_TO_M_customers_data_reminders` FOREIGN KEY +(`customerNumber`) REFERENCES `customers` (`customerNumber`) +ON DELETE CASCADE +ON UPDATE CASCADE +) ENGINE=InnoDB COMMENT='Used to remind the customer service personnel +about a client\'s missing data. This enables them to ask the client to +provide the data during the next interaction with the client.' + +-- STEP 6 Create a trigger that has multiple statements +DELIMITER $$ +CREATE TRIGGER TRG_AFTER_INSERT_ON_customers +AFTER INSERT ON customers FOR EACH ROW +BEGIN +IF NEW.postalCode IS NULL THEN +INSERT INTO `customers_data_reminders` +(`customerNumber`, `customers_data_reminders_timestamp`, +`customers_data_reminders_message`) +VALUES (NEW.customerNumber, CURRENT_TIMESTAMP(2), 'Please remember +to record the client\'s postal code'); +END IF; +IF NEW.salesRepEmployeeNumber IS NULL THEN +INSERT INTO `customers_data_reminders` +(`customerNumber`, `customers_data_reminders_timestamp`, +`customers_data_reminders_message`) +VALUES (NEW.customerNumber, CURRENT_TIMESTAMP(2), 'Please remember +to assign a sales representative to the client'); +END IF; +IF NEW.creditLimit IS NULL THEN +INSERT INTO `customers_data_reminders` +(`customerNumber`, `customers_data_reminders_timestamp`, +`customers_data_reminders_message`) +VALUES (NEW.customerNumber, CURRENT_TIMESTAMP(2), 'Please remember +to set the client\'s credit limit'); +END IF; +END$$ +DELIMITER ; + +-- STEP 7 Confirm the trigger is fired when insertion is made +INSERT INTO `customers` +(`customerNumber`, `customerName`, `contactLastName`, `contactFirstName`, +`phone`, `addressLine1`, `city`, `country`) +VALUES +('497', 'House of Leather', 'Wambua', 'Gabriel', '+254 720 123 456', '9 +Agha Khan Walk', 'Nairobi', 'Kenya'); + +-- STEP 8 Create a new table to store parts data +CREATE TABLE part ( +part_no VARCHAR(18) PRIMARY KEY, +part_description VARCHAR(255), +part_supplier_tax_PIN VARCHAR (11) CHECK (part_supplier_tax_PIN REGEXP +'^[A-Z]{1}[0-9]{9}[A-Z]{1}$'), +part_supplier_email VARCHAR (55), +part_buyingprice DECIMAL(10,2 ) NOT NULL CHECK (part_buyingprice >= 0), +part_sellingprice DECIMAL(10,2) NOT NULL, +CONSTRAINT CHK_part_sellingprice_GT_buyingprice CHECK +(part_sellingprice >= part_buyingprice), +CONSTRAINT CHK_part_valid_supplier_email CHECK (part_supplier_email +REGEXP '^[a-zA-Z0-9]{3,}@[a-zA-Z0-9]{1,}\\.[a-zA-Z0-9.]{1,}$') +); + +-- STEP 9. Create the following user-defined error in a trigger +DELIMITER // +CREATE TRIGGER TRG_BEFORE_UPDATE_ON_part +BEFORE UPDATE ON part FOR EACH ROW +BEGIN +DECLARE errorMessage VARCHAR(255); +DECLARE EXIT HANDLER FOR SQLSTATE '45000' +BEGIN +RESIGNAL SET MESSAGE_TEXT = errorMessage; +END; +SET errorMessage = CONCAT('The new selling price of ', +NEW.part_sellingprice, ' cannot be 2 times greater than the current selling +price of ', OLD.part_sellingprice); +IF NEW.part_sellingprice > OLD.part_sellingprice * 2 THEN +SIGNAL SQLSTATE '45000'; +END IF; +END// +DELIMITER ; + + +-- STEP 10. Confirm that the static, dynamic, and semantic constraints are working + +INSERT INTO `part` (`part_no`, `part_description`, `part_supplier_tax_PIN`, +`part_supplier_email`, `part_buyingprice`, `part_sellingprice`) +VALUES ('001', 'The tyres of a 1958 Chevy Corvette Limited Edition', +'P05120157U', 'toysRus@gmail', '100', '50'); \ No newline at end of file diff --git a/.github/Lab2-triggers_and_check_constraints.jpeg b/.github/Lab2-triggers_and_check_constraints.jpeg new file mode 100644 index 0000000..5f78ce5 Binary files /dev/null and b/.github/Lab2-triggers_and_check_constraints.jpeg differ diff --git a/075855-triggers.mysql b/075855-triggers.mysql new file mode 100644 index 0000000..8308aed --- /dev/null +++ b/075855-triggers.mysql @@ -0,0 +1,61 @@ +-- List all the databases +SHOW DATABASES; +-- switch to the current database +USE 75855_lab2_triggers; +-- list of all tables +SHOW TABLES; + +-- STEP 1 +SHOW CREATE TABLE employees; +CREATE TABLE `employees` ( + `employeeNumber` int NOT NULL, + `lastName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `firstName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `extension` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `officeCode` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `reportsTo` int DEFAULT NULL, + `jobTitle` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + PRIMARY KEY (`employeeNumber`), + KEY `reportsTo` (`reportsTo`), + KEY `officeCode` (`officeCode`), + CONSTRAINT `employees_ibfk_1` FOREIGN KEY (`reportsTo`) REFERENCES `employees` (`employeeNumber`), + CONSTRAINT `employees_ibfk_2` FOREIGN KEY (`officeCode`) REFERENCES `offices` (`officeCode`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE `employees_undo` ( + `date_of_change` timestamp(2) NOT NULL DEFAULT CURRENT_TIMESTAMP(2), + `employeeNumber` int NOT NULL, + `lastName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `firstName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `extension` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `officeCode` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `reportsTo` int DEFAULT NULL, + `jobTitle` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `change_type` varchar(50) NOT NULL, + PRIMARY KEY (`date_of_change`), + UNIQUE KEY `date_of_change_UNIQUE` (`date_of_change`) + +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- STEP 2 +CREATE + + TRIGGER TRG_BEFORE_UPDATE_ON_employees + BEFORE UPDATE ON employees FOR EACH ROW + + INSERT INTO `employees_undo` SET + `date_of_change` = CURRENT_TIMESTAMP(2), + `employeeNumber` = OLD.`employeeNumber` , + `lastName` = OLD.`lastName` , + `firstName` = OLD.`firstName` , + `extension` = OLD.`extension` , + `email` = OLD.`email` , + `officeCode` = OLD.`officeCode` , + `reportsTo` = OLD.`reportsTo` , + `jobTitle` = OLD.`jobTitle` , + `change_type` = 'An update DML operation was executed'; + + -- STEP 3 + SHOW TRIGGERS; diff --git a/075855-triggers.sql b/075855-triggers.sql new file mode 100644 index 0000000..a33b047 --- /dev/null +++ b/075855-triggers.sql @@ -0,0 +1,195 @@ +-- List all the databases +SHOW DATABASES; +-- switch to the current database +USE 75855_lab2_triggers; +-- list of all tables +SHOW TABLES; + +-- STEP 1 +SHOW CREATE TABLE employees; +CREATE TABLE `employees` ( + `employeeNumber` int NOT NULL, + `lastName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `firstName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `extension` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `officeCode` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `reportsTo` int DEFAULT NULL, + `jobTitle` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + PRIMARY KEY (`employeeNumber`), + KEY `reportsTo` (`reportsTo`), + KEY `officeCode` (`officeCode`), + CONSTRAINT `employees_ibfk_1` FOREIGN KEY (`reportsTo`) REFERENCES `employees` (`employeeNumber`), + CONSTRAINT `employees_ibfk_2` FOREIGN KEY (`officeCode`) REFERENCES `offices` (`officeCode`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE `employees_undo` ( + `date_of_change` timestamp(2) NOT NULL DEFAULT CURRENT_TIMESTAMP(2), + `employeeNumber` int NOT NULL, + `lastName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `firstName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `extension` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `officeCode` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `reportsTo` int DEFAULT NULL, + `jobTitle` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `change_type` varchar(50) NOT NULL, + PRIMARY KEY (`date_of_change`), + UNIQUE KEY `date_of_change_UNIQUE` (`date_of_change`) + +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- STEP 2 +CREATE + + TRIGGER TRG_BEFORE_UPDATE_ON_employees + BEFORE UPDATE ON employees FOR EACH ROW + + INSERT INTO `employees_undo` SET + `date_of_change` = CURRENT_TIMESTAMP(2), + `employeeNumber` = OLD.`employeeNumber` , + `lastName` = OLD.`lastName` , + `firstName` = OLD.`firstName` , + `extension` = OLD.`extension` , + `email` = OLD.`email` , + `officeCode` = OLD.`officeCode` , + `reportsTo` = OLD.`reportsTo` , + `jobTitle` = OLD.`jobTitle` , + `change_type` = 'An update DML operation was executed'; + + -- STEP 3 + SHOW TRIGGERS; + + -- STEP 4 + UPDATE `employees` +SET +`lastName` = 'Muiruri' +WHERE +`employeeNumber` = '1056'; + +UPDATE `employees` +SET +`email` = 'mmuiruri@classicmodelcars.com' +WHERE +`employeeNumber` = '1056'; + +SELECT * FROM employees_undo; + +-- STEP 5 +CREATE TABLE `customers_data_reminders` ( + `customerNumber` int NOT NULL COMMENT 'Identifies the customer whose data is partly missing', + `customers_data_reminders_timestamp` timestamp(2) NOT NULL DEFAULT +CURRENT_TIMESTAMP(2) COMMENT 'Records the time when the missing data was detected', + `customers_data_reminders_message` varchar(100) NOT NULL COMMENT 'Records a message that helps the customer service personnel to know what data is missing from the customer\'s record', + `customers_data_reminders_status` tinyint NOT NULL DEFAULT '0' COMMENT +'Used to record the status of a reminder (0 if it has not yet been addressed and 1 if it has been addressed)', + PRIMARY KEY +(`customerNumber`,`customers_data_reminders_timestamp`,`customers_data_reminders_message`,`customers_data_reminders_status`), + CONSTRAINT `FK_1_customers_TO_M_customers_data_reminders` FOREIGN KEY +(`customerNumber`) REFERENCES `customers` (`customerNumber`) + ON DELETE CASCADE + ON UPDATE CASCADE +) ENGINE=InnoDB COMMENT='Used to remind the customer service personnel about a client\'s missing data. This enables them to ask the client to +provide the data during the next interaction with the client.'; + +-- STEP 6 +DELIMITER $$ +CREATE TRIGGER TRG_AFTER_INSERT_ON_customers +AFTER INSERT ON customers FOR EACH ROW +BEGIN + IF NEW.postalCode IS NULL THEN + INSERT INTO `customers_data_reminders` + (`customerNumber`, `customers_data_reminders_timestamp`, +`customers_data_reminders_message`) + VALUES (NEW.customerNumber, CURRENT_TIMESTAMP(2), 'Please remember +to record the client\'s postal code'); + END IF; + IF NEW.salesRepEmployeeNumber IS NULL THEN + INSERT INTO `customers_data_reminders` + (`customerNumber`, `customers_data_reminders_timestamp`, +`customers_data_reminders_message`) + VALUES (NEW.customerNumber, CURRENT_TIMESTAMP(2), 'Please remember +to assign a sales representative to the client'); + END IF; + IF NEW.creditLimit IS NULL THEN + INSERT INTO `customers_data_reminders` + (`customerNumber`, `customers_data_reminders_timestamp`, +`customers_data_reminders_message`) + VALUES (NEW.customerNumber, CURRENT_TIMESTAMP(2), 'Please remember +to set the client\'s credit limit'); + END IF; +END$$ +DELIMITER ; + +-- STEP 7 +INSERT INTO `customers` +(`customerNumber`, `customerName`, `contactLastName`, `contactFirstName`, +`phone`, `addressLine1`, `city`, `country`) +VALUES +('497', 'House of Leather', 'Wambua', 'Gabriel', '+254 720 123 456', '9 +Agha Khan Walk', 'Nairobi', 'Kenya'); + +DELETE FROM `customers` WHERE `customerNumber` = '497'; + +select * from customers_data_reminders; + +INSERT INTO `customers` +(`customerNumber`, `customerName`, `contactLastName`, `contactFirstName`, +`phone`, `addressLine1`, `city`, `country`, `salesRepEmployeeNumber`) +VALUES +('497', 'House of Leather', 'Wambua', 'Gabriel', '+254 720 123 456', '9 +Agha Khan Walk', 'Nairobi', 'Kenya', 1401); + +select * from customers_data_reminders; + +UPDATE `customers` SET `postalCode` = '00100' WHERE `customerNumber` = +'497'; + +select * from customers_data_reminders; + +-- STEP 8 +CREATE TABLE part ( + part_no VARCHAR(18) PRIMARY KEY, + part_description VARCHAR(255), + part_supplier_tax_PIN VARCHAR (11) CHECK (part_supplier_tax_PIN REGEXP +'^[A-Z]{1}[0-9]{9}[A-Z]{1}$'), + part_supplier_email VARCHAR (55), + part_buyingprice DECIMAL(10,2 ) NOT NULL CHECK (part_buyingprice >= 0), + part_sellingprice DECIMAL(10,2) NOT NULL, + CONSTRAINT CHK_part_sellingprice_GT_buyingprice CHECK +(part_sellingprice >= part_buyingprice), + CONSTRAINT CHK_part_valid_supplier_email CHECK (part_supplier_email +REGEXP '^[a-zA-Z0-9]{3,}@[a-zA-Z0-9]{1,}\\.[a-zA-Z0-9.]{1,}$') +); + + -- STEP 9 + DELIMITER // +CREATE TRIGGER TRG_BEFORE_UPDATE_ON_part +BEFORE UPDATE ON part FOR EACH ROW +BEGIN + DECLARE errorMessage VARCHAR(255); + DECLARE EXIT HANDLER FOR SQLSTATE '45000' + BEGIN + RESIGNAL SET MESSAGE_TEXT = errorMessage; + END; + + SET errorMessage = CONCAT('The new selling price of ', +NEW.part_sellingprice, ' cannot be 2 times greater than the current selling +price of ', OLD.part_sellingprice); + IF NEW.part_sellingprice > OLD.part_sellingprice * 2 THEN + SIGNAL SQLSTATE '45000'; + END IF; +END// +DELIMITER ; + +SHOW CREATE TABLE part; +-- STEP 10 +INSERT INTO `part` (`part_no`, `part_description`, `part_supplier_tax_PIN`, +`part_supplier_email`, `part_buyingprice`, `part_sellingprice`) +VALUES ('001', 'The tyres of a 1958 Chevy Corvette Limited Edition', +'P051201576U', 'toysRus@gmail.com', '100', '100'); + +UPDATE `part` SET `part_sellingprice` = '250.00' WHERE (`part_no` = '001'); + +SHOW TRIGGERS; + diff --git a/170490 -triggers.mysql b/170490 -triggers.mysql new file mode 100644 index 0000000..43e1d46 --- /dev/null +++ b/170490 -triggers.mysql @@ -0,0 +1,170 @@ +-- List all the databases +SHOW DATABASES; +-- switch to the current database +USE 75855_lab2_triggers; +-- list of all tables +SHOW TABLES; + +-- STEP 1 +SHOW CREATE TABLE employees; +CREATE TABLE `employees` ( + `employeeNumber` int NOT NULL, + `lastName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `firstName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `extension` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `officeCode` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `reportsTo` int DEFAULT NULL, + `jobTitle` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + PRIMARY KEY (`employeeNumber`), + KEY `reportsTo` (`reportsTo`), + KEY `officeCode` (`officeCode`), + CONSTRAINT `employees_ibfk_1` FOREIGN KEY (`reportsTo`) REFERENCES `employees` (`employeeNumber`), + CONSTRAINT `employees_ibfk_2` FOREIGN KEY (`officeCode`) REFERENCES `offices` (`officeCode`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE `employees_undo` ( + `date_of_change` timestamp(2) NOT NULL DEFAULT CURRENT_TIMESTAMP(2), + `employeeNumber` int NOT NULL, + `lastName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `firstName` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `extension` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `officeCode` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `reportsTo` int DEFAULT NULL, + `jobTitle` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `change_type` varchar(50) NOT NULL, + PRIMARY KEY (`date_of_change`), + UNIQUE KEY `date_of_change_UNIQUE` (`date_of_change`) + +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- STEP 2 +CREATE + + TRIGGER TRG_BEFORE_UPDATE_ON_employees + BEFORE UPDATE ON employees FOR EACH ROW + + INSERT INTO `employees_undo` SET + `date_of_change` = CURRENT_TIMESTAMP(2), + `employeeNumber` = OLD.`employeeNumber` , + `lastName` = OLD.`lastName` , + `firstName` = OLD.`firstName` , + `extension` = OLD.`extension` , + `email` = OLD.`email` , + `officeCode` = OLD.`officeCode` , + `reportsTo` = OLD.`reportsTo` , + `jobTitle` = OLD.`jobTitle` , + `change_type` = 'An update DML operation was executed'; + + -- STEP 4 + SHOW TRIGGERS; + UPDATE `employees` +SET +`lastName` = 'Muiruri' +WHERE + +`employeeNumber` = '1056'; +SELECT * FROM employees_undo; + +-- STEP 5 Create a table to store reminders +CREATE TABLE `customers_data_reminders` ( +`customerNumber` int NOT NULL COMMENT 'Identifies the customer whose data +is partly missing', +`customers_data_reminders_timestamp` timestamp(2) NOT NULL DEFAULT +CURRENT_TIMESTAMP(2) COMMENT 'Records the time when the missing data was +detected', +`customers_data_reminders_message` varchar(100) NOT NULL COMMENT 'Records +a message that helps the customer service personnel to know what data is +missing from the customer\'s record', +`customers_data_reminders_status` tinyint NOT NULL DEFAULT '0' COMMENT +'Used to record the status of a reminder (0 if it has not yet been +addressed and 1 if it has been addressed)', +PRIMARY KEY +(`customerNumber`,`customers_data_reminders_timestamp`,`customers_data_remi +nders_message`,`customers_data_reminders_status`), +CONSTRAINT `FK_1_customers_TO_M_customers_data_reminders` FOREIGN KEY +(`customerNumber`) REFERENCES `customers` (`customerNumber`) +ON DELETE CASCADE +ON UPDATE CASCADE +) ENGINE=InnoDB COMMENT='Used to remind the customer service personnel +about a client\'s missing data. This enables them to ask the client to +provide the data during the next interaction with the client.' + +-- STEP 6 Create a trigger that has multiple statements +DELIMITER $$ +CREATE TRIGGER TRG_AFTER_INSERT_ON_customers +AFTER INSERT ON customers FOR EACH ROW +BEGIN +IF NEW.postalCode IS NULL THEN +INSERT INTO `customers_data_reminders` +(`customerNumber`, `customers_data_reminders_timestamp`, +`customers_data_reminders_message`) +VALUES (NEW.customerNumber, CURRENT_TIMESTAMP(2), 'Please remember +to record the client\'s postal code'); +END IF; +IF NEW.salesRepEmployeeNumber IS NULL THEN +INSERT INTO `customers_data_reminders` +(`customerNumber`, `customers_data_reminders_timestamp`, +`customers_data_reminders_message`) +VALUES (NEW.customerNumber, CURRENT_TIMESTAMP(2), 'Please remember +to assign a sales representative to the client'); +END IF; +IF NEW.creditLimit IS NULL THEN +INSERT INTO `customers_data_reminders` +(`customerNumber`, `customers_data_reminders_timestamp`, +`customers_data_reminders_message`) +VALUES (NEW.customerNumber, CURRENT_TIMESTAMP(2), 'Please remember +to set the client\'s credit limit'); +END IF; +END$$ +DELIMITER ; + +-- STEP 7 Confirm the trigger is fired when insertion is made +INSERT INTO `customers` +(`customerNumber`, `customerName`, `contactLastName`, `contactFirstName`, +`phone`, `addressLine1`, `city`, `country`) +VALUES +('497', 'House of Leather', 'Wambua', 'Gabriel', '+254 720 123 456', '9 +Agha Khan Walk', 'Nairobi', 'Kenya'); + +-- STEP 8 Create a new table to store parts data +CREATE TABLE part ( +part_no VARCHAR(18) PRIMARY KEY, +part_description VARCHAR(255), +part_supplier_tax_PIN VARCHAR (11) CHECK (part_supplier_tax_PIN REGEXP +'^[A-Z]{1}[0-9]{9}[A-Z]{1}$'), +part_supplier_email VARCHAR (55), +part_buyingprice DECIMAL(10,2 ) NOT NULL CHECK (part_buyingprice >= 0), +part_sellingprice DECIMAL(10,2) NOT NULL, +CONSTRAINT CHK_part_sellingprice_GT_buyingprice CHECK +(part_sellingprice >= part_buyingprice), +CONSTRAINT CHK_part_valid_supplier_email CHECK (part_supplier_email +REGEXP '^[a-zA-Z0-9]{3,}@[a-zA-Z0-9]{1,}\\.[a-zA-Z0-9.]{1,}$') +); + +-- STEP 9. Create the following user-defined error in a trigger +DELIMITER // +CREATE TRIGGER TRG_BEFORE_UPDATE_ON_part +BEFORE UPDATE ON part FOR EACH ROW +BEGIN +DECLARE errorMessage VARCHAR(255); +DECLARE EXIT HANDLER FOR SQLSTATE '45000' +BEGIN +RESIGNAL SET MESSAGE_TEXT = errorMessage; +END; +SET errorMessage = CONCAT('The new selling price of ', +NEW.part_sellingprice, ' cannot be 2 times greater than the current selling +price of ', OLD.part_sellingprice); +IF NEW.part_sellingprice > OLD.part_sellingprice * 2 THEN +SIGNAL SQLSTATE '45000'; +END IF; +END// +DELIMITER ; + + +-- STEP 10. Confirm that the static, dynamic, and semantic constraints are working +INSERT INTO `part` (`part_no`, `part_description`, `part_supplier_tax_PIN`, +`part_supplier_email`, `part_buyingprice`, `part_sellingprice`) +VALUES ('001', 'The tyres of a 1958 Chevy Corvette Limited Edition', +'P05120157U', 'toysRus@gmail', '100', '50'); \ No newline at end of file diff --git a/Lab2-triggers_and_check_constraints.sql b/Lab2-triggers_and_check_constraints.sql new file mode 100644 index 0000000..c6d8c81 --- /dev/null +++ b/Lab2-triggers_and_check_constraints.sql @@ -0,0 +1,96 @@ +-- switch to the current database +USE 75855_lab2_triggers; + +-- STEP 1: Transaction + +-- turn of autocommit option +SET autocommit = OFF; + +-- set isolation level +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; + +START TRANSACTION; + +-- create the new column in orders table to record the orderTotal amount +ALTER TABLE orders +ADD orderTotal decimal(10,2); + +-- create the new column in payments table to record the ordorderNumber +ALTER TABLE payments +ADD orderNumber int NOT NULL; +-- Add a check constraint to check the credit limit column in the customers table +ALTER TABLE customers +ADD CONSTRAINT check_credit_limit CHECK (creditLimit >= 0); + +-- Create Triggers + +-- Trigger 1: check if the customerNumber is valid +DELIMITER // +CREATE TRIGGER order_customer_check +BEFORE INSERT ON orders +FOR EACH ROW +BEGIN + -- Check if the customerNumber exists in the customers table + SELECT COUNT(*) INTO @customer_exists + FROM customers + WHERE customerNumber = NEW.customerNumber; + + IF @customer_exists = 0 THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'Invalid customerNumber'; + END IF; + +END; +// +DELIMITER ; + +-- Trigger 2: Check if a payment is made when an order is inserted +DROP TRIGGER IF EXISTS order_payment_check; + +-- Recreate the trigger with new logic +DELIMITER // +CREATE TRIGGER order_payment_check +BEFORE INSERT ON payments +FOR EACH ROW +BEGIN + DECLARE order_amount DECIMAL(10, 2); + + -- Get the total amount of the corresponding order + SELECT orderTotal INTO order_amount + FROM orders + WHERE orderNumber = NEW.orderNumber; + + -- Check if the payment amount is less than the order amount + IF NEW.amount < order_amount THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'Payment amount is less than the order amount'; + END IF; +END; +// +DELIMITER ; + +-- Create a save point before an order is made +SAVEPOINT order_savepoint; + +-- Insert a new order +SELECT @orderNumber := MAX(orderNumber)+1 FROM orders; +INSERT INTO orders (orderNumber,orderDate, requiredDate, shippedDate, status, comments, customerNumber, orderTotal) +VALUES (@orderNumber,DATE(NOW()), DATE(DATE_ADD(NOW(), INTERVAL 3 DAY)), NULL, 'Processing', 'New order', 103, 1500); + +select * from orders order by orderNumber desc; + +select * from payments order by customerNumber asc; + +-- Create a save point before a payment is made +SAVEPOINT payment_savepoint; + +-- Record a payment for the order +INSERT INTO payments (customerNumber, checkNumber, paymentDate, amount, orderNumber) +VALUES (103, 'CHK123456', DATE(NOW()), 1200, @orderNumber); + +-- Commit the transaction +COMMIT; + +SET autocommit = ON; + + diff --git a/README.md b/README.md index cb21b12..9ac4bee 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-24ddc0f5d75046c5622901739e7c5dd533143b0c8e959d652212380cedb1ea36.svg)](https://classroom.github.com/a/8egdwdH8) [![Open in Visual Studio Code](https://classroom.github.com/assets/open-in-vscode-718a45dd9cf7e7f842a935f5ebbe5719a5e09af4491e668f4dbf3b35d5cca122.svg)](https://classroom.github.com/online_ide?assignment_repo_id=12109866&assignment_repo_type=AssignmentRepo) # Required Lab Work Submission Please refer to the lab manual (Lab 2 on transactions and check constraints) available here for the detailed instructions: [https://elearning.strathmore.edu/course/view.php?id=3277](https://elearning.strathmore.edu/course/view.php?id=3277) diff --git a/makhatsa.mysql b/makhatsa.mysql new file mode 100644 index 0000000..f8d3c98 --- /dev/null +++ b/makhatsa.mysql @@ -0,0 +1,2 @@ +----to list database +show DATABASES; \ No newline at end of file