-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay15.sql
464 lines (389 loc) · 13.4 KB
/
Day15.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
use zoom;
-- Triggers
/*
Definition of Triggers :
A trigger is a special type of stored procedure in a database that automatically executes (or "fires")
in response to certain events on a particular table or view. Triggers are used to enforce business rules,
maintain data integrity, and automate system tasks without requiring explicit calls from applications.
Triggers are powerful tools in database management, allowing for automated responses to data changes
while ensuring data integrity and enforcing business rules.
Key Characteristics of Triggers :
1. Automatic Execution: Triggers are executed automatically when a specified event occurs.
2. Event-Driven: They are associated with specific events such as INSERT, UPDATE, or DELETE.
3. Row-Level or Statement-Level: Triggers can operate on each row affected by the event (row-level)
or once for the entire statement (statement-level).
4. Performance: Triggers can impact performance, especially if they contain complex logic or are
executed frequently.
5. Debugging: Debugging triggers can be challenging, as they execute automatically and may not be visible in
the application flow.
Types of Triggers :
1. BEFORE Triggers: Executed before the triggering event (e.g., before an INSERT, UPDATE, or DELETE operation).
2. AFTER Triggers: Executed after the triggering event has occurred.
3. INSTEAD OF Triggers(Not Supported in MySQL): Used primarily with views, these triggers execute in place of
the triggering event.
Structure of SQLSTATE
Format: The SQLSTATE value is a five-character string, where the first two characters represent
the class of the error, and the last three characters provide more specific information about the error.
Classes: The first two characters indicate the general category of the error.
For example:
- 00 indicates successful completion.
- 01 indicates a warning.
- 02 indicates no data found.
- 22 indicates a data exception (e.g., invalid data).
- 45 indicates a user-defined exception.
*/
-- Step 1: Create the Table
CREATE TABLE Accounts (
AccountID INT AUTO_INCREMENT PRIMARY KEY,
AccountHolder VARCHAR(100) NOT NULL,
Balance DECIMAL(10, 2) NOT NULL
);
INSERT INTO Accounts (AccountHolder, Balance) VALUES
('Rahul Sharma', 15000.00), -- 15,000 INR
('Priya Gupta', 25000.50), -- 25,000.50 INR
('Amit Verma', 1000.75), -- 1,000.75 INR
('Sneha Reddy', 50000.00), -- 50,000 INR
('Vikram Singh', 7500.00); -- 7,500 INR
select * from Accounts;
-- Example 1: BEFORE Trigger
-- Scenario: Preventing negative balances in a bank account.
DELIMITER //
CREATE TRIGGER prevent_negative_balance
BEFORE UPDATE ON Accounts
FOR EACH ROW
BEGIN
IF NEW.balance < 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Balance cannot be negative';
END IF;
END;
//DELIMITER ;
UPDATE Accounts SET Balance = -5000.00 WHERE AccountID = 2; -- This will trigger an error
UPDATE Accounts SET Balance = 20000.00 WHERE AccountID = 3; -- This will succeed
-- Example 2: AFTER Trigger
-- Scenario: Logging changes to an audit table after an account balance is updated.
-- Step 1: Create a table
CREATE TABLE AuditLog (
log_id INT AUTO_INCREMENT PRIMARY KEY,
account_id INT,
old_balance DECIMAL(10, 2),
new_balance DECIMAL(10, 2),
change_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO AuditLog (account_id, old_balance, new_balance) VALUES
(1, 15000.00, 30000.00), -- Example: Account ID 1 changed from 15000.00 to 30000.00
(2, 25000.50, 20000.00), -- Example: Account ID 2 changed from 25000.50 to 20000.00
(3, 1000.75, 500.00); -- Example: Account ID 3 changed from 1000.75 to 500.00
select * from AuditLog;
-- Step 2: Create the Trigger
DELIMITER //
CREATE TRIGGER log_balance_change
AFTER UPDATE ON Accounts
FOR EACH ROW
BEGIN
INSERT INTO AuditLog (account_id, old_balance, new_balance)
VALUES (OLD.AccountID, OLD.Balance, NEW.Balance);
END;
//
DELIMITER ;
-- Step 3: Test the Trigger
UPDATE Accounts SET Balance = 150000.00 WHERE AccountID = 2; -- Update the balance of AccountID 1
select * from Accounts;
select * from AuditLog;
UPDATE Accounts SET Balance = 150.00 WHERE AccountID = 3; -- Update the balance of AccountID 1
select * from Accounts;
select * from AuditLog;
-- Example 3: INSTEAD OF Trigger (Not Supported in Mysql)
-- Scenario: Updating a view instead of the underlying table.
DELIMITER //
CREATE VIEW AccountView AS
SELECT account_id, account_holder, balance
FROM Accounts;
CREATE TRIGGER update_account_view
INSTEAD OF UPDATE ON AccountView
FOR EACH ROW
BEGIN
UPDATE Accounts
SET balance = NEW.balance
WHERE account_id = OLD.account_id;
END;
//DELIMITER ;
-- Example 4: BEFORE INSERT Trigger
-- Scenario: Automatically set the creation date for new accounts.
-- Step 1: Ensure the Accounts Table Has a creation_date Column
ALTER TABLE Accounts
ADD COLUMN creation_date DATETIME;
select * from Accounts;
-- Step 2: Create the BEFORE INSERT Trigger
DELIMITER //
CREATE TRIGGER set_creation_date
BEFORE INSERT ON Accounts
FOR EACH ROW
BEGIN
SET NEW.creation_date = NOW();
END;
//DELIMITER ;
-- Step 3: Test the Trigger
INSERT INTO Accounts (accountid, accountholder, balance)
VALUES (20, 'John Doe', 1000.00);
select * from Accounts;
-- Example 5: AFTER DELETE Trigger
-- Scenario: Log deletions of accounts to an audit table.
-- Step 1: Create the DeletedAccountsLog Table
CREATE TABLE DeletedAccountsLog (
log_id INT AUTO_INCREMENT PRIMARY KEY,
accountid INT,
accountholder VARCHAR(100),
deleted_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Step 2: Create the AFTER DELETE Trigger
DELIMITER //
CREATE TRIGGER log_account_deletion
AFTER DELETE ON Accounts
FOR EACH ROW
BEGIN
INSERT INTO DeletedAccountsLog (accountid, accountholder)
VALUES (OLD.accountid, OLD.accountholder);
END;
//
DELIMITER ;
-- Step 3: Test the Trigger
DELETE FROM Accounts WHERE accountid = 20; -- Replace with an existing account ID
SELECT * FROM DeletedAccountsLog WHERE accountid = 20; -- Replace with the deleted account ID
-- Example 6: BEFORE UPDATE Trigger
-- Scenario: Prevent updates to the account holder's name if the balance is not zero.
DELIMITER //
CREATE TRIGGER prevent_name_change_if_balance_not_zero
BEFORE UPDATE ON Accounts
FOR EACH ROW
BEGIN
IF OLD.balance <> 0 AND OLD.accountholder <> NEW.accountholder THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot change account holder name when balance is not zero';
END IF;
END;
//DELIMITER ;
-- Test the Trigger
UPDATE Accounts
SET accountholder = 'Bob Johnson'
WHERE accountid = 2; -- Bob Smith has a balance of 0.00
SELECT * FROM Accounts;
-- Example 7: AFTER INSERT Trigger
-- Scenario: Automatically create an entry in the AuditLog table when a new account is created.
DELIMITER //
CREATE TRIGGER log_new_account_creation
AFTER INSERT ON Accounts
FOR EACH ROW
BEGIN
INSERT INTO AuditLog (account_id, old_balance, new_balance)
VALUES (NEW.accountid, 0, NEW.balance);
END;
//DELIMITER ;
-- Test the Trigger
INSERT INTO Accounts (accountholder, balance) VALUES ('John Doe', 1500.00);
SELECT * FROM AuditLog;
-- Example 8: BEFORE INSERT Trigger
-- Scenario: Ensure that the account balance cannot be set to a value greater than a specified limit.
DELIMITER //
CREATE TRIGGER prevent_exceeding_balance_limit
BEFORE INSERT ON Accounts
FOR EACH ROW
BEGIN
IF NEW.balance > 10000 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Balance cannot exceed 10,000';
END IF;
END;
//DELIMITER ;
-- Test the Trigger
INSERT INTO Accounts (accountholder, balance) VALUES ('Alice Johnson', 15000.00);
-- Example 9: AFTER UPDATE Trigger
-- Scenario: Update a summary table whenever an account balance is updated.
CREATE TABLE AccountSummary (
total_accounts INT,
total_balance DECIMAL(10, 2)
);
-- Initialize summary table
INSERT INTO AccountSummary (total_accounts, total_balance)
SELECT COUNT(*), SUM(balance) FROM Accounts;
DELIMITER //
CREATE TRIGGER update_account_summary
AFTER UPDATE ON Accounts
FOR EACH ROW
BEGIN
UPDATE AccountSummary
SET total_balance = total_balance + (NEW.balance - OLD.balance);
END;
//DELIMITER ;
-- Test the Trigger
INSERT INTO Accounts (accountholder, balance) VALUES
('Alice Johnson', 1000.00),
('Bob Smith', 2000.00),
('Charlie Brown', 3000.00);
set SQL_SAFE_UPDATES=0;
UPDATE Accounts
SET balance = 2500.00
WHERE accountid = 3; -- Update Alice's balance
SELECT * FROM AccountSummary;
-- Example 10: BEFORE DELETE Trigger
-- Scenario: Prevent deletion of accounts that have a balance greater than zero.
DELIMITER //
CREATE TRIGGER prevent_account_deletion_with_balance
BEFORE DELETE ON Accounts
FOR EACH ROW
BEGIN
IF OLD.balance > 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot delete account with a positive balance';
END IF;
END;
//DELIMITER ;
-- Example 11: BEFORE INSERT Trigger
-- Scenario: Ensure that the account holder's name is not empty when creating a new account.
DELIMITER //
CREATE TRIGGER prevent_empty_account_holder
BEFORE INSERT ON Accounts
FOR EACH ROW
BEGIN
IF NEW.account_holder IS NULL OR TRIM(NEW.account_holder) = '' THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Account holder name cannot be empty';
END IF;
END;
//
DELIMITER ;
-- Example 12: AFTER UPDATE Trigger
-- Scenario: Notify an external system (simulated here by inserting into a Notifications table)
-- whenever an account balance is updated.
CREATE TABLE Notifications (
notification_id INT AUTO_INCREMENT PRIMARY KEY,
account_id INT,
message VARCHAR(255),
notification_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
DELIMITER //
CREATE TRIGGER notify_balance_update
AFTER UPDATE ON Accounts
FOR EACH ROW
BEGIN
INSERT INTO Notifications (account_id, message)
VALUES (NEW.account_id, CONCAT('Account balance updated from ', OLD.balance, ' to ', NEW.balance));
END;
//
DELIMITER ;
-- Example 13: BEFORE UPDATE Trigger
-- Scenario: Prevent changes to the balance if the account is marked as inactive.
DELIMITER //
CREATE TRIGGER prevent_balance_change_if_inactive
BEFORE UPDATE ON Accounts
FOR EACH ROW
BEGIN
IF OLD.status = 'inactive' THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot change balance of inactive accounts';
END IF;
END;
//
DELIMITER ;
-- Example 14: AFTER INSERT Trigger
-- Scenario: Automatically create a welcome message for new accounts in a Messages table.
CREATE TABLE Messages (
message_id INT AUTO_INCREMENT PRIMARY KEY,
account_id INT,
message TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
DELIMITER //
CREATE TRIGGER create_welcome_message
AFTER INSERT ON Accounts
FOR EACH ROW
BEGIN
INSERT INTO Messages (account_id, message)
VALUES (NEW.account_id, CONCAT('Welcome, ', NEW.account_holder, '! Your account has been created.'));
END;
//
DELIMITER ;
-- Example 15: BEFORE DELETE Trigger
-- Scenario: Log the details of an account before it is deleted.
DELIMITER //
CREATE TABLE DeletedAccountsLog (
log_id INT AUTO_INCREMENT PRIMARY KEY,
account_id INT,
account_holder VARCHAR(100),
balance DECIMAL(10, 2),
deleted_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TRIGGER log_account_deletion_details
BEFORE DELETE ON Accounts
FOR EACH ROW
BEGIN
INSERT INTO DeletedAccountsLog (account_id, account_holder, balance)
VALUES (OLD.account_id, OLD.account_holder, OLD.balance);
END;
//
DELIMITER ;
-- Example 16: AFTER UPDATE Trigger
-- Scenario: Update a LastUpdated timestamp in the Accounts table whenever an account is updated.
ALTER TABLE Accounts ADD COLUMN last_updated DATETIME;
DELIMITER //
CREATE TRIGGER update_last_updated
AFTER UPDATE ON Accounts
FOR EACH ROW
BEGIN
UPDATE Accounts
SET last_updated = NOW()
WHERE account_id = NEW.account_id;
END;
//
DELIMITER ;
-- Example 17: BEFORE INSERT Trigger
-- Scenario: Ensure that the account balance is not negative when creating a new account.
DELIMITER //
CREATE TRIGGER prevent_negative_balance_on_insert
BEFORE INSERT ON Accounts
FOR EACH ROW
BEGIN
IF NEW.balance < 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Balance cannot be negative on account creation';
END IF;
END;
//
DELIMITER ;
-- Example 18: AFTER INSERT Trigger
-- Scenario: Update a summary table with the total number of accounts whenever a new account is created.
CREATE TABLE AccountSummary (
total_accounts INT DEFAULT 0
);
-- Initialize summary table
INSERT INTO AccountSummary (total_accounts) VALUES (0);
DELIMITER //
CREATE TRIGGER update_account_summary_on_insert
AFTER INSERT ON Accounts
FOR EACH ROW
BEGIN
UPDATE AccountSummary
SET total_accounts = total_accounts + 1;
END;
//
DELIMITER ;
-- Example 19: BEFORE UPDATE Trigger
-- Scenario: Prevent changes to the account holder's name if the account has been active for more than a year.
DELIMITER //
CREATE TRIGGER prevent_name_change_if_active_for_year
BEFORE UPDATE ON Accounts
FOR EACH ROW
BEGIN
IF DATEDIFF(NOW(), OLD.creation_date) > 365 AND OLD.account_holder <> NEW.account_holder THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot change account holder name after 1 year of account creation';
END IF;
END;
//
DELIMITER ;
-- Example 20: AFTER DELETE Trigger
-- Scenario: Update a summary table with the total number of accounts whenever an account is deleted.
-- Assuming the AccountSummary table has already been created
-- and initialized with a total_accounts column.
DELIMITER //
CREATE TRIGGER update_account_summary_on_delete
AFTER DELETE ON Accounts
FOR EACH ROW
BEGIN
UPDATE AccountSummary
SET total_accounts = total_accounts - 1;
END;
//
DELIMITER ;