-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathpostgresql_reference.sql
More file actions
1326 lines (1077 loc) · 47.1 KB
/
postgresql_reference.sql
File metadata and controls
1326 lines (1077 loc) · 47.1 KB
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
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
-- --------------------------------------------------------------------------------
-- PostgreSQL Reference and Guide
-- ReferenceCollection.com
-- Licensed under CC BY-SA
-- --------------------------------------------------------------------------------
-- Table of Contents
--------------------
-- 1. Introduction
-- 2. Basic Syntax
-- 3. Data Types
-- 4. Database Operations
-- 5. Table Operations
-- 6. Constraints
-- 7. Data Manipulation
-- 8. Querying Data
-- 9. Joins
-- 10. Aggregate Functions
-- 11. Subqueries
-- 12. Indexes
-- 13. Stored Procedures and Functions
-- 14. Transactions
-- 15. Views
-- 16. Triggers
-- 17. User Management
-- 18. Backup and Restore
-- 19. Concurrency Control
-- 20. Replication
-- 21. Partitioning
-- 22. Extensions
-- 23. JSON and JSONB
-- 24. Full-Text Search
-- 25. Window Functions
-- 26. Common Table Expressions (CTEs)
-- 27. Inheritance
-- --------------------------------------------------------------------------------
-- 1. Introduction
-- --------------------------------------------------------------------------------
-- Overview
-----------
-- PostgreSQL is a powerful open-source relational database management
-- system (RDBMS). It uses and extends the SQL language combined with many
-- features that safely store and scale the most complicated data workloads.
-- History
----------
-- PostgreSQL, often simply Postgres, was originally developed at the University
-- of California, Berkeley in 1986. It has more than 30 years of active development
-- and has earned a strong reputation for reliability, robustness, and performance.
-- Architecture
---------------
-- PostgreSQL uses a client/server model. A PostgreSQL session consists of the
-- following processes:
-- 1. A server, which manages the database files, accepts connections from client
-- applications, and performs database actions on behalf of the clients.
-- 2. The user's client application that wants to perform database operations.
-- Components
-------------
-- Databases: A collection of schemas, which contains tables, functions, etc.
-- Schemas: A namespace that contains database objects like tables, views, etc.
-- Tables: Structures within a schema that hold data in rows and columns.
-- Rows: Individual records in a table.
-- Columns: Fields within a table that define the type of data stored.
-- SQL Commands
---------------
-- SQL commands in PostgreSQL are divided into several categories:
-- Data Definition Language (DDL): CREATE, ALTER, DROP, TRUNCATE
-- Data Manipulation Language (DML): SELECT, INSERT, UPDATE, DELETE
-- Data Control Language (DCL): GRANT, REVOKE
-- Transaction Control Language (TCL): BEGIN, COMMIT, ROLLBACK
-- --------------------------------------------------------------------------------
-- 2. Basic Syntax
-- --------------------------------------------------------------------------------
-- Comments
-----------
-- There are two types of comments: single-line and multi-line.
-- Single-line comment
/* Multi-line comment */
-- Semicolons
-------------
-- Each SQL statement should end with a semicolon.
SELECT 'Hello, PostgreSQL';
-- Case Sensitivity
-------------------
-- SQL Keywords are case-insensitive. Database, Table, and Column
-- Names are also case-insensitive unless they are double-quoted.
CREATE DATABASE ExampleDB;
CREATE DATABASE "exampleDB"; -- This will create a different database
-- Schema Usage
---------------
-- Schemas are used to organize objects. The default schema is 'public'.
CREATE SCHEMA my_schema;
CREATE TABLE my_schema.my_table (id serial PRIMARY KEY);
-- Set the search path to prioritize 'my_schema'.
SET search_path TO my_schema, public;
-- --------------------------------------------------------------------------------
-- 3. Data Types
-- --------------------------------------------------------------------------------
-- PostgreSQL supports a wide variety of data types.
-- Numeric Types
INTEGER -- Signed four-byte integer
BIGINT -- Signed eight-byte integer
NUMERIC(p,s) -- (precision,scale): Exact numeric of selectable precision
REAL -- Single precision floating-point number
DOUBLE PRECISION -- Double precision floating-point number
-- Character Types
CHAR(n) -- Fixed-length character string
VARCHAR(n) -- Variable-length character string with limit
TEXT -- Variable-length character string
-- Date/Time Types
DATE -- Calendar date (year, month, day)
TIME -- Time of day
TIMESTAMP -- Date and time
INTERVAL -- Time interval
-- Boolean Type
BOOLEAN -- True or false
-- Enumerated Type
CREATE TYPE mood AS ENUM ('sad', 'happy');
-- Array Type
INTEGER[] -- Array of integers
VARCHAR[] -- Array of strings
-- JSON Types
JSON -- Textual JSON data
JSONB -- Binary JSON data, decomposed
-- Other Types
UUID -- Universally Unique Identifiers
BYTEA -- Binary data ("byte array")
CIDR -- IPv4 or IPv6 network address
INET -- IPv4 or IPv6 host address
MACADDR -- MAC address
-- --------------------------------------------------------------------------------
-- 4. Database Operations
-- --------------------------------------------------------------------------------
-- Data is organized into databases, which contain schemas and tables.
-- Listing databases.
\l
-- Creating a database.
CREATE DATABASE my_database;
-- Dropping a database.
DROP DATABASE IF EXISTS my_database;
-- Connecting to a database.
\c my_database
-- --------------------------------------------------------------------------------
-- 5. Table Operations
-- --------------------------------------------------------------------------------
-- Tables are composed of columns (fields) and rows (records).
-- Creating a table
CREATE TABLE products (
id SERIAL PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
category VARCHAR(50),
price NUMERIC(8, 2) NOT NULL,
stock_quantity INTEGER,
created_at DATE
);
-- Altering a table (add, modify, drop).
ALTER TABLE products ADD COLUMN description TEXT;
ALTER TABLE products ALTER COLUMN description SET NOT NULL;
ALTER TABLE products DROP COLUMN description;
-- Dropping a table.
DROP TABLE IF EXISTS products;
-- Describe table structure.
\d products
-- --------------------------------------------------------------------------------
-- 6. Constraints
-- --------------------------------------------------------------------------------
-- PostgreSQL constraints are used to specify rules for the data in a table.
-- They ensure the integrity of data in the database.
--
-- Common PostgreSQL constraints:
-- * PRIMARY KEY: Uniquely identifies each row in a table.
-- * FOREIGN KEY: Establishes a link between two tables.
-- * UNIQUE: Ensures all values in a column are distinct.
-- * NOT NULL: Ensures a column cannot have NULL values.
-- * CHECK: Ensures that all column values satisfy a specific condition.
-- * DEFAULT: Provides a default value, if no value is specified.
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY, -- PRIMARY KEY constraint
product_id INTEGER UNIQUE, -- UNIQUE constraint
customer_name VARCHAR(100) NOT NULL, -- NOT NULL constraint
order_date DATE NOT NULL, -- NOT NULL constraint
quantity INTEGER CHECK (quantity > 0), -- CHECK constraint
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- DEFAULT constraint
FOREIGN KEY (product_id) REFERENCES products(id) -- FOREIGN KEY constraint
);
-- Adding a constraint.
ALTER TABLE orders ADD CONSTRAINT chk_valid_order CHECK (order_date <= CURRENT_DATE);
-- Adding an exclusion constraint.
CREATE TABLE reservations (
room_id INT,
during TSRANGE,
-- Enforce that no two rows can have the same (room_id and time range).
EXCLUDE USING GIST (room_id WITH =, during WITH &&)
);
-- --------------------------------------------------------------------------------
-- 7. Data Manipulation
-- --------------------------------------------------------------------------------
-- Inserting/Updating data in your tables.
-- You can insert either a single row or multiple rows
INSERT INTO products (product_name, category, price, stock_quantity, created_at)
VALUES
('Laptop', 'Electronics', 999.99, 50, '2023-01-15'),
('Smartphone', 'Electronics', 799.99, 150, '2023-02-01'),
('Desk Chair', 'Furniture', 199.99, 75, '2023-03-10');
-- Updating the price of a specific product based on its name.
UPDATE products SET price = 879.99 WHERE product_name = 'Smartphone';
-- Deleting a specific product based on its stock_quantity.
DELETE FROM products WHERE stock_quantity = 0;
-- --------------------------------------------------------------------------------
-- 8. Querying Data
-- --------------------------------------------------------------------------------
-- Retrieving data from your tables.
-- Retrieve all columns for each product.
SELECT * FROM products;
-- Retrieve only specific columns for each product.
SELECT product_name, price, stock_quantity FROM products;
-- Retrieve all products with a price greater than 500.
SELECT * FROM products WHERE price > 500;
-- Results can be ordered: ascending (ASC) or descending (DESC).
SELECT * FROM products ORDER BY created_at DESC;
-- Retrieve the first 10 products with their names and prices.
SELECT product_name, price FROM products LIMIT 10;
-- Retrieve the next 10 products after the first 10 (offset).
SELECT product_name, price FROM products OFFSET 10 LIMIT 10;
-- Retrieve all unique product categories.
SELECT DISTINCT category FROM products;
-----------
-- 9. Joins
-----------
-- Joins are crucial for querying data spread across multiple tables.
-- They are used to combine rows from two or more tables based
-- on a related column between them.
--
-- Main types of PostgreSQL joins:
-- * INNER JOIN: Returns rows with matching values in both tables.
-- * LEFT JOIN : Returns all rows from the left table, and matching
-- rows from the right table. unmatched right rows are NULL.
-- * RIGHT JOIN: Returns all rows from the right table, and matching
-- rows from the left table. unmatched left rows are NULL.
-- * FULL JOIN : Returns all rows with matches in either table
-- unmatched rows are NULL.
-- * CROSS JOIN: Returns the Cartesian product of two tables, showing all
-- possible row combinations.
-- * SELF JOIN : Joins a table with itself to compare same table rows.
-- INNER JOIN: Retrieve the order details and product name for all orders.
SELECT orders.order_id, products.product_name, orders.customer_name, orders.quantity, orders.order_date
FROM orders
INNER JOIN products ON orders.product_id = products.id;
-- LEFT JOIN: Retrieve all products with their order, if available, else NULL.
SELECT products.product_name, orders.order_id, orders.customer_name, orders.quantity, orders.order_date
FROM products
LEFT JOIN orders ON products.id = orders.product_id;
-- RIGHT JOIN: Retrieve all orders with their product, if available, else NULL.
SELECT products.product_name, orders.order_id, orders.customer_name, orders.quantity, orders.order_date
FROM products
RIGHT JOIN orders ON products.id = orders.product_id;
-- FULL JOIN: Retrieve all matched or unmatched products and orders, else NULL.
SELECT products.product_name, orders.order_id
FROM products
FULL JOIN orders ON products.id = orders.product_id;
-- CROSS JOIN: Retrieve all possible combinations of products and categories.
SELECT products.product_name, categories.category_name
FROM products
CROSS JOIN categories;
-- --------------------------------------------------------------------------------
-- 10. Aggregate Functions
-- --------------------------------------------------------------------------------
-- Used to perform calculations on a set of values and return a single value.
-- Often used with the GROUP BY clause to group rows that have the same values.
-- Common Postgres aggregate functions:
-- * COUNT(): Counts the number of rows or non-null values.
-- * SUM(): Calculates the sum of a set of values.
-- * AVG(): Calculates the average of a set of values.
-- * MAX(): Returns the maximum value in a set.
-- * MIN(): Returns the minimum value in a set.
-- * ARRAY_AGG(): Collects values into an array.
-- * STRING_AGG(): Concatenates strings with a delimiter.
-- Get the total number of orders.
SELECT COUNT(*) AS total_orders FROM orders;
-- Get the total amount of all orders.
SELECT SUM(amount) AS total_amount FROM orders;
-- Get the product count and average price for each category.
SELECT category, COUNT(*) AS product_count, AVG(price) AS average_price
FROM products
GROUP BY category;
-- Get categories with more than 5 products.
SELECT category, COUNT(*) AS product_count
FROM products
GROUP BY category
HAVING COUNT(*) > 5;
-- Get a list of products for each category as an array.
SELECT category, ARRAY_AGG(product_name) AS products
FROM products
GROUP BY category;
-- Get a comma-separated list of products for each category.
SELECT category, STRING_AGG(product_name, ', ') AS product_list
FROM products
GROUP BY category;
-- --------------------------------------------------------------------------------
-- 11. Subqueries
-- --------------------------------------------------------------------------------
-- A Subquery is a query nested inside another query. They are useful for
-- breaking down complex queries and can be used in SELECT, WHERE, HAVING,
-- FROM, and EXISTS clauses.
--
-- Types of Subqueries:
-- * Scalar: Returns a single value.
-- * Row: Returns a single row with multiple columns.
-- * Table: Returns multiple rows and columns.
-- * Correlated: References columns from the outer query.
-- Scalar: Retrieve products priced above the overall average.
SELECT product_name, price
FROM products
WHERE price > (SELECT AVG(price) FROM products);
-- Row: Retrieve the product with the highest price across all categories.
SELECT *
FROM products
WHERE (category, price) = (
SELECT category, MAX(price)
FROM products
GROUP BY category
ORDER BY MAX(price) DESC
LIMIT 1
);
-- Table: Retrieve products that have been ordered more than 100 times.
SELECT product_name, price
FROM products
WHERE id IN (
SELECT product_id
FROM orders
GROUP BY product_id
HAVING SUM(quantity) > 100
);
-- Correlated: Retrieve the most expensive product across all categories.
SELECT p.product_name, p.price
FROM products p
WHERE p.price > (
SELECT AVG(price)
FROM products
WHERE category = p.category
);
-- --------------------------------------------------------------------------------
-- 12. Indexes
-- --------------------------------------------------------------------------------
-- Improve query performance by speeding up data retrieval. But may slow
-- down data modification operations such as INSERT, UPDATE, and DELETE.
--
-- Types of indexes in PostgreSQL:
-- * B-tree: Default, for general use.
-- * Hash: Optimized for exact matches.
-- * GIST: Supports complex types, full-text search.
-- * SP-GiST: Efficient for non-balanced structures.
-- * GIN: Good for arrays and composite types.
-- * BRIN: Best for large, sequential data.
-- Create a B-tree index on product names.
CREATE INDEX idx_product_name ON products(product_name);
-- Create a unique B-tree index on SKU values.
CREATE UNIQUE INDEX idx_product_sku ON products(sku);
-- Create a B-tree index on category and price.
CREATE INDEX idx_product_category_price ON products(category, price);
-- Create a partial B-tree index on products with price greater than 1000.
CREATE INDEX idx_high_value_products ON products(price) WHERE price > 1000;
-- Create a B-tree index on lowercased product names.
CREATE INDEX idx_lower_product_name ON products(LOWER(product_name));
-- Drop the index on product names if it exists.
DROP INDEX IF EXISTS idx_product_name;
-- Rebuild all indexes for the products table.
REINDEX TABLE products;
-- --------------------------------------------------------------------------------
-- 13. Stored Procedures and Functions
-- --------------------------------------------------------------------------------
-- A set of SQL statements that can be stored and executed repeatedly.
-- They improve performance by reducing client-server communication.
--
-- * Procedures: Perform actions, may not return a value.
-- * Functions: Return a value, usable in SQL queries.
-- Create or replace a procedure to update a product's price.
CREATE OR REPLACE PROCEDURE update_product_price(
product_id_param INTEGER,
new_price NUMERIC
)
LANGUAGE plpgsql
-- Changes the delimiter to $$ to allow for multi-line statements.
AS $$
BEGIN
UPDATE products
SET price = new_price
WHERE id = product_id_param;
END;
$$;
-- Call the procedure to update the price of product with ID 1.
CALL update_product_price(1, 1099.99);
-- Drop the procedure if it exists.
DROP PROCEDURE IF EXISTS update_product_price(INTEGER, NUMERIC);
-- Create or replace a function to get the count of products in a category.
CREATE OR REPLACE FUNCTION get_product_count(category_name VARCHAR)
RETURNS INTEGER AS $$
DECLARE
product_count INTEGER;
BEGIN
SELECT COUNT(*) INTO product_count
FROM products
WHERE category = category_name;
RETURN product_count;
END;
$$ LANGUAGE plpgsql;
-- Get the count of products in the 'Electronics' category.
SELECT get_product_count('Electronics');
-- Drop the function if it exists.
DROP FUNCTION IF EXISTS get_product_count(VARCHAR);
-- --------------------------------------------------------------------------------
-- 14. Transactions
-- --------------------------------------------------------------------------------
-- Transaction is a sequence of one or more SQL operations that are executed
-- as a single unit. If any statement fails, the entire transaction can be
-- rolled back to maintain data integrity.
--
-- Transactions have the following properties (ACID):
-- * Atomicity: Entire transaction succeeds or fails as a whole.
-- * Consistency: Ensures valid state transitions in the database.
-- * Isolation: Transactions run independently of each other.
-- * Durability: Committed transactions persist, even after failures.
-- Start a transaction.
BEGIN;
-- Insert a new product.
INSERT INTO products (product_name, category, price, stock_quantity, created_at)
VALUES ('Laptop', 'Electronics', 999.99, 50, '2023-01-15');
-- if there's an error, roll back the transaction, discarding all changes.
ROLLBACK;
-- Commit the transaction, applying all changes.
COMMIT;
-- Starting another transaction.
BEGIN;
-- Insert a new product and set a savepoint.
INSERT INTO products (product_name, category, price, stock_quantity, created_at)
VALUES ('Smartphone', 'Electronics', 799.99, 150, '2023-02-01');
-- Set a savepoint.
SAVEPOINT my_savepoint;
-- Update stock quantity.
UPDATE products SET stock_quantity = stock_quantity - 1 WHERE id = 1;
-- Roll back to the savepoint, undoing changes since the savepoint.
ROLLBACK TO my_savepoint;
-- Release the savepoint, removing it from the transaction.
RELEASE SAVEPOINT my_savepoint;
-- Commit the transaction, applying all changes up to the savepoint.
COMMIT;
-- --------------------------------------------------------------------------------
-- 15. Views
-- --------------------------------------------------------------------------------
-- Views are virtual tables based on the result of an SQL statement.
-- They don't store data and provide a way to simplify complex queries,
-- improve data security and ensure a consistent data interface.
--
-- Types of PostgreSQL views:
-- 1. Simple: Based on one table or basic joins.
-- 2. Complex: Involve multiple tables or complex queries.
-- 3. Updatable: Allow INSERT, UPDATE, and DELETE.
-- 4. Materialized: Store results physically for faster access.
-- Create a simple view of product names and prices.
CREATE VIEW product_overview AS
SELECT product_name, price
FROM products;
-- Query the product overview view.
SELECT * FROM product_overview;
-- Create a detailed view of orders with product details.
CREATE VIEW detailed_order_summary AS
SELECT
o.customer_name, p.product_name, p.price, o.quantity,
(p.price * o.quantity) AS total_cost,
o.order_date
FROM orders o
JOIN products p ON o.product_id = p.id;
-- Query the detailed order summary view.
SELECT * FROM detailed_order_summary;
-- Create a materialized view summarizing product sales.
CREATE MATERIALIZED VIEW product_sales_summary AS
SELECT
p.id AS product_id,
p.product_name,
SUM(o.quantity) AS total_quantity_sold,
SUM(p.price * o.quantity) AS total_revenue
FROM orders o
JOIN products p ON o.product_id = p.id
GROUP BY p.id, p.product_name;
-- Refresh the materialized view to update data.
REFRESH MATERIALIZED VIEW product_sales_summary;
-- Query the refreshed materialized view.
SELECT * FROM product_sales_summary;
-- Drop views and materialized view if they exist.
DROP VIEW IF EXISTS product_overview;
DROP VIEW IF EXISTS detailed_order_summary;
DROP MATERIALIZED VIEW IF EXISTS product_sales_summary;
-- --------------------------------------------------------------------------------
-- 16. Triggers
-- --------------------------------------------------------------------------------
-- Triggers are database objects that are automatically executed when
-- certain events occurs.
--
-- Types of triggers in MySQL:
-- * BEFORE INSERT, AFTER INSERT, BEFORE UPDATE, AFTER UPDATE,
-- BEFORE DELETE and AFTER DELETE.
--
-- NEW: New row of data that is being inserted or updated.
-- OLD: Existing row of data before it is updated or deleted.
-- Define a function to update the stock quantity.
CREATE OR REPLACE FUNCTION update_stock_quantity()
RETURNS TRIGGER AS $$
BEGIN
-- Decrease stock quantity based on the new order.
UPDATE products
SET stock_quantity = stock_quantity - NEW.quantity
WHERE id = NEW.product_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create a trigger to call the function after an order is inserted.
CREATE TRIGGER after_order_insert
AFTER INSERT ON orders
FOR EACH ROW
EXECUTE FUNCTION update_stock_quantity();
-- Define a function to check the stock before inserting an order.
CREATE OR REPLACE FUNCTION check_stock_before_insert()
RETURNS TRIGGER AS $$
DECLARE
stock INT;
BEGIN
-- Check current stock quantity for the product.
SELECT stock_quantity INTO stock FROM products WHERE id = NEW.product_id;
-- Raise an exception if stock is insufficient.
IF stock < NEW.quantity THEN
RAISE EXCEPTION 'Insufficient stock for product ID %', NEW.product_id;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create a trigger to call the function before an order is inserted.
CREATE TRIGGER before_order_insert
BEFORE INSERT ON orders
FOR EACH ROW
EXECUTE FUNCTION check_stock_before_insert();
-- Drop the trigger if it exists.
DROP TRIGGER IF EXISTS before_order_insert ON orders;
-- Drop the stock checking function if it exists.
DROP FUNCTION IF EXISTS check_stock_before_insert();
-- --------------------------------------------------------------------------------
-- 17. User Management
-- --------------------------------------------------------------------------------
-- User management involves creating, modifying, and deleting user
-- accounts, as well as granting and revoking privileges.
-- Create a new user with a password.
CREATE USER new_user WITH PASSWORD 'password123';
-- Create a superuser with a password.
CREATE USER admin_user WITH SUPERUSER PASSWORD 'adminpassword';
-- Grant SELECT and INSERT privileges on the products table to new_user.
GRANT SELECT, INSERT ON products TO new_user;
-- Grant all privileges on the public schema to new_user.
GRANT ALL PRIVILEGES ON SCHEMA public TO new_user;
-- Create a read-only role.
CREATE ROLE read_only;
-- Grant SELECT on all tables in the public schema to the read_only role.
GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only;
-- Grant the read_only role to new_user.
GRANT read_only TO new_user;
-- Revoke INSERT privilege on the products table from new_user.
REVOKE INSERT ON products FROM new_user;
-- Drop the user new_user if it exists.
DROP USER IF EXISTS new_user;
-- Drop the read_only role.
DROP ROLE read_only;
-- --------------------------------------------------------------------------------
-- 18. Backup and Restore
-- --------------------------------------------------------------------------------
-- Regular backups are crucial for data safety and recovery.
-- Backup the entire database to a SQL file.
pg_dump -U username -d database_name -f backup_file.sql;
-- Backup specific tables to a SQL file.
pg_dump -U username -d database_name -t table1 -t table2 -f backup_file.sql;
-- Backup only the schema (no data) to a SQL file.
pg_dump -U username -d database_name --schema-only -f schema_backup.sql;
-- Backup the database to a custom-format backup file.
pg_dump -U username -d database_name -F c -f backup_file.custom;
-- Backup the database to a directory format.
pg_dump -U username -d database_name -F d -f backup_directory;
-- Restore database from a custom-format backup file.
pg_restore -U username -d database_name backup_file.custom;
-- Restore database from a directory-format backup.
pg_restore -U username -d database_name backup_directory;
-- Restore database from a SQL file.
psql -U username -d database_name -f backup_file.sql;
-- Physical Backup
------------------
-- Creates binary copy of the database cluster to a specified directory.
pg_basebackup -U username -D backup_directory -Fp -Xs -P;
-- To Restore:
-- 1. Stop the PostgreSQL server.
-- 2. Replace the existing data directory with the backup directory.
-- 3. Start the PostgreSQL server.
-- Point-in-Time Recovery
-------------------------
-- 1. Enable WAL Archiving:
ALTER SYSTEM SET archive_mode = 'on';
ALTER SYSTEM SET archive_command = 'cp %p /your/archive/directory/%f';
SELECT pg_reload_conf();
-- 2. Take Base Backup:
pg_basebackup -D /path/to/backup -Ft -z -P --wal-method=stream
-- 3. Stop the PostgreSQL server:
pg_ctl stop -D /path/to/data_directory
-- 4. Restore Backup:
tar -xvf /path/to/backup/base.tar.gz -C /path/to/data_directory
-- 5. Create recovery.conf with:
restore_command = 'cp /your/archive/directory/%f %p'
recovery_target_time = 'YYYY-MM-DD HH:MI:SS'
-- 6. Start the PostgreSQL server:
pg_ctl start -D /path/to/data_directory
-- --------------------------------------------------------------------------------
-- 19. Concurrency Control
-- --------------------------------------------------------------------------------
-- Concurrency Control ensures that multiple transactions can be executed
-- simultaneously, without interfering with each other, maintaining integrity
-- and consistency. By Default Postgres uses Multi-Version Concurrency Control.
--
-- Key concepts Concurrency Control:
-- * Multi-Version Concurrency Control (MVCC): Allows multiple versions of a
-- row to exist, helping to manage concurrent access without locking.
-- * Isolation Levels: Controls visibility of transaction changes.
-- * Locks: Prevent conflicts between transactions.
-- * Deadlocks: Occur when transactions wait on each other's locks.
-- Isolation Levels
-------------------
-- * READ COMMITTED: Default. Sees data committed before each query.
-- * READ UNCOMMITTED: Can read uncommitted changes.
-- * REPEATABLE READ: Sees the same snapshot for all queries in the transaction.
-- * SERIALIZABLE: Ensures transactions act as if executed sequentially.
-- Setting an isolation level
BEGIN;
-- Set isolation level to Repeatable Read
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- Perform some operations
SELECT * FROM products WHERE category = 'Electronics';
-- Commit the transaction
COMMIT;
-- Locks
--------
-- PostgreSQL lock types:
-- * Row-Level Locks:
-- - FOR UPDATE: Blocks row modifications and locks by others.
-- - FOR SHARE: Blocks modifications, allows reading.
-- * Table-Level Locks:
-- - ACCESS SHARE: Allows reads, blocks exclusive locks.
-- - ROW SHARE: Allows reads, row-level updates.
-- - ROW EXCLUSIVE: Allows inserts, updates, deletes.
-- - SHARE UPDATE EXCLUSIVE: Blocks schema changes, VACUUM.
-- - SHARE: Blocks modifications, allows reads.
-- - SHARE ROW EXCLUSIVE: Blocks modifications and certain locks.
-- - EXCLUSIVE: Allows only ACCESS SHARE locks.
-- - ACCESS EXCLUSIVE: Blocks all access.
-- * Advisory Locks: User-defined, for custom use cases.
-- Row-level locking:
BEGIN;
-- Locking row to update its stock quantity.
SELECT * FROM products WHERE id = 1 FOR UPDATE;
-- Update the locked row.
UPDATE products SET stock_quantity = stock_quantity - 1 WHERE id = 1;
-- Commit the transaction.
COMMIT;
-- Table-level locking:
BEGIN;
-- Lock the 'products' table in EXCLUSIVE mode
LOCK TABLE products IN EXCLUSIVE MODE;
-- Perform some operations
-- Commit the transaction
COMMIT;
-- Deadlock:
-- Transaction 1:
BEGIN;
-- Lock row 1 for update.
UPDATE example SET value = value + 1 WHERE id = 1;
-- Attempt to lock row 2, which is already locked by Transaction 2.
UPDATE example SET value = value + 1 WHERE id = 2;
-- Commit (will not reach due to deadlock).
COMMIT;
-- Transaction 2:
BEGIN;
-- Lock row 2 for update.
UPDATE example SET value = value + 1 WHERE id = 2;
-- Attempt to lock row 1, which is already locked by Transaction 1.
UPDATE example SET value = value + 1 WHERE id = 1;
-- Commit (will not reach due to deadlock).
COMMIT;
-- PostgreSQL detects the deadlock and aborts one of the transactions.
-- --------------------------------------------------------------------------------
-- 20. Replication
-- --------------------------------------------------------------------------------
-- Is a process that allows you to automatically copy data from one
-- database server (the master) to one or more database servers (the slaves).
--
-- Benefits :
-- High availability by allowing a slave to be promoted to master in case of
-- failure, enables load balancing by distributing read queries across slaves,
-- facilitates backups on a slave, and allows intensive data analysis.
--
-- Key concepts:
-- * Primary: Source database server with original data.
-- * Standby: Destination server receiving data copies.
-- * WAL: Log of all changes, like MySQL's binary log.
-- * Streaming Replication: Real-time WAL transfer to standby.
-- * Physical Replication: Byte-by-byte copy of the database.
-- * Logical Replication: Replication based on object-level changes.
-- PostgreSQL Primary Configuration:
-- Set up WAL for replication.
wal_level = replica -- WAL level for replication
max_wal_senders = 10 -- Max concurrent WAL sender processes
wal_keep_size = '1GB' -- Size of WAL to keep for replication
hot_standby = on -- Allow queries on standby
-- Create replication user.
CREATE USER repl_user WITH REPLICATION ENCRYPTED PASSWORD 'password';
-- Allow replication connections from replica.
host replication repl_user <replica_ip_address>/24 md5
-- Perform a base backup from the primary server.
pg_basebackup -h <primary_ip_address> -D /path_to_data -U replicator -P --wal-method=stream
-- PostgreSQL Replica Configuration:
-- Enable hot standby and configure primary connection.
hot_standby = on
primary_conninfo = 'host=<primary_ip> port=5432 user=replicator password=replica_password'
trigger_file = '/tmp/postgresql.trigger'
-- Start the standby server.
pg_ctl start -D /path/to/standby/data
-- Monitor replication status.
SELECT * FROM pg_stat_replication;
-- Check the WAL receiver status.
SELECT * FROM pg_stat_wal_receiver;
-- Pause WAL replay on the replica.
SELECT pg_wal_replay_pause();
-- Resume WAL replay on the replica.
SELECT pg_wal_replay_resume();
-- Promote the replica to primary.
pg_ctl promote -D /path/to/standby/data
-- --------------------------------------------------------------------------------
-- 21. Partitioning
-- --------------------------------------------------------------------------------
-- Is a database feature that allows you to divide a large table into
-- smaller, more manageable pieces, yet still treat them as a single table.
--
-- Main types of partitioning in PostgreSQL:
-- 1. Range: Based on a range of values (e.g., date ranges).
-- 2. List : Based on a list of known values (e.g., categories).
-- 3. Hash : Based on a hash of the partition key.
-- Create a range-partitioned table by creation date.
CREATE TABLE products (
id SERIAL PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
category VARCHAR(50),
price DECIMAL(8, 2) NOT NULL,
stock_quantity INT,
created_at DATE
) PARTITION BY RANGE (created_at);
-- Create a partition for the year 2023.
CREATE TABLE products_2023 PARTITION OF products
FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');
-- Create a partition for the year 2024.
CREATE TABLE products_2024 PARTITION OF products
FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');
-- Create a default partition for any non-matching dates.
CREATE TABLE products_default PARTITION OF products DEFAULT;
-- Create a list-partitioned table by category.
CREATE TABLE products (
id SERIAL PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
category VARCHAR(50),
price DECIMAL(8, 2) NOT NULL,
stock_quantity INT,
created_at DATE
) PARTITION BY LIST (category);
-- Create a partition for Electronics.
CREATE TABLE products_electronics PARTITION OF products
FOR VALUES IN ('Electronics');
-- Create a partition for Furniture.
CREATE TABLE products_furniture PARTITION OF products
FOR VALUES IN ('Furniture');
-- Create a default partition for any non-matching categories.
CREATE TABLE products_default PARTITION OF products DEFAULT;
-- After partitioning a table, you can insert, update, delete, and
-- query data without any special modification to your queries.
-- Detach a partition, making it a standalone table.
ALTER TABLE products DETACH PARTITION products_2023;
-- Reattach a detached partition or add a new table as a partition.
ALTER TABLE products ATTACH PARTITION products_2023
FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');
-- Permanently delete a partition and its data.
DROP TABLE products_2023;
-- --------------------------------------------------------------------------------
-- 22. Extensions
-- --------------------------------------------------------------------------------
-- Extensions are packages that add functionality to the database.
-- They can include additional data types, functions, operators, and more.
--
-- Key aspects of PostgreSQL Extensions:
-- 1. Modularity: Encapsulate related objects and functionality.
-- 2. Versioning: Extensions can be upgraded or downgraded.
-- 3. Dependency management: Extensions can depend on other extensions.
-- 4. Easy installation: Can be installed with a single SQL command.
--
-- Common PostgreSQL Extensions:
-- * PostGIS: Adds support for geographic objects.
-- * pgcrypto: Provides cryptographic functions.
-- * hstore: Implements key-value pair storage.
-- * uuid-ossp: Generates universally unique identifiers (UUIDs).
-- List available extensions.
SELECT * FROM pg_available_extensions;
-- List installed extensions.
SELECT * FROM pg_extension;
-- Install the hstore extension if it's not already installed.
CREATE EXTENSION IF NOT EXISTS hstore;
-- Create a table with an hstore column.
CREATE TABLE products (
id SERIAL PRIMARY KEY,