{"id":30004645,"url":"https://github.com/alifa-ara-heya/postgresql-commands","last_synced_at":"2026-02-11T01:03:38.188Z","repository":{"id":294070089,"uuid":"985896922","full_name":"alifa-ara-heya/PostgreSQL-commands","owner":"alifa-ara-heya","description":"PostgreSQL commands","archived":false,"fork":false,"pushed_at":"2025-09-02T02:50:43.000Z","size":69,"stargazers_count":8,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-02T04:25:15.834Z","etag":null,"topics":["postgres","postgresql","postgresql-database"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alifa-ara-heya.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-18T18:40:20.000Z","updated_at":"2025-09-02T02:50:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"da8e7e0c-2ec9-44d6-b6d1-3523da276387","html_url":"https://github.com/alifa-ara-heya/PostgreSQL-commands","commit_stats":null,"previous_names":["alifa-ara-heya/postgresql-commands"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/alifa-ara-heya/PostgreSQL-commands","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alifa-ara-heya%2FPostgreSQL-commands","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alifa-ara-heya%2FPostgreSQL-commands/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alifa-ara-heya%2FPostgreSQL-commands/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alifa-ara-heya%2FPostgreSQL-commands/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alifa-ara-heya","download_url":"https://codeload.github.com/alifa-ara-heya/PostgreSQL-commands/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alifa-ara-heya%2FPostgreSQL-commands/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29323969,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-11T00:34:26.354Z","status":"ssl_error","status_checked_at":"2026-02-11T00:34:09.494Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["postgres","postgresql","postgresql-database"],"created_at":"2025-08-05T07:16:59.224Z","updated_at":"2026-02-11T01:03:38.175Z","avatar_url":"https://github.com/alifa-ara-heya.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"## **PostgreSQL Quick Reference**\n\n## [Table of Contents](#table-of-contents)\n\n1. [Connecting to PostgreSQL](#1-connecting-to-postgresql)\n2. [Creating Database](#2-creating-database)\n3. [Switching Databases and Exiting](#3-switching-databases-and-exiting)\n4. [Listing Information](#4-listing-information)\n5. [Managing Users / Roles](#5-managing-users--roles)\n6. [Login as New User](#6-login-as-new-user)\n7. [Table Operations](#7-table-operations)\n8. [Granting and Revoking Permissions](#8-granting-and-revoking-permissions)\n9. [Renaming and Deleting Databases](#9-renaming-and-deleting-databases)\n10. [Renaming and Deleting Tables](#10-renaming-and-deleting-tables)\n11. [Table with Constraints](#11-table-with-constraints)\n12. [Clearing Terminal](#12-clearing-terminal)\n13. [PostgreSQL Data Types](#13-postgresql-data-types)\n14. [Modifying Columns in PostgreSQL](#14-modifying-columns-in-postgresql)\n15. [Creating a Table](#15-creating-a-table)\n16. [Selecting Data](#16-selecting-data)\n17. [Data Filtering (`WHERE` Clause)](#17-data-filtering-where-clause)\n18. [Scalar Functions](#18-scalar-functions)\n19. [Aggregate Functions](#19-aggregate-functions)\n20. [`NULL` Filtering](#20-null-filtering)\n21. [Handling `NULL` with COALESCE](#21-handling-null-with-coalesce)\n22. [`IN` Operator](#22-in-operator)\n23. [`BETWEEN` Operator](#23-between-operator)\n24. [`LIKE` Operator](#24-like-operator)\n25. [Updating and Deleting Data](#25-updating-and-deleting-data)\n26. [Pagination (`LIMIT` and `OFFSET`)](#26-pagination-limit-and-offset)\n27. [Date, Time, and Boolean Operations](#27-date-time-and-boolean-operations)\n28. [Grouping and Filtering Data with `GROUP BY` and `HAVING`](#28-grouping-and-filtering-data-with-group-by-and-having)\n29. [Foreign Key Constraints and `ON DELETE` Actions](#29-foreign-key-constraints-and-on-delete-actions)\n30. [Joins in PostgreSQL](#30-joins-in-postgresql)\n31. [Additional Join Examples](#31-additional-join-examples)\n32. [Subqueries and Advanced Filtering](#32-subqueries-and-advanced-filtering)\n33. [Views in PostgreSQL](#33-views-in-postgresql)\n34. [PostgreSQL Functions](#34-postgresql-functions)\n35. [PostgreSQL Procedures](#35-postgresql-procedures)\n36. [Triggers in PostgreSQL](#36-triggers-in-postgresql)\n37. [Indexing](#37-indexing)\n\n### **1. Connecting to PostgreSQL**\n\n- **Basic connection:**\n  ```bash\n  psql\n  ```\n- **Connect with a specific user (e.g., the user is postgres here):**\n  ```bash\n  psql -U postgres\n  ```\n- **Connect to a specific database:**\n  ```bash\n  psql -U postgres -d test_db; #uses the test_db with the superuser Postgres\n  psql -U user1 -d postgres;\n  ```\n- **View connection info (gives the user details and port name):**\n  ```sql\n  \\conninfo\n  ```\n- **To see the version of  postgreSQL:**\n  ```sql\n  select version();\n  ```\n\n---\n\n### **2. Creating Database**\n\n- **Create a database:**\n  ```sql\n  CREATE DATABASE test_db;\n  --or,\n  create database test_db1; --not case sensitive\n  ```\n\n---\n\n### **3. Switching Databases and Exiting**\n\n- **Connect to another DB while in `psql`:**\n\n  ```sql\n  \\c test_db\n  ```\n\n- **Quit `psql`:**\n  ```sql\n  \\q\n  ```\n\n---\n\n### **4. Listing Information**\n\n- **List all databases:**\n  ```sql\n  \\l\n  ```\n- **List all users/roles:**\n  ```sql\n  \\du\n  ```\n- **List all schemas (inside a DB):**\n  ```sql\n  \\dn\n  ```\n- **List all commands of PostgrSQL:**\n  ```sql\n  \\?\n  ```\n\n---\n\n### **5. Managing Users / Roles**\n\n- **Create a user:**\n  ```sql\n  CREATE USER user2;\n  CREATE USER user1 WITH LOGIN ENCRYPTED PASSWORD '12345';\n  ```\n- **Create a role:**\n  ```sql\n  CREATE ROLE role1 WITH LOGIN ENCRYPTED PASSWORD '12345';\n  ```\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **6. Login as New User**\n\n- **Access database with a user:**\n  ```bash\n  psql -U user1 -d postgres;\n  ```\n\n\u003e Note: User must have permission on the database.\n\n---\n\n### **7. Table Operations**\n\n- **Create a table example:**\n  ```sql\n  CREATE TABLE test_table (\n    name VARCHAR(50) --here, name is the column name, varchar is a datatype and test_table is the name of the table\n  );\n  ```\n- **Insert data:**\n  ```sql\n  INSERT INTO test_table (name)\n  VALUES ('ayesha');\n  ```\n- **Select data (to view/read everything in a table):**\n  ```sql\n  SELECT * FROM test_table;\n  ```\n\n---\n\n### **8. Granting and Revoking Permissions**\n\n- **Switch user and connect to a database:**\n  ```bash\n  psql -U user4 -d postgres;\n  ```\n  _(switching from one user to another)_\n- **Grant all privileges on a table to a user:**\n  ```sql\n  GRANT ALL PRIVILEGES ON TABLE test_table TO user4;\n  ```\n  _(postgres is a superuser, but other users are not; to allow a user to access a table, the superuser must grant permissions.)_\n- **Grant select (read-only) permission on a table:**\n  ```sql\n  GRANT SELECT ON TABLE test_table TO user3;\n  ```\n  _(gives permission to view the table but not insert or delete)_\n- **Revoke select permission on a table:**\n  ```sql\n  REVOKE SELECT ON TABLE test_table FROM user3\n  ```\n  _(revokes viewing permission)_\n- **Grant all privileges on all tables in schema `public` to a user:**\n  ```sql\n  GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO user3;\n  ```\n  _(gives permission on all tables)_\n- **Grant select on all tables in schema `public` to a role:**\n  ```sql\n  GRANT SELECT ON ALL TABLES IN SCHEMA public TO role1;\n  ```\n  _(to allow role to view/read all databases)_\n- **Grant a role to a user:**\n  ```sql\n  GRANT role1 TO user3;\n  ```\n  _(grants role access to user)_\n\n---\n\n### **9. Renaming and Deleting Databases**\n\n- **Rename a database:**\n  ```sql\n  ALTER DATABASE test_db RENAME TO another_db;\n  ```\n- **Delete (drop) a database:**\n\n  ```sql\n  DROP DATABASE another_db;\n  ```\n\n  ***\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n---\n\n### **10. Renaming and Deleting Tables**\n\n- **Rename a table:**\n  ```sql\n  ALTER TABLE person RENAME TO student;\n  ```\n- **Delete (drop) a table:**\n  ```sql\n  DROP TABLE your_table;\n  ```\n- **Delete a table if exists (to avoid the error):**\n  ```sql\n  DROP TABLE if exists your_table;\n  ```\n\n---\n\n### **11. Table with constraints**\n\n- **Table creation template with constraints:**\n  ```sql\n  CREATE TABLE table_name (\n      column1 datatype constraint,\n      column2 datatype constraint,\n      column3 datatype constraint,\n      ...\n  );\n  ```\n- **Creating Tables with Constraints example**\n\n  ```sql\n\n  CREATE TABLE person (\n      person_id SERIAL PRIMARY KEY,  -- SERIAL auto-increments, PRIMARY KEY enforces uniqueness and NOT NULL\n      first_name VARCHAR(50) NOT NULL, -- Limits text to 50 characters, NOT NULL ensures the value must be provided\n      last_name VARCHAR(50) NOT NULL,  -- Same as above, for the last name\n      is_active BOOLEAN DEFAULT true, -- BOOLEAN type, DEFAULT sets initial value to true if not provided\n      age INTEGER CHECK (age \u003e= 0),  -- INTEGER type, CHECK ensures age must be zero or greater\n      email VARCHAR(255) UNIQUE   -- UNIQUE ensures no duplicate emails\n  );\n\n  ```\n\n- **Foreign Key Constraint**\n  - Values in the foreign key column must exist in the referenced primary key column.\n  - Example Tables:\n\n| **Product** |                | **Order**    |             | **Customer**    |          |\n| ----------- | -------------- | ------------ | ----------- | --------------- | -------- |\n| **prod_id** | **prod_title** | **order_id** | **prod_id** | **customer_id** | **name** |\n| 1           | shoe           | 1            | 1           | 1               | Alice    |\n| 2           | t-shirt        | 2            | 2           | 2               | Bob      |\n\n```sql\nCREATE TABLE customers (\n    customer_id SERIAL PRIMARY KEY,\n    name VARCHAR(100) NOT NULL\n);\n\nCREATE TABLE products (\n    prod_id SERIAL PRIMARY KEY,\n    prod_title VARCHAR(100) NOT NULL\n);\n\nCREATE TABLE orders (\n    order_id SERIAL PRIMARY KEY,\n    customer_id INTEGER REFERENCES customers(customer_id),\n    prod_id INTEGER REFERENCES products(prod_id)      -- foreign key to products\n);\n--customer_id in orders table is a foreign key that references customer_id in the customers table.\n\n--This means you cannot insert a customer_id in orders unless it exists in the customers table.\n```\n\n- **Multiple Column Primary Key Example**\n\n  ```sql\n  CREATE TABLE person2 (\n      id SERIAL,\n      user_name VARCHAR(20),\n      age INTEGER CHECK (age \u003e= 18),\n      PRIMARY KEY (id, user_name),\n      UNIQUE (user_name, age)\n  );\n\n  ```\n\n- **Single-Row Insert template**\n\n  ```sql\n  INSERT INTO your_table (column1, column2, column3)\n  VALUES (value1, value2, value3);\n\n  ```\n\n- **Single-Row Insert example**\n  ```sql\n  INSERT INTO employees (first_name, last_name, hire_date)\n  VALUES ('John', 'Doe', '2022-01-22');\n  ```\n- **Multi-Row Insert template**\n\n  ```sql\n  INSERT INTO your_table (column1, column2, column3)\n  VALUES\n      (value1_1, value2_1, value3_1),\n      (value1_2, value2_2, value3_2),\n      ...;\n\n  ```\n\n- **Multi-Row Insert Example**\n\n  ```sql\n  INSERT INTO employees (first_name, last_name, hire_date)\n  VALUES\n      ('Jane', 'Smith', '2022-02-20'),\n      ('Bob', 'Johnson', '2022-03-25');\n\n  ```\n\n- **If we know the columns (not recommended)**\n  ```sql\n  -- Assuming table person has columns (id, name, age)\n  INSERT INTO persons VALUES (1, 'John Doe', 23);\n  ```\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **12. Clearing Terminal**\n\n- **Clear terminal from `psql`:**\n\n  ```sql\n  \\! clear   -- Linux/macOS\n  \\! cls     -- Windows\n\n  ```\n\n---\n\n### **13. PostgreSQL Data Types**\n\n1. **Integer Types**\n\n| Type       | Range                                                   | Storage | Notes                                              |\n| ---------- | ------------------------------------------------------- | ------- | -------------------------------------------------- |\n| `INT`      | -2,147,483,648 to 2,147,483,647                         | 4 bytes | Commonly used standard integer                     |\n| `BIGINT`   | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | 8 bytes | For very large integers                            |\n| `SMALLINT` | -32,768 to 32,767                                       | 2 bytes | For small integer range                            |\n| `SERIAL`   | Like `INT`                                              | 4 bytes | Auto-incrementing integer, useful for primary keys |\n\n---\n\n2. **Floating-Point Types**\n\n| Type      | Storage  | Precision          | Notes                                       |\n| --------- | -------- | ------------------ | ------------------------------------------- |\n| `FLOAT4`  | 4 bytes  | ~6 decimal digits  | Single precision                            |\n| `FLOAT8`  | 8 bytes  | ~15 decimal digits | Double precision                            |\n| `NUMERIC` | Variable | User-defined       | Exact precision, for financial calculations |\n\n---\n\n3. **Character Types**\n\n| Type         | Storage              | Notes                                                                                |\n| ------------ | -------------------- | ------------------------------------------------------------------------------------ |\n| `CHAR(n)`    | Fixed length, padded | Fixed-length character string                                                        |\n| `VARCHAR(n)` | Variable length      | Variable-length character string up to `n` (recommended over `CHAR(n)` saves space). |\n| `TEXT`       | Variable length      | Unlimited length text, similar to `VARCHAR` but no length limit                      |\n\n---\n\n4. **UUID**\n\n- **Definition:** Universally Unique Identifier type\n- **Storage:** 128-bit (16 bytes), represented as 32 hex digits with hyphens\n- **Example:** `3c0ab34f-51f4-4d7b-84ee-b197af61dcb3`\n\n---\n\n5. **Date and Time Types**\n\n| Type          | Storage  | Notes                         |\n| ------------- | -------- | ----------------------------- |\n| `DATE`        | 4 bytes  | Stores calendar date          |\n| `TIME`        | 8 bytes  | Stores time of day (no date)  |\n| `TIMESTAMP`   | 8 bytes  | Stores both date and time     |\n| `TIMESTAMPTZ` | 8 bytes  | Timestamp with time zone      |\n| `INTERVAL`    | Variable | Represents time span/duration |\n\n---\n\n6. **Boolean**\n\n| Type      | Storage | Notes                       |\n| --------- | ------- | --------------------------- |\n| `BOOLEAN` | 1 byte  | Stores TRUE or FALSE values |\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **14. Modifying Columns in PostgreSQL**\n\n- **Select Data from Table**\n\n```sql\nSELECT * FROM person3;\n```\n\n- **Add a Column**\n\n```sql\nALTER TABLE person3\nADD COLUMN email VARCHAR(25) DEFAULT 'default@email.com' NOT NULL;\n```\n\n_Adds `email` column with a default value and `NOT NULL` constraint_\n\n- **Insert Data into Table**\n\n```sql\nINSERT INTO person3 VALUES (5, 'test2', 45, 'test@gmail.com');\n```\n\n_Inserts a new row into `person3`._\n\n- **Delete a Column**\n\n```sql\nALTER TABLE person3 DROP COLUMN email;\n```\n\n_Removes the `email` column from `person3`._\n\n- **Rename a Column**\n\n```sql\nALTER TABLE person3 RENAME COLUMN age TO user_age;\n```\n\n_Renames `age` column to `user_age`._\n\n- **Change Data Type of a Column**\n\n```sql\nALTER TABLE person3 ALTER COLUMN user_name TYPE VARCHAR(50);\n```\n\n_Alters the `user_name` column to have a maximum length of 50 characters._\n\n- **Add Constraint to Existing Column**\n\n```sql\nALTER TABLE person3 ALTER COLUMN user_age SET NOT NULL;\n```\n\n_Adds `NOT NULL` constraint to `user_age` column._\n\n\u003e Note: Constraints like `DEFAULT`, `UNIQUE`, `PRIMARY KEY`, and `FOREIGN KEY` cannot be added with like this.\n\n- **Delete a Constraint**\n\n```sql\nALTER TABLE person3 ALTER COLUMN user_age DROP NOT NULL;\n```\n\n_Removes the `NOT NULL` constraint from `user_age`._\n\n- **Add a New Column**\n\n```sql\nALTER TABLE person3 ADD COLUMN user_address VARCHAR(255);\n```\n\n_Adds `user_address` column with a maximum length of 255 characters._\n\n- **Insert Data into New Column**\n\n```sql\nINSERT INTO person3 VALUES (11, 'test3', 20, 'sylhet');\n```\n\n_Inserts new data into the table._\n\n- **Add Unique Constraint**\n\n```sql\nALTER TABLE person3\nADD CONSTRAINT unique_person3_user_address UNIQUE (user_address);\n```\n\n_Adds a `UNIQUE` constraint to the `user_address` column._\n\n- **Add Foreign Key Constraint**\n\n```sql\n----Create a foreign key constraint on department_id in the students table referencing departments(id).\n\nALTER table students\nadd constraint fk_department_id\nFOREIGN key (department_id)\nREFERENCES departments(id)\n```\n\n\u003e _`fk_students_department` is the name of the constraint (you can choose any name). This enforces that any department_id in students table must exist in departments.id, or be NULL._\n\n- **Delete a Unique Constraint**\n\n```sql\nALTER TABLE person3 ALTER COLUMN user_name DROP UNIQUE; --will give syntax error\n```\n\n- **Error**: You can't directly drop a `UNIQUE` constraint this way; it needs to be done via `DROP CONSTRAINT`.\n\n```sql\nALTER TABLE person3 DROP CONSTRAINT unique_person3_user_address;\n```\n\n_Removes the `unique_person3_user_address` constraint._\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### ** PostgreSQL Operations - Queries and Commands - Basic Table Operations**\n\n---\n\n### **15. Creating a Table**\n\n- **Creating a Table named students**\n\n```sql\nCREATE TABLE students (\n    student_id SERIAL PRIMARY KEY,\n    firstName VARCHAR(50) NOT NULL,\n    lastName VARCHAR(50) NOT NULL,\n    age INT,\n    grade CHAR(2),\n    course VARCHAR(50),\n    email VARCHAR(100),\n    dob DATE,\n    blood_group VARCHAR(5),\n    country VARCHAR(50)\n);\n```\n\n---\n\n### **16. Selecting Data**\n\n- **Select All Rows**\n\n```sql\nSELECT * FROM students;\n```\n\n- **Select Specific Column**\n\n```sql\nSELECT email FROM students;\n```\n\n- **Select or View Multiple Columns**\n\n```sql\nSELECT email, age FROM students;\n```\n\n- **Using Aliases**\n\n```sql\nSELECT email AS studentEmail FROM students;\nSELECT email AS \"student email\" FROM students;  -- Use double quotes for column names\n```\n\n- **Order By**\n\n```sql\nSELECT * FROM students ORDER BY firstName ASC;  -- Ascending (A-Z)\nSELECT * FROM students ORDER BY firstName DESC;  -- Descending (Z-A)\nSELECT country FROM students ORDER BY country ASC;  -- List countries A-Z\nSELECT * FROM students ORDER BY student_id;  -- sorted by ID\n```\n\n- **Distinct Values**\n\n```sql\nSELECT DISTINCT country FROM students;  -- Unique countries\n```\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **17. Data Filtering (`WHERE` Clause)**\n\n- **Filtering by Country**\n\n```sql\nSELECT * FROM students WHERE country = 'USA'; --viewing students only from the USA (conditional filtering)\n\n```\n\n- **Multiple Conditions (AND / OR)**\n\n```sql\n--select students with A grade in chemistry\nSELECT * FROM students WHERE grade = 'A' AND course = 'Chemistry';\n\n--select students from the USA or Canada\nSELECT * FROM students WHERE country = 'USA' OR country = 'Canada';\n\n--select students from the USA or Canada and the age is 20\nSELECT * FROM students WHERE (country = 'USA' OR country = 'Canada') AND age = 20;\n```\n\n- **Filtering by Range**\n\n```sql\nSELECT * FROM students WHERE age \u003e 20;  -- Age greater than 20\nSELECT * FROM students WHERE age BETWEEN 19 AND 22;  -- Between 19 and 22\n\n--select students older than 20 years old with course history;\nSELECT * FROM students WHERE age \u003e 20 AND course = 'History';\n```\n\n- **Not Equal**\n\n```sql\nSELECT * FROM students WHERE age \u003c\u003e 20;  -- Not 20 years old\n\n--similar action but different syntax:\nSELECT * FROM students WHERE age != 20;\nSELECT * FROM students WHERE NOT age = 20;\n```\n\n- **String Matching (LIKE / ILIKE)**\n\n```sql\nSELECT * FROM students WHERE firstName LIKE '%am';  -- Ends with 'am'\nSELECT * FROM students WHERE firstName LIKE 'A%';  -- Starts with 'A'\nSELECT * FROM students WHERE firstName ILIKE 'a%';  -- Case-insensitive search\nSELECT * FROM students WHERE firstName LIKE '__a';  -- Third letter is 'a'\nSELECT * FROM students WHERE firstName ILIKE '%a%'; --To match any student name that contains the letter \"a\" or 'A' anywhere\n```\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **18. Scalar Functions**\n\n\u003e **Scalar functions** are functions that operate on single values (scalar values) and return a single value as the result.\n\n- **UPPER()**\n\n  Converts all characters in a string to uppercase.\n\n  ```sql\n  SELECT upper(firstName) FROM students;\n\n  --make every letter of firstName uppercase and view the whole table\n  SELECT upper(firstName) AS firstNameInUppercase, * FROM students; --alias\n  ```\n\n- **LOWER()**\n\n  Converts all characters in a string to lowercase.\n\n  ```sql\n  SELECT lower(firstName) FROM students;\n\n  ```\n\n- **CONCAT()**\n\n  Concatenates two or more strings together.\n\n  ```sql\n  SELECT concat(firstName, ' ', lastName) FROM students;\n\n  ```\n\n- **LENGTH()**\n\n  Returns the number of characters in a string.\n\n  ```sql\n  SELECT length(firstName) FROM students;\n\n  ```\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **19. Aggregate Functions**\n\n\u003e **Aggregate functions** in PostgreSQL are used to perform calculations on a set of rows and return a single result.\n\n- **Average Age**\n\n  AVG() calculates the average of a set of values.\n\n```sql\nSELECT avg(age) FROM students;\n\n```\n\n- **Max Age**\n\n  MAX() returns the max value in a set.\n\n```sql\nSELECT max(age) FROM students;\n\n```\n\n- MIN() returns the minimum value in a set.\n- SUM() calculates the sum of values in a set.\n- **Count Rows**\n\n```sql\nSELECT count(*) FROM students;\n\n```\n\n- **Find Longest Name**\n\n```sql\nSELECT max(length(firstName)) FROM students;\n\n```\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **20. `NULL` Filtering**\n\n```sql\nSELECT * FROM students WHERE email IS NULL;  -- Rows with no email\nSELECT * FROM students WHERE email = 'rachel.garcia@example.com';  -- Specific email\n\n```\n\n---\n\n### **21. Handling `NULL` with COALESCE**\n\n- **Default Placeholder for NULL (Using COALESCE for Default Values)**\n\n```sql\nSELECT COALESCE(email, 'Email Not Provided'), age, blood_group FROM students;\n\n```\n\n---\n\n### **22. `IN` Operator**\n\nThe `IN` operator is used to check if a value matches any value in a list of values. Can be used to shorten multiple OR operators.\n\n- **e.g. View students only from the USA, UK, and Canada:**\n\n  ```sql\n  --with OR operator\n  SELECT *\n  FROM students\n  WHERE\n      country = 'USA'\n      OR country = 'Canada'\n      OR country = 'UK';\n\n  --with IN operator (shorter)\n  SELECT * FROM students WHERE country IN ('USA', 'UK', 'Canada');\n\n  ```\n\n- **View students not from the USA, UK, and Canada:**\n\n  ```sql\n  SELECT * FROM students WHERE country NOT IN ('USA', 'UK', 'Canada');\n\n  ```\n\n  ***\n\n  [🔼 Back to Table of Contents](#table-of-contents)\n\n### **23. `BETWEEN` Operator**\n\nThe `BETWEEN` operator is used to filter the results within a range (inclusive).\n\n- **View students with ages between 19 and 22:**\n\n  ```sql\n  SELECT * FROM students WHERE age BETWEEN 19 AND 22;\n\n  ```\n\n- **View students with `dob` between '2001-01-01' and '2002-12-12':**\n\n  ```sql\n  SELECT * FROM students WHERE dob BETWEEN '2001-01-01' AND '2002-12-12';\n\n  ```\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **24. `LIKE` Operator**\n\nThe `LIKE` operator is used to search for a specified pattern in a column.\n\n- **Find names that contain 'am' at the last:**\n\n  ```sql\n  SELECT * FROM students WHERE firstName LIKE '%am';\n\n  ```\n\n  - `%` is a wildcard that matches zero or more characters.\n\n- **Names starting with 'A':**\n\n  ```sql\n  SELECT * FROM students WHERE firstName LIKE 'A%';\n\n  ```\n\n  - `%` matches any number of characters after 'A'.\n\n- **Case-sensitive matching with `LIKE`:**\n\n  ```sql\n  SELECT * FROM students WHERE firstname LIKE 'a%'; --will not give the names start with 'A'\n\n  ```\n\n- **Case-insensitive matching with `ILIKE`:**\n\n  ```sql\n  SELECT * FROM students WHERE firstname ILIKE 'a%'; --gives names starting with 'A'.\n\n  ```\n\n- **Third letter is 'a' (underscore `_` matches a single character):**\n\n  ```sql\n  SELECT * FROM students WHERE firstname LIKE '__a'; --e.g. Eva, Mia\n\n  ```\n\n- **Names with 'o' as the third letter and two characters in between:**\n\n  ```sql\n  SELECT * FROM students WHERE lastname LIKE '__o__'; --e.g. Brown, Moore\n\n  ```\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **25. Updating and Deleting Data**\n\n- **Update Data**\n\n```sql\nUPDATE students\nSET email = 'default2@test.com', age = 30\nWHERE student_id = 5;\n\n--another example\nUPDATE students SET email = NULL WHERE student_id = 4;\n\n```\n\n- **Delete Data**\n\n```sql\n\nDELETE FROM students WHERE grade = 'B';  -- Delete all B grade students\nDELETE FROM students WHERE grade = 'C+' AND country = 'Ireland';  -- Specific condition\n\n```\n\n- **Delete All Rows**\n\n```sql\nDELETE FROM students;  -- Deletes all rows in the table\n\n```\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **26. Pagination (`LIMIT` and `OFFSET`)**\n\n- **Limit Results**\n\n```sql\nSELECT * FROM students LIMIT 5;  -- Shows first 5 rows\nSELECT * FROM students LIMIT 5 OFFSET 2;  -- Skips the first 2, shows next 5 rows\n\n```\n\n- **Pagination Example**\n\n```sql\nSELECT * FROM students LIMIT 5 OFFSET 5 * 0;  -- Rows 1-6\nSELECT * FROM students LIMIT 5 OFFSET 5 * 1;  -- Rows 7-11\nSELECT * FROM students LIMIT 5 OFFSET 5 * 2;  -- Rows 12-17\n\n```\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **27. Date, Time, and Boolean Operations**\n\n- **Show current timezone:**\n\n```sql\nSHOW timezone;\n```\n\n- **Current timestamp (includes date, time, and timezone):**\n\n```sql\nSELECT now();\n```\n\n- **Create a table with timestamp fields:**\n\n```sql\nCREATE TABLE timeZ (\n    ts TIMESTAMP WITHOUT TIME ZONE,\n    tsz TIMESTAMP WITH TIME ZONE\n);\n```\n\n- **Insert sample data:**\n\n```sql\nINSERT INTO timeZ\nVALUES (\n    '2024-12-05 10:45:07',\n    '2024-12-05 10:45:07'\n);\n```\n\n- **View table contents:**\n\n```sql\nSELECT * FROM timeZ; --2024-12-05 10:45:07\t  2024-12-05 10:45:07-05\n```\n\n- **Show today’s date:**\n\n```sql\nSELECT CURRENT_DATE;\nSELECT now()::date;  -- Casts timestamp to date\n```\n\n- **Show current time:**\n\n```sql\nSELECT now()::time;  -- Casts timestamp to time\n```\n\n- **Format timestamp as string:**\n\n```sql\nSELECT to_char(now(), 'mm-dd-yyyy');\nSELECT to_char(now(), 'Mon');     -- e.g., May\nSELECT to_char(now(), 'Month');   -- e.g., May\nSELECT to_char(now(), 'MONTH');   -- e.g., MAY\nSELECT to_char(now(), 'DDD');     -- Day of the year\n```\n\n- **Date arithmetic (subtracting intervals):**\n\n```sql\nSELECT CURRENT_DATE - INTERVAL '1 year'; --the day before one year from today\nSELECT CURRENT_DATE - INTERVAL '1 year 2 month';-- the day before one year and 2 months from today\n```\n\n- **Calculate age:**\n\n```sql\nSELECT age(CURRENT_DATE, '1995-11-1');  -- Result in years, months, days, e,g., \"years\":29,\"months\":6,\"days\":19\n\n--calculating age of each student\nSELECT *, age(CURRENT_DATE, dob) FROM students;\n```\n\n- **Extract parts from a date:**\n\n```sql\nSELECT extract(YEAR FROM '2023-08-12'::date); --2023\nSELECT extract(MONTH FROM '2023-08-12'::date); ----8\nSELECT extract(DAY FROM '2023-08-12'::date); ----12\n```\n\n- **Boolean casting examples:**\n\n```sql\nSELECT 1::Boolean;        -- true\nSELECT 'n'::Boolean;      -- false\nSELECT 'y'::Boolean;      -- true\nSELECT 'f'::Boolean;      -- false\nSELECT 't'::Boolean;      -- true\nSELECT 'no'::Boolean;     -- false\nSELECT 'yes'::Boolean;    -- true\n```\n\n---\n\n### **28. Grouping and Filtering Data with `GROUP BY` and `HAVING`**\n\n- **Group by country:**\n\n```sql\nSELECT country FROM students GROUP BY country;\n-- Lists distinct countries\n```\n\n- **Count students in each country:**\n\n```sql\nSELECT country, count(*) FROM students GROUP BY country;\n```\n\n- **Average age per country:**\n\n```sql\nSELECT country, avg(age) FROM students GROUP BY country;\n```\n\n- **Filter groups using `HAVING`:**\n\n```sql\nSELECT country, avg(age)\nFROM students\nGROUP BY country\nHAVING avg(age) \u003e 20;\n-- Filters country groups where average age \u003e 20\n```\n\n\u003e Note: `WHERE` filters individual rows; `HAVING` filters grouped results.\n\n- **Count students born in each year:**\n\n```sql\nSELECT extract(YEAR FROM dob) AS birth_year, count(*)\nFROM students\nGROUP BY birth_year;\n-- Groups students by birth year and counts the number of students in each year\n```\n\n---\n\n### **29. Foreign Key Constraints and `ON DELETE` Actions**\n\n#### 🔸 Table Creation:\n\n- **Using `\"user\"` as a table name (quoted because it's a reserved keyword):**\n\n```sql\nCREATE TABLE \"user\" (\n    id SERIAL PRIMARY KEY,\n    userName VARCHAR(25) NOT NULL\n);\n```\n\n---\n\n#### 🔸 `ON DELETE` Actions in Foreign Keys\n\n- **`ON DELETE CASCADE`**- Automatically deletes related posts when a user is deleted.\n\n```sql\nCREATE TABLE post (\n    id SERIAL PRIMARY KEY,\n    title TEXT NOT NULL,\n    user_id INTEGER REFERENCES \"user\"(id) ON DELETE CASCADE\n    --user_id is the foreign key of the 'post' table\n);\n```\n\n- **`ON DELETE SET NULL`** - Sets `user_id` to `NULL` in posts when the related user is deleted.\n\n```sql\nCREATE TABLE post (\n    id SERIAL PRIMARY KEY,\n    title TEXT NOT NULL,\n    user_id INTEGER REFERENCES \"user\"(id) ON DELETE SET NULL\n);\n```\n\n- **`ON DELETE SET DEFAULT`** - Sets `user_id` to a default value (e.g., 2) when the user is deleted.\n\n```sql\nCREATE TABLE post (\n    id SERIAL PRIMARY KEY,\n    title TEXT NOT NULL,\n    user_id INTEGER DEFAULT 2 REFERENCES \"user\"(id) ON DELETE SET DEFAULT\n);\n```\n\n---\n\n#### 🔸 Sample Data Insertion\n\n- **Insert users:**\n\n```sql\nINSERT INTO \"user\" (userName)\nVALUES\n    ('ayesha'),\n    ('fatima'),\n    ('khadiza'),\n    ('maryam');\n```\n\n- **View users:**\n\n```sql\nSELECT * FROM \"user\";\n```\n\n- **Insert posts:**\n\n```sql\nINSERT INTO post (title, user_id)\nVALUES\n    ('My first post!', 1),\n    ('Just another update!', 2),\n    ('Learning SQL is fun!', 3),\n    ('Post number four!', 4),\n    ('Quick post for practice.', 2);\n```\n\n- **Insert post with NULL user_id (only if `user_id` allows NULLs):**\n\n```sql\nINSERT INTO post (title, user_id) VALUES ('test', NULL);\n```\n\n- **View posts:**\n\n```sql\nSELECT * FROM post;\n```\n\n- **Make column non-nullable (if needed):**\n\n```sql\nALTER TABLE post ALTER COLUMN user_id SET NOT NULL;\n```\n\n---\n\n#### 🔸 Clean-Up (Optional for Reset)\n\n```sql\nDROP TABLE post;\nDROP TABLE \"user\";\n```\n\n---\n\n#### 🔸 Deletion Constraints\n\n- **Attempt to delete a user:**\n\n```sql\nDELETE FROM \"user\" WHERE id = 4;\n```\n\n\u003e 📝 If `ON DELETE` action is not set (default behavior is `RESTRICT` or `NO ACTION`), deletion will fail if related records exist in the referencing table.\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **30. Joins in PostgreSQL**\n\n#### 🔸 Tables Setup\n\n```sql\nCREATE TABLE \"user\" (\n    id SERIAL PRIMARY KEY,\n    userName VARCHAR(25) NOT NULL\n);\n\nCREATE TABLE post (\n    id SERIAL PRIMARY KEY,\n    title TEXT NOT NULL,\n    user_id INTEGER REFERENCES \"user\" (id)\n);\n```\n\n#### 🔸 Insert Sample Data\n\n```sql\nINSERT INTO \"user\" (userName)\nVALUES ('ayesha'), ('fatima'), ('khadija'), ('maryam');\n\nINSERT INTO post (title, user_id)\nVALUES\n    ('My first post!', 2),\n    ('Just another update!', 1),\n    ('Learning SQL is fun!', 1),\n    ('Post number four!', 4),\n    ('Quick post for practice.', 2),\n    ('this is test post title', NULL);\n```\n\n---\n\n#### 🔸 `INNER JOIN`- Join only matching rows from both tables, filters out the unrelated posts and users, only show the data which meet condition.\n\n```sql\nSELECT title, userName\nFROM post\nJOIN \"user\" ON post.user_id = \"user\".id;\n\n-- View all columns as a single table\nSELECT * FROM post JOIN \"user\" ON post.user_id = \"user\".id;\n\n-- Column disambiguation(providing context when column names are same, e.g., id)\nSELECT \"user\".id, post.id FROM post JOIN \"user\" ON post.user_id = \"user\".id;\n\n-- Using aliases\nSELECT p.id FROM post p JOIN \"user\" u ON p.user_id = u.id;\n\nSELECT p.id FROM post AS p JOIN \"user\" AS u ON p.user_id = u.id; --using 'as'\n```\n\n---\n\n- `USING` keyword-\n\n```sql\nSELECT *\nFROM employees\n    JOIN departments ON departments.department_id = employees.department_id;\n\n--\"Using\" keyword makes it concise\n\nSELECT * FROM employees JOIN departments USING (department_id);\n--when same joining /common column exists like e.g.department_id\n```\n\n#### 🔸 `LEFT JOIN` - Returns all rows from the `post` table and matched rows from `user`:\n\n```sql\nSELECT * FROM post AS p LEFT JOIN \"user\" u ON p.user_id = u.id;\n```\n\n---\n\n#### 🔸 `RIGHT JOIN` - Returns all rows from the `user` table and matched rows from `post`:\n\n```sql\nSELECT * FROM post AS p RIGHT JOIN \"user\" u ON p.user_id = u.id;\n```\n\n\u003e ⚠️ Table order matters in `LEFT` and `RIGHT` joins.\n\n---\n\n#### 🔸 `FULL OUTER JOIN`\n\n- Returns all rows from both tables, matched where possible:\n\n```sql\nSELECT * FROM post AS p FULL OUTER JOIN \"user\" u ON p.user_id = u.id;\n```\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **31. Additional Join Examples**\n\n##### Sample Tables\n\n```sql\nCREATE TABLE employees (\n    emp_id INT,\n    emp_name VARCHAR(50),\n    dept_id INT\n);\n\nCREATE TABLE department (\n    dept_id INT,\n    dept_name VARCHAR(50)\n);\n```\n\n##### Sample Data\n\n```sql\nINSERT INTO employees VALUES (1, 'John Doe', 101);\nINSERT INTO employees VALUES (2, 'Jane Smith', 102);\n\nINSERT INTO department VALUES (101, 'Human Resources');\nINSERT INTO department VALUES (102, 'Marketing');\n```\n\n##### `CROSS JOIN`- Combines every row of `employees` with every row of `department`:\n\n```sql\nSELECT * FROM employees CROSS JOIN department;\n```\n\n##### `NATURAL JOIN`- Joins tables using columns with the same names:\n\n```sql\nSELECT * FROM employees NATURAL JOIN department;\n-- Requires both tables to have a common column name (e.g., dept_id)\n```\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n---\n\n### **32. Subqueries and Advanced Filtering**\n\n\u003e A subquery is a nested query within another SQL statement.\n\u003e Here’s a well-organized **Section 31** in Markdown format for your PostgreSQL notes:\n\n#### 🔸 Table: `employees`\n\n```sql\nCREATE TABLE employees (\n    employee_id SERIAL PRIMARY KEY,\n    employee_name VARCHAR(50) NOT NULL,\n    department_name VARCHAR(50),\n    salary DECIMAL(10, 2),\n    hire_date DATE\n);\n```\n\n_(Sample data provided in earlier code block can be reused.)_\n\n---\n\n#### 🔸 Find Employees with Salary Greater Than Highest in HR\n\n```sql\n-- Step 1: Check the highest salary in HR\nSELECT MAX(salary) FROM employees WHERE department_name = 'HR';\n-- Result: 85000\n\n-- Step 2: Get all employees with salary above that\nSELECT *\nFROM employees --outer query\nWHERE salary \u003e (\n    SELECT MAX(salary)\n    FROM employees\n    WHERE department_name = 'HR' --the bracketed part is the subquery\n);\n```\n\n_This subquery returns a **single value**, and the outer query uses it for filtering._\n\n---\n\n#### 🔸 Subquery Returning a Single Column (One-to-All Comparison)\n\n```sql\n-- Total salary sum added as a column to each row (same value repeated)\nSELECT *, (SELECT SUM(salary) FROM employees) FROM employees;\n```\n\n---\n\n#### 🔸 Subquery Returning Multiple Rows\n\nExample:\n\n#### ❓ **Find all employees who work in the same departments as 'Jane Smith'**\n\n```sql\n-- Step 1: Find departments Jane Smith works in (returns multiple rows if she works in many)\nSELECT department_name\nFROM employees\nWHERE employee_name = 'Jane Smith';\n\n-- Step 2: Use that result in a subquery to get other employees in the same departments\nSELECT *\nFROM employees\nWHERE department_name IN (\n    SELECT department_name\n    FROM employees\n    WHERE employee_name = 'Jane Smith'\n);\n```\n\nAnother Example:\n\n#### ❓ **Find all departments that have employees with salary \u003e 90,000**\n\n```sql\nSELECT DISTINCT department_name\nFROM employees\nWHERE department_name IN (\n    SELECT department_name\n    FROM employees\n    WHERE salary \u003e 90000\n);\n```\n\n---\n\n#### 🔸 Subquery as a Virtual Table\n\n```sql\n-- Show sum of salaries per department using a subquery\nSELECT *\nFROM (\n    SELECT department_name, SUM(salary) AS total_salary\n    FROM employees\n    GROUP BY department_name\n) AS sum_dept_salary;\n```\n\n\u003e The subquery behaves like a derived/temporary table and can be referenced in the outer query.\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **33. Views in PostgreSQL**\n\n#### 🔸 What is a View?\n\n- A **view** is a **virtual table** based on the result of a SQL query.\n- It does **not store data** physically — it **dynamically generates** results when queried.\n- Think of it as a saved SQL query you can treat like a regular table.\n\n---\n\n#### 🔸 Example: Creating a View for Department Average Salaries\n\n```sql\n-- Base data\nSELECT * FROM employees;\n\n-- Create a view\nCREATE VIEW dept_avg_salary AS\nSELECT department_name, AVG(salary) AS avg_salary\nFROM employees\nGROUP BY department_name;\n```\n\n- **Query the view just like a table:**\n\n```sql\nSELECT * FROM dept_avg_salary;\n```\n\n---\n\n#### ✅ Benefits of Using Views\n\n- **Simplifies complex queries**\n  You can hide joins, calculations, or nested queries behind a simple interface.\n\n- **Improves security**\n  You can expose limited columns or rows via views while restricting access to full tables.\n\n- **Enhances data abstraction**\n  Changes in the underlying schema can be hidden from users by updating the view logic.\n\n---\n\n#### 🧠 Notes\n\n- **Modifying data through views** is limited:\n\n  - Simple views can sometimes be used in `INSERT`, `UPDATE`, and `DELETE` operations.\n  - Complex views (e.g., those with `JOIN`, `GROUP BY`, aggregates) are usually **read-only**.\n\n- To drop a view:\n\n```sql\nDROP VIEW dept_avg_salary;\n```\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **34. PostgreSQL Functions**\n\n#### 🔸 What is a Function?\n\nA **function** in PostgreSQL is a reusable block of SQL logic that:\n\n- Can **accept parameters**\n- Can **return a value**\n- Can be used within `SELECT`, `WHERE`, etc.\n\n---\n\n#### 🔸 1. Function Without Parameters\n\n```sql\nCREATE FUNCTION count_emp()\nRETURNS INT\nLANGUAGE SQL\nAS\n$$\n    SELECT COUNT(*) FROM employees;\n$$;\n\n-- Calling the function\nSELECT count_emp();\n```\n\n---\n\n#### 🔸 2. Function Returning Nothing (`void`)\n\n```sql\nCREATE FUNCTION del_emp()\nRETURNS void\nLANGUAGE SQL\nAS\n$$\n   DELETE FROM employees WHERE employee_id = 30;\n$$;\n\n-- Calling the function\nSELECT del_emp();\n```\n\n---\n\n#### 🔸 3. Function With Parameters\n\n```sql\nCREATE OR REPLACE FUNCTION del_emp_by_id(p_emp_id INT)\nRETURNS void\nLANGUAGE SQL\nAS\n$$\n   DELETE FROM employees WHERE employee_id = p_emp_id;\n$$;\n\n-- Call the function\nSELECT del_emp_by_id(29);\n```\n\n---\n\n#### 🧠 Notes on Functions\n\n- Can be written in **SQL** or **PL/pgSQL**\n- Can be **called in `SELECT` statements**\n- Useful for computations or encapsulating logic that returns a value\n- Cannot perform transactional control like `COMMIT` or `ROLLBACK`\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **35. PostgreSQL Procedures**\n\n#### 🔸 What is a Procedure?\n\nA **procedure** is similar to a function, but:\n\n- Is called using `CALL`\n- Does **not return a value directly**\n- Can contain **transactional control** (`BEGIN`, `COMMIT`, `ROLLBACK`)\n- Often used for performing actions or system tasks\n\n---\n\n#### 🔸 1. Procedure Without Parameters\n\n```sql\nCREATE PROCEDURE remove_emp()\nLANGUAGE plpgsql\nAS\n$$\nBEGIN\n    DELETE FROM employees WHERE employee_id = 28;\nEND;\n$$;\n\n-- Calling the procedure\nCALL remove_emp();\n```\n\n---\n\n#### 🔸 2. Procedure With Parameters and Internal Variable\n\n```sql\nCREATE PROCEDURE remove_emp_by_id(p_emp_id INT)\nLANGUAGE plpgsql\nAS\n$$\nDECLARE\n    test_var INT;\nBEGIN\n    SELECT employee_id INTO test_var FROM employees WHERE employee_id = p_emp_id;\n    DELETE FROM employees WHERE employee_id = test_var;\n    RAISE NOTICE 'Employee Removed Successfully'; --similar to console.log()\nEND;\n$$;\n\n-- Calling the procedure\nCALL remove_emp_by_id(11);\n```\n\n---\n\n#### 🧠 Notes on Procedures\n\n- Must be called using `CALL`, not `SELECT`\n- Cannot be used inside `SELECT` or `WHERE`\n- Designed for side-effect actions (insert, delete, etc.)\n- Supports `RAISE NOTICE`, flow control (`IF`, `LOOP`, etc.), and exception handling\n\n---\n\n### 🔁 **Function vs. Procedure — Key Differences**\n\n| Feature             | Function                        | Procedure                            |\n| ------------------- | ------------------------------- | ------------------------------------ |\n| Invocation          | `SELECT function_name()`        | `CALL procedure_name()`              |\n| Return Value        | Must return a value (or `void`) | Does not return a value directly     |\n| Transaction Control | ❌ Not allowed                  | ✅ Allowed (`BEGIN`, `COMMIT`, etc.) |\n| Usage Context       | Can be used inside queries      | Cannot be used inside queries        |\n| Language Support    | `SQL`, `PL/pgSQL`, others       | Typically `PL/pgSQL`                 |\n| Best Use Case       | Computation, returning data     | Performing tasks with side effects   |\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **36. Triggers in PostgreSQL**\n\n#### 🔸 What is a Trigger?\n\nA **trigger** is a special database object that **automatically executes** a defined function **in response to certain events** on a table or view.\n\n---\n\n#### 🔹 Trigger Event Types\n\n- **Table-Level Events:**  \n  `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`\n\n- **Database-Level Events (Advanced):**  \n  `STARTUP`, `SHUTDOWN`, `CONNECTION START/END`, etc. _(Handled differently, often with event triggers.)_\n\n---\n\n#### 🔹 Basic Syntax of a Trigger\n\n```sql\nCREATE TRIGGER trigger_name\n{ BEFORE | AFTER | INSTEAD OF } { INSERT | UPDATE | DELETE | TRUNCATE }\nON table_name\n[FOR EACH ROW | FOR EACH STATEMENT]\nEXECUTE FUNCTION function_name();\n```\n\n---\n\n#### 🔸 Example: Store Deleted Users in an Audit Table\n\n---\n\n**1. Base Table**\n\n```sql\nCREATE TABLE my_users (\n    user_name VARCHAR(50),\n    email VARCHAR(100)\n);\n\nINSERT INTO my_users VALUES\n    ('Mezba', 'mezba@mail.com'),\n    ('Mir', 'mir@mail.com');\n\nSELECT * FROM my_users;\n```\n\n---\n\n**2. Audit Table**\n\n```sql\nCREATE TABLE deleted_users_audit (\n    deleted_user_name VARCHAR(50),\n    deletedAt TIMESTAMP\n);\n\nSELECT * FROM deleted_users_audit;\n```\n\n---\n\n**3. Create the Trigger Function**\n\n```sql\nCREATE OR REPLACE FUNCTION save_deleted_user()\nRETURNS TRIGGER\nLANGUAGE plpgsql\nAS\n$$\nBEGIN\n    INSERT INTO deleted_users_audit\n    VALUES (OLD.user_name, NOW());  -- 'OLD' holds the deleted row data\n    RAISE NOTICE 'Deleted user audit log created';\n    RETURN OLD;  -- necessary for DELETE triggers\nEND;\n$$;\n```\n\n---\n\n**4. Create the Trigger**\n\n```sql\nCREATE OR REPLACE TRIGGER save_deleted_user_trigger\nBEFORE DELETE\nON my_users\nFOR EACH ROW\nEXECUTE FUNCTION save_deleted_user();\n```\n\n---\n\n**5. Delete a User (Trigger Fires Automatically)**\n\n```sql\nDELETE FROM my_users WHERE user_name = 'Mir';\n```\n\n\u003e ✅ After deletion, a new row will be inserted into `deleted_users_audit` with the username and timestamp.\n\n---\n\n#### Notes on Triggers\n\n- Use `OLD` for accessing **existing row values** during `DELETE` or `UPDATE`.\n- Use `NEW` for accessing **incoming row values** during `INSERT` or `UPDATE`.\n- Triggers can run:\n\n  - **Before or After** the event (`BEFORE DELETE`, `AFTER INSERT`, etc.)\n  - **For Each Row** or **Once Per Statement**\n\n- You must **create the function first** before creating the trigger.\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n\n### **37. Indexing**\n\n#### 🔸 What is an Index?\n\nA **database index** is a **data structure** used to **quickly locate and access data** in a table — similar to an index in a book. It enhances **read performance**, especially for large tables.\n\n\u003e Without indexing, PostgreSQL performs a **sequential scan** (i.e., checks every row).\n\n---\n\n#### 🔸 Example: Indexing Workflow\n\n```sql\n-- Step 1: Check baseline query performance\nEXPLAIN ANALYZE\nSELECT * FROM employees WHERE employee_name = 'William Jackson';\n\n-- Step 2: Create index on employee_name column\nCREATE INDEX idx_employees_employee_name\nON employees (employee_name);\n\n-- Step 3: Re-run the query to see improved performance\nEXPLAIN ANALYZE\nSELECT * FROM employees WHERE employee_name = 'William Jackson';\n```\n\n\u003e `EXPLAIN ANALYZE` helps you analyze query plans and compare before vs. after indexing.\n\n---\n\n#### 🔸 Viewing Data Directory Location\n\n```sql\nSHOW data_directory;\n```\n\n---\n\n### ✅ When to Use Indexing\n\n- On **frequently queried columns** in `WHERE`, `JOIN`, `ORDER BY`, or `GROUP BY`\n- On **large tables** where filtering or searching slows down\n- On **columns with high cardinality** (i.e., many unique values)\n- When supporting **foreign key relationships**\n\n---\n\n### ❌ When Not to Use Indexing\n\n- On **small tables** (sequential scan is often faster)\n- On **columns with low cardinality** (e.g., boolean fields)\n- If the column is **rarely used in queries**\n- When doing **frequent write operations** (`INSERT`, `UPDATE`, `DELETE`) — too many indexes can slow them down due to constant index maintenance\n\n---\n\n### ⚙️ Algorithms Behind Indexing\n\n| Index Type | Description                                                               | Use Case                            |\n| ---------- | ------------------------------------------------------------------------- | ----------------------------------- |\n| **B-tree** | Default; balanced tree for fast lookup (`=`, `\u003c`, `\u003e`, `BETWEEN`, `LIKE`) | Most general-purpose cases          |\n| **Hash**   | Hash table-based, only for exact match (`=`)                              | Fast equality lookups               |\n| **GIN**    | Generalized Inverted Index for arrays, JSONB, full-text search            | Full-text search, complex datatypes |\n| **GiST**   | Generalized Search Tree, supports ranges, geometric types                 | Ranges, proximity queries           |\n| **BRIN**   | Block Range Index — summarizes large block ranges                         | Very large tables, time-series data |\n\n---\n\n### Notes\n\n- PostgreSQL **automatically uses indexes** if the query planner finds them beneficial.\n\n- You can **force an index** with:\n\n  ```sql\n  SET enable_seqscan = off;\n  ```\n\n- You can **drop an index** with:\n\n  ```sql\n  DROP INDEX idx_employees_employee_name;\n  ```\n\n- PostgreSQL supports **composite indexes**:\n\n  ```sql\n  CREATE INDEX idx_multi ON employees (department_name, salary);\n  ```\n\n\u003e 🏁 Indexes **speed up read performance** but **may slow down writes** — use wisely.\n\n---\n\n[🔼 Back to Table of Contents](#table-of-contents)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falifa-ara-heya%2Fpostgresql-commands","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falifa-ara-heya%2Fpostgresql-commands","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falifa-ara-heya%2Fpostgresql-commands/lists"}