From f3909f68a21e8fae60d4c66155159b6719a26091 Mon Sep 17 00:00:00 2001 From: Divyansh Garg Date: Fri, 3 Oct 2025 21:36:52 +0530 Subject: [PATCH 1/2] Fixed bugs in psql-query.md file --- psql-query.md | 130 +++++++++++++++++++++----------------------------- 1 file changed, 55 insertions(+), 75 deletions(-) diff --git a/psql-query.md b/psql-query.md index b5bab1b..f8e6dd7 100644 --- a/psql-query.md +++ b/psql-query.md @@ -1,124 +1,110 @@ ```sql --- Create a table named department +-- 1. Create a table named department CREATE TABLE department ( dept_name VARCHAR(100) PRIMARY KEY, building VARCHAR(120) NOT NULL, - budget NUMERIC(12,2) NOT NULL DEFAULT 'undecided', + budget NUMERIC(12,2) NOT NULL DEFAULT 0.00, num_staff INT ); --- Insert values into the department table +-- 2. Insert unique values into the department table INSERT INTO department (dept_name, building, budget, num_staff) -VALUES ('cse', 'ma wazed', 12.20, 10), - ('cse', 'ma wazed', 12.20, 10), - ('cse', 'ma wazed', 12.20, 10); +VALUES ('CSE', 'MA Wazed', 12000.00, 10), + ('EEE', 'Main Building', 15000.00, 8), + ('ME', 'Workshop Block', 13000.00, 12); --- Add a column named dept_code to the existing department table -ALTER TABLE department ADD COLUMN dept_code VARCHAR(6) NOT NULL; +-- 3. Add new columns with default values +ALTER TABLE department ADD COLUMN dep_code VARCHAR(15) DEFAULT 'NA'; --- Add a column named dep_code to the existing department table after the dept_name column -ALTER TABLE department ADD COLUMN dep_code VARCHAR(6) NOT NULL AFTER dept_name; - --- Remove the dept_code column from the department table -ALTER TABLE department DROP COLUMN dept_code; - --- Modify the data type of the dept_code column to VARCHAR(10) in the department table -ALTER TABLE department ALTER COLUMN dept_code TYPE VARCHAR(10); - --- Delete the department table along with its structure -DROP TABLE department; - --- Delete all data from the department table, keeping the table structure -DELETE FROM department; --- OR -TRUNCATE department; - --- Insert values into a table (TABLE2) from another table (TABLE1) based on a condition -INSERT INTO TABLE2 (employeeId, employeeName) -SELECT id, firstName FROM TABLE1 WHERE CONDITION; +-- 4. Insert values into another table from a table +-- Make sure employee_archive exists +INSERT INTO employee_archive (employeeId, employeeName) +SELECT emp_id, first_name +FROM employee +WHERE salary > 50000; --- Update the salary column of the instructor table by increasing it by 5% for instructors with salary below the average salary +-- 5. Update instructor salary below average by 5% UPDATE instructor SET salary = salary * 1.05 WHERE salary < (SELECT AVG(salary) FROM instructor); --- Update the salary column of the instructor table using a case statement +-- 6. Update salary using CASE UPDATE instructor SET salary = CASE WHEN salary <= 100000 THEN salary * 1.05 ELSE salary * 1.03 END; --- Retrieve records from the instructor table and order the results by dept_name in descending order and salary in ascending order +-- 7. Select instructors ordered by dept_name DESC, salary ASC SELECT * FROM instructor ORDER BY dept_name DESC, salary ASC; --- Retrieve a limited number of rows from a table +-- 8. Retrieve limited rows SELECT * -FROM TABLE_NAME -LIMIT n; +FROM instructor +LIMIT 5; -- first 5 rows --- Retrieve a limited number of rows from a table, starting from the mth row +-- 9. Retrieve rows with offset SELECT * -FROM TABLE_NAME -LIMIT n OFFSET m; +FROM instructor +LIMIT 5 OFFSET 10; -- rows 11-15 --- Retrieve records from the instructor table where the name is not 'pranto' or 'Zahid' +-- 10. Select where name not in list SELECT * FROM instructor -WHERE name NOT IN ('pranto', 'Zahid'); +WHERE name NOT IN ('Pranto', 'Zahid'); --- Retrieve records from the instructor table where the id is within a range +-- 11. Select where id is within a subquery SELECT * FROM instructor WHERE id IN (SELECT id FROM instructor WHERE id < 500); --- Retrieve records from the instructor table where the salary is between 5000 and 10000 +-- 12. Select salary between 5000 and 10000 SELECT sname FROM instructor WHERE salary BETWEEN 5000 AND 10000; --- Retrieve records from the instructor table where the salary is NULL +-- 13. Select rows where salary is NULL SELECT * FROM instructor WHERE salary IS NULL; --- Retrieve records from the instructor table where the id ends with '5' followed by any character +-- 14. Select id ending with '5' and any character SELECT * FROM instructor -WHERE id LIKE '%5_'; +WHERE id::TEXT LIKE '%5_'; --- Find the average salary of instructors in the CSE department -SELECT AVG(salary) +-- 15. Average salary of CSE department +SELECT AVG(salary) AS avg_salary FROM instructor WHERE dept_name = 'CSE'; --- Find the number of departments in the instructor relation -SELECT COUNT(DISTINCT dept_name) +-- 16. Number of distinct departments +SELECT COUNT(DISTINCT dept_name) AS num_departments FROM instructor; --- Find the number of tuples (rows) in the instructor relation +-- 17. Number of rows in instructor table SELECT COUNT(*) AS num_rows FROM instructor; --- Retrieve the department name and the average salary of instructors for each department +-- 18. Department name and average salary SELECT dept_name, AVG(salary) AS avg_salary FROM instructor GROUP BY dept_name; --- Retrieve the department name and the number of instructors in each department +-- 19. Department name and number of instructors SELECT dept_name, COUNT(id) AS num_of_teacher FROM instructor GROUP BY dept_name; --- Perform a natural join between the employee and branch tables -SELECT branch_name, first_name, last_name +-- 20. Join example: LEFT JOIN employee and branch +SELECT branch.branch_name, employee.first_name, employee.last_name FROM employee -[LEFT|RIGHT] JOIN branch +LEFT JOIN branch ON employee.emp_id = branch.mgr_id; --- Perform a nested query to retrieve employee names based on their IDs in the works_with table +-- 21. Nested query example SELECT employee.first_name, employee.last_name FROM employee WHERE employee.emp_id IN ( @@ -127,7 +113,7 @@ WHERE employee.emp_id IN ( WHERE total_sales > 30000 ); --- Create a trigger that inserts values into another table when a new row is inserted into table1 +-- 22. Trigger example: insert into table2 when a row is inserted in table1 CREATE OR REPLACE FUNCTION triggertest() RETURNS TRIGGER AS $$ BEGIN @@ -141,14 +127,14 @@ BEFORE INSERT ON table1 FOR EACH ROW EXECUTE FUNCTION triggertest(); --- Create a trigger with conditional statements that inserts values into another table based on the sex column in the employee table -CREATE OR REPLACE FUNCTION my_trigger() +-- 23. Trigger with conditional logic +CREATE OR REPLACE FUNCTION sex_trigger() RETURNS TRIGGER AS $$ BEGIN IF NEW.sex = 'M' THEN INSERT INTO trigger_test VALUES ('added male employee'); ELSIF NEW.sex = 'F' THEN - INSERT INTO trigger_test VALUES ('added female'); + INSERT INTO trigger_test VALUES ('added female employee'); ELSE INSERT INTO trigger_test VALUES ('added other employee'); END IF; @@ -156,21 +142,15 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE TRIGGER my_trigger +CREATE TRIGGER my_sex_trigger BEFORE INSERT ON employee FOR EACH ROW -EXECUTE FUNCTION my_trigger(); - --- Example of a complex query involving multiple tables and joins -SELECT t.eName -FROM ( - SELECT * - FROM employee - NATURAL JOIN manages -) AS t -INNER JOIN employee AS e -ON t.mName = e.eName -AND t.city = e.city -AND t.street = e.street; - -``` \ No newline at end of file +EXECUTE FUNCTION sex_trigger(); + +-- 24. Complex query: explicit JOIN instead of NATURAL JOIN +SELECT e1.eName +FROM manages m +INNER JOIN employee e1 ON m.emp_id = e1.emp_id +INNER JOIN employee e2 ON m.mName = e2.eName + AND m.city = e2.city + AND m.street = e2.street; From b229d5f988693d81a08e08bfe00407f427afefb9 Mon Sep 17 00:00:00 2001 From: Divyansh Garg Date: Fri, 3 Oct 2025 23:10:26 +0530 Subject: [PATCH 2/2] Add triggers example with audit logging --- psql/advance.md | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/psql/advance.md b/psql/advance.md index 31d5a25..cbedfb9 100644 --- a/psql/advance.md +++ b/psql/advance.md @@ -57,7 +57,7 @@ CREATE TABLE example_table ( ); ``` -Constraints can be defined when a table is created or added later using the ALTER TABLE statement. Constraints can also be dropped using tthe ALTER TABLE statement. +Constraints can be defined when a table is created or added later using the ALTER TABLE statement. Constraints can also be dropped using the ALTER TABLE statement. ## Joins @@ -198,25 +198,48 @@ In the above syntax, the trigger function trigger_function_name is created using Example: ```sql --- Example of creating a trigger +-- 1. Create target table +CREATE TABLE target_table ( + id SERIAL PRIMARY KEY, + name TEXT, + age INT +); + +-- 2. Create audit table +CREATE TABLE audit_table ( + audit_id SERIAL PRIMARY KEY, + event_type TEXT NOT NULL, + event_time TIMESTAMP NOT NULL DEFAULT NOW(), + table_name TEXT NOT NULL, + old_data JSONB, + new_data JSONB +); + +-- 3. Create trigger function CREATE OR REPLACE FUNCTION log_changes() RETURNS TRIGGER AS $$ BEGIN IF TG_OP = 'INSERT' THEN INSERT INTO audit_table (event_type, event_time, table_name, new_data) - VALUES ('INSERT', NOW(), TG_TABLE_NAME, NEW); + VALUES ('INSERT', NOW(), TG_TABLE_NAME, to_jsonb(NEW)); + RETURN NEW; + ELSIF TG_OP = 'UPDATE' THEN INSERT INTO audit_table (event_type, event_time, table_name, old_data, new_data) - VALUES ('UPDATE', NOW(), TG_TABLE_NAME, OLD, NEW); + VALUES ('UPDATE', NOW(), TG_TABLE_NAME, to_jsonb(OLD), to_jsonb(NEW)); + RETURN NEW; + ELSIF TG_OP = 'DELETE' THEN INSERT INTO audit_table (event_type, event_time, table_name, old_data) - VALUES ('DELETE', NOW(), TG_TABLE_NAME, OLD); + VALUES ('DELETE', NOW(), TG_TABLE_NAME, to_jsonb(OLD)); + RETURN OLD; END IF; - RETURN NEW; + RETURN NULL; END; $$ LANGUAGE plpgsql; +-- 4. Attach trigger to target table CREATE TRIGGER audit_trigger AFTER INSERT OR UPDATE OR DELETE ON target_table