{"id":15187451,"url":"https://github.com/sravanigodavarthi/oltp-banking-database","last_synced_at":"2026-03-09T12:01:59.562Z","repository":{"id":247826784,"uuid":"821535979","full_name":"sravanigodavarthi/OLTP-Banking-Database","owner":"sravanigodavarthi","description":"An OLTP banking system is implemented, emphasizing data integrity and atomicity, and leveraging constraints, triggers, stored procedures, views, and indexing to enhance query performance.","archived":false,"fork":false,"pushed_at":"2024-07-19T18:19:26.000Z","size":480,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-06T17:50:16.036Z","etag":null,"topics":["atomicity","constraints","datamodeling","indexing","oltp","plpgsql","postgresql","python","rollback","stored-procedures","triggers"],"latest_commit_sha":null,"homepage":"","language":"Python","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/sravanigodavarthi.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}},"created_at":"2024-06-28T19:09:47.000Z","updated_at":"2024-07-19T18:19:29.000Z","dependencies_parsed_at":"2024-07-19T21:29:54.551Z","dependency_job_id":null,"html_url":"https://github.com/sravanigodavarthi/OLTP-Banking-Database","commit_stats":null,"previous_names":["sravanigodavarthi/oltp-banking-database"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sravanigodavarthi/OLTP-Banking-Database","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sravanigodavarthi%2FOLTP-Banking-Database","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sravanigodavarthi%2FOLTP-Banking-Database/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sravanigodavarthi%2FOLTP-Banking-Database/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sravanigodavarthi%2FOLTP-Banking-Database/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sravanigodavarthi","download_url":"https://codeload.github.com/sravanigodavarthi/OLTP-Banking-Database/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sravanigodavarthi%2FOLTP-Banking-Database/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30294685,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T11:12:22.024Z","status":"ssl_error","status_checked_at":"2026-03-09T11:10:54.577Z","response_time":61,"last_error":"SSL_read: 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":["atomicity","constraints","datamodeling","indexing","oltp","plpgsql","postgresql","python","rollback","stored-procedures","triggers"],"created_at":"2024-09-27T18:22:43.425Z","updated_at":"2026-03-09T12:01:59.526Z","avatar_url":"https://github.com/sravanigodavarthi.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OLTP-Banking-Database\n## Project Description\nIn this project an OLTP (Online Transaction Processing) database for a banking system is developed using `PostgreSQL`. The primary objective is to explore and demonstrate key database concepts, such as:\n* Implementing transaction management with `rollbacks`\n* Creating and utilizing `triggers` for automated actions\n* Developing `stored procedures` to encapsulate business logic\n* Enforcing `data integrity` with constraints\n* Enhancing query performance through `indexing`\n## Banking System Data Model\nBank legislation varies from country to country, and not all banks offer the same products and services. In this project, we consider a simple and generic data model for a banking system. This data model represents how data is stored, organized, and accessed in a database.\n\n\u003cbr\u003e\n\u003cdiv align = center\u003e\n\u003cimg src=\"bank_OLTP_ERD.png\" align=\"center\" width=\"1000\" /\u003e\n\u003c/div\u003e\n\n\n### Entities and Relationships\n**Department:** This entity stores information about different departments within the organization. It has a `one-to-many` relationship with the `Employee` entity, as each department can have multiple employees.\n\n**Employee:** This entity stores information about employees. It includes a foreign key `department_id` which references the `Department` entity, establishing a relationship that employees belong to `specific departments`.\n\n**Customer:** This entity stores information about customers. Each customer can have multiple accounts, establishing a `one-to-many` relationship with the `Account` entity.\n\n**Account:** This entity stores information about customer accounts. It includes a foreign key `customer_id` which references the `Customer` entity. Each account is associated with `one customer`.\n\n**Transaction:** This entity stores information about transactions. It includes foreign keys `account_id` and `employee_id`, establishing relationships with the `Account` and `Employee` entities. Each transaction is associated with a `specific account` and processed by a `specific employee`.\n\nThe [main.py](/main.py) script sets up a database according to the specified data model. It creates two schemas: `human_resource` and `finance`, and defines tables within these schemas: `department`, `employee`, `customer`, `account`, and `transaction`, with the necessary indexing and constraints. The script also inserts sample data into these tables.\n\n## Enhancing query performance through indexing\n\nIndexes are used to quickly locate and access data in a database table without having to search every row of the table each time it is accessed.\n\n`B-tree` indexing, used for `FK` columns as shown below, enhances the performance of join operations, referential integrity checks, and query execution involving foreign key relationships. This leads to more efficient and scalable database applications.\n\n    CREATE INDEX IF NOT EXISTS idx_transaction_account_id\n    ON finance.transaction USING btree (account_id);\n\n    CREATE INDEX IF NOT EXISTS idx_employee_department_id\n    ON human_resource.employee USING btree (department_id);\n\n    CREATE INDEX IF NOT EXISTS idx_account_customer_id\n    ON finance.account USING btree (customer_id);\n\nAdditionally, creating a `composite index` on `(first_name, last_name)` is beneficial for queries that involve both columns together, enhancing search performance for such queries.\n\n    CREATE INDEX IF NOT EXISTS idx_first_name_last_name\n    ON human_resource.employee USING btree (first_name, last_name);\n\n## Enforcing data integrity with constraints\n\nIn databases, constraints are rules applied to data columns to ensure data integrity, accuracy, and reliability. They restrict the type of data that can be inserted into a table to maintain consistency and correctness.\n\n**Primary Key Constraints** :\n* Primary keys ensure that each record in a table is unique.\n  * `department_pkey` on `human_resource.department(department_id)`\n  * `employee_pkey` on `human_resource.employee(employee_id)`\n  * `user_pkey` on `finance.customer(customer_id)`\n  * `account_pkey` on `finance.account(account_id)`\n  * `transaction_pkey` on `finance.transaction(transaction_id)`\n\n**Foreign Key Constraints**: \n* **Foreign keys** ensure referential integrity by requiring that a value in one table must exist in another table.\n  * `department_fkey` on `human_resource.employee(department_id`) references `human_resource.department(department_id)`\n  * `user_fkey` on `finance.account(customer_id)` references `finance.customer(customer_id)`\n  * `account_fkey` on `finance.transaction(account_id)` references `finance.account(account_id)`\n  * `employee_fkey` on `finance.transaction(employee_id)` references `human_resource.employee(employee_id)`\n\n**Check Constraints**: \n* **Check constraints** ensure that values in a column meet specific conditions.\n  * `chk_valid_customer_type` on `finance.customer(customer_type)` ensures that the value is either retail or corporate.\n  * `chk_positive_balance` on `finance.account(current_balance)` ensures that the balance is non-negative.\n  * `chk_non_negative_amount` on `finance.transaction(amount)` ensures that the transaction amount is positive.\n  * `chk_salary_positive` on `human_resource.employee(salary)` ensures that the salary is positive.\n\n## Implementing transaction management with rollbacks\n\nThe finance.transfer procedure encapsulates the logic for secure and reliable fund transfers between accounts (sender_id and receiver_id). It ensures `transactional integrity` by either completing all operations successfully or rolling back completely in case of failure. The procedure employs robust exception handling to manage unexpected issues and maintains `atomicity`, treating all database changes as a single unit of work, thus adhering to `ACID` properties.\n\n    CREATE OR REPLACE PROCEDURE finance.transfer(\n        IN sender_id integer,\n        IN receiver_id integer,\n        IN amount numeric,\n        IN employee_id integer\n        )\n    LANGUAGE 'plpgsql'\n    AS $$\n            DECLARE\n                rollback_message TEXT := 'Transaction rolled back: Insufficient funds';\n                commit_message TEXT := 'Transaction committed successfully';\n            BEGIN\n                IF (SELECT current_balance FROM finance.account WHERE account_id = sender_id) \u003c amount THEN\n                RAISE EXCEPTION '%', rollback_message;\n                ELSE\n                    UPDATE finance.account SET current_balance = current_balance - amount WHERE account_id = sender_id;\n                    UPDATE finance.account SET current_balance = current_balance + amount WHERE account_id = receiver_id;\n                    INSERT INTO finance.transaction (account_id, transaction_type, amount, employee_id) VALUES (sender_id, 'WITHDRAWAL', amount, employee_id);\n                    INSERT INTO finance.transaction (account_id, transaction_type, amount, employee_id) VALUES (receiver_id, 'DEPOSIT', amount, employee_id);\n                END IF;\n            EXCEPTION\n                WHEN OTHERS THEN\n                -- Rollback the transaction\n                RAISE EXCEPTION 'Error transferring funds: %', SQLERRM;\n                ROLLBACK;\n            END;\n    $$;\n        \n## Creating and utilizing triggers for automated actions\n\nTriggers are powerful tools in databases that help automate tasks, enforce data integrity, and implement complex business rules by executing predefined actions in response to specific events.\n\nIn this project, the trigger function `employee_salary_update_func()` is designed to insert a record into the `employee_salary_update` table whenever an employee's salary is updated, serving an auditing purpose.\n\n1. **Creating the Audit Table**\n\n* `employee_salary_update table` captures the details of any salary changes, including the old and new salaries and the date of the chan\n\n      CREATE TABLE IF NOT EXISTS human_resource.employee_salary_update\n      (\n          log_id integer NOT NULL GENERATED ALWAYS AS IDENTITY,\n          employee_id integer NOT NULL,\n          first_name VARCHAR(50),\n          last_name VARCHAR(50),\n          old_salary numeric(10,2) NOT NULL,\n          incremented_salary numeric(10,2) NOT NULL,\n          incremented_on date NOT NULL,\n          CONSTRAINT employee_salary_update_pkey PRIMARY KEY (log_id)\n      );\n\n2. **Creating the Trigger Function**\n\n* This function compares the old and new salary values. If they are different, it logs the change in the `employee_salary_update table`.\n\n      CREATE OR REPLACE FUNCTION human_resource.employee_salary_update_func()\n          RETURNS trigger\n          LANGUAGE plpgsql\n          AS $$\n              BEGIN\n                  IF NEW.salary \u003c\u003e OLD.salary THEN\n                      INSERT INTO human_resource.employee_salary_update (employee_id, first_name, last_name, old_salary, incremented_salary, incremented_on)\n                      VALUES (OLD.employee_id, OLD.first_name, OLD.last_name, OLD.salary, NEW.salary, now());\n                  END IF;\n                  RETURN NEW;\n              END;\n          $$;\n\n3. **Creating the Trigger**\n\n* This trigger ensures that the `employee_salary_update_func` function is called automatically whenever the salary column of the employee table is updated.\n\n      CREATE TRIGGER employee_salary_update_trigger\n          AFTER UPDATE OF salary ON human_resource.employee\n          FOR EACH ROW\n          EXECUTE FUNCTION human_resource.employee_salary_update_func();\n\n4. **Executing an Update to Fire the Trigger**\n\n* This update statement triggers the `employee_salary_update_func` function, which logs the salary change in the `employee_salary_update` table.\n\n      UPDATE human_resource.employee\n      SET salary = 90000\n      WHERE first_name = 'John' AND last_name = 'Doe';\n\n## Creating Views for Simplified Data Retrieval\nViews provide an organized way to query and retrieve detailed information from multiple related tables within the finance and human_resource schemas.\n* View to get detailed account information including customer details\n  \n      CREATE OR REPLACE VIEW finance.account_details AS\n      SELECT \n        account.account_id,\n        account.account_holder,\n        account.current_balance,\n        customer.customer_id,\n        customer.customer_type\n      FROM \n        finance.account\n      JOIN \n        finance.customer ON account.customer_id = customer.customer_id;\n\n* View to get detailed transaction information linked with account details\n  \n      CREATE OR REPLACE VIEW finance.transaction_details AS\n      SELECT \n        account.account_id,\n        account.customer_id,\n        transaction.transaction_id,\n        transaction.transaction_date,\n        transaction.amount,\n        transaction.transaction_type\n      FROM \n        finance.transaction\n      JOIN \n        finance.account ON account.account_id = transaction.account_id;\n\n* View to get detailed employee information along with their department details\n\n      CREATE OR REPLACE VIEW human_resource.employee_details AS\n      SELECT \n          e.employee_id,\n          e.first_name,\n          e.last_name,\n          e.hire_date,\n          e.salary,\n          d.department_name,\n          d.department_id\n      FROM \n          human_resource.employee e\n      JOIN \n          human_resource.department d ON e.department_id = d.department_id;\n\n**Note:**\nThe procedures, triggers, views, and indexing SQL queries are directly executed using the PostgreSQL GUI.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsravanigodavarthi%2Foltp-banking-database","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsravanigodavarthi%2Foltp-banking-database","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsravanigodavarthi%2Foltp-banking-database/lists"}