{"id":24807242,"url":"https://github.com/bagusperdanay7/postgresql-notes","last_synced_at":"2026-04-28T23:02:22.153Z","repository":{"id":235932687,"uuid":"791566475","full_name":"bagusperdanay7/PostgreSQL-Notes","owner":"bagusperdanay7","description":"Catatan Materi PostgreSQL-Notes diambil dari YouTube Pak Eko Kurniawan Khennedy (Programmer Zaman Now)","archived":false,"fork":false,"pushed_at":"2024-09-24T18:10:40.000Z","size":139,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-30T09:17:47.199Z","etag":null,"topics":["database","postgresql","sql"],"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/bagusperdanay7.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-04-25T00:25:28.000Z","updated_at":"2024-09-24T18:14:00.000Z","dependencies_parsed_at":"2024-04-25T02:06:29.513Z","dependency_job_id":"e8630559-be88-48f4-864a-bc540e38a596","html_url":"https://github.com/bagusperdanay7/PostgreSQL-Notes","commit_stats":null,"previous_names":["bagusperdanay7/postgresql-notes"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bagusperdanay7%2FPostgreSQL-Notes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bagusperdanay7%2FPostgreSQL-Notes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bagusperdanay7%2FPostgreSQL-Notes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bagusperdanay7%2FPostgreSQL-Notes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bagusperdanay7","download_url":"https://codeload.github.com/bagusperdanay7/PostgreSQL-Notes/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245440580,"owners_count":20615633,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["database","postgresql","sql"],"created_at":"2025-01-30T09:17:51.102Z","updated_at":"2026-04-28T23:02:22.095Z","avatar_url":"https://github.com/bagusperdanay7.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tutorial PostgreSQL Database\n\nKode ini merupakan materi PostgreSQL yang dibawakan oleh **Eko Kurniawan Khannedy** dari channel YouTube _Programmer Zaman Now_.\n\nLink Tutorial: [Video](https://www.youtube.com/watch?v=iEeveYoD0SA)\n\nBahasan Materi Meliputi:\n\n- Pengenalan Sistem Basis Data\n- Pengenalan PostgreSQL\n- Menginstall PostgreSQL\n- Database\n- Tipe Data\n- Tipe Data Number\n- Tipe Data String\n- Tipe Data Date dan Time\n- Tipe Data Boolean\n- Tipe Data Enum\n- TIpe Data Lainnya\n- Table\n- Insert Data\n- Select Data\n- Primary Key\n- Where Clause\n- Update Data\n- Delete Data\n- Alias\n- Where Operator\n- Order By Clause\n- Limit Clause\n- Select Distinct Data\n- Numeric Function\n- Auto Increment\n- Sequence\n- String Function\n- Date dan Time Function\n- Flow Control Function\n- Aggregate Function\n- Grouping\n- Constraint\n- Index\n- Full Text Search\n- Table Relationship\n- Join\n- One to One Relationship\n- One to Many Relationship\n- Many to Many Relationship\n- Jenis Jenis Join\n- Subqueries\n- Set Operator\n- Transaction\n- Locking\n- Schema\n- User Management\n- Backup Database\n- Restore Database\n\n## Technology stack \u0026 Tools\n\n**Program ini membutuhkan:**\n\n| Language \u0026 Library | Version |\n| ------------------ | ------- |\n| PostgreSQL         | 15.5+   |\n| pgAdmin 4          | 7.0+    |\n\n## Catatan Pribadi\n\nJika ingin klona di komputer lain. Taruh di direktori berikut:\n\n    .\n    ├── Course\n    │   ├── Programmer Zaman Now\n    |   |   ├── POSTGRESQL\n    |   |   └── ...\n    |   └── ...\n    └── ...\n\nJika sudah di berada di folder **POSTGRESQL**, baru clone.\n\n```sh\ngit clone https://github.com/bagusperdanay7/PostgreSQL-Notes.git\n```\n\n# Notes\n\nIni merupakan catatan pribadi mengenai materi dari **PostgreSQL** Database dengan Pak _Eko Kurniawan Khannedy_.\n\n## Mengunakan PostgreSQL Pertama kali\n\nMasukkan syntax berikut di terminal, sesuaikan `--username` dan `--password` nya.\n\n```shell\npsql --host=localhost --port=5432 --username=user --password\npsql --host=localhost --port=5432 --dbname=belajar_restore --username=user --password\n```\n\n## Melihat Semua Database\n\nUntuk melihat semua database gunakan `\\l` atau command di bawah ini\n\n```sql\nselect datname from pg_database;\n```\n\n## Membuat Database Baru\n\n`nama_database` diisi dengan nama database yang diinginkan\n\n```sql\ncreate database nama_database;\n```\n\n## Menghapus Database\n\n`nama_database` diisi dengan nama database yang diinginkan\n\n```sql\ndrop database nama_database;\n```\n\n## Menggunakan Database\n\n```console\n\\c namadatabase\n```\n\n## Melihat Table\n\n```sql\nselect * from pg_tables where schemaname = 'public';\n```\n\n## Membuat Table\n\n```sql\ncreate table barang(\n    kode int,\n    name varchar(100),\n    harga int,\n    jumlah int\n);\n```\n\n## Melihat Detail Table\n\n```console\n\\d barang\n```\n\n## Mengubah Table\n\nJika Menambah Column\n\n```sql\nalter table barang\nadd column deskripsi text;\n```\n\nMenghapus Column\n\n```sql\nalter table barang\ndrop column deskripsi;\n```\n\nJika\n\n### Mengubah Nama Column\n\n```sql\nalter table barang\nrename column name to nama;\n```\n\n## Default Value \u0026 Null Value\n\nKetika kita ingin membuat suatu kolom nilainya tidak boleh kosong gunakan kata kunci `NOT NULL`. Jika ingin nilai bawaan (defaultnya) terisi jika tidak diisi, maka gunakan kata kunci `default`.\n\n```sql\ncreate table barang(\n    kode int not null ,\n    name varchar(100) not null,\n    harga int not null default 1000,\n    jumlah int not null default 0,\n    waktu_dibuat timestamp not null default current_timestamp\n);\n```\n\n## Membuat Ulang Table\n\n```sql\ntruncate barang;\n```\n\n## Menghapus Table\n\n```sql\ndrop table barang;\n```\n\n## Memasukkan Data (Insert)\n\n### Memasukkan Data Single\n\n```sql\ninsert into products(id, name, price, quantity)\nvalues('P0001', 'Mie Ayam Original', 15000, 100);\n```\n\n### Memasukkan Banyak Data\n\n```sql\ninsert into products(id, name, price, quantity)\nvalues ('P0003', 'Mie Ayam Ceker', 20000, 100),\n       ('P0004', 'Mie Ayam Spesial', 25000, 100),\n       ('P0005', 'Mie Ayam Yamin', 15000, 100);\n```\n\n## Melihat / Menyeleksi Data (Select)\n\n### Melihat Semua Data dan Semua Kolom\n\n```sql\nselect * from products;\n```\n\n### Melihat Semua data dan hanya beberapa kolom\n\n```sql\nselect id, name, price, quantity from products;\n```\n\n## Primary Key\n\nPrimary key biasanya bersifat unik, Primary Key adalah sebuah kolom yang kita tunjuk sebagai id dari table tersebut. Primary key bisa merujuk beberapa kolom, namun disarankan hanya satu kolom saja.\n\n### Menambahkan Primary Key di Tabel\n\n```sql\ncreate table products(\n    id varchar(10) not null ,\n    name varchar(100) not null,\n    description text,\n    price int not null ,\n    quantity int not null default 0,\n    created_at timestamp not null default current_timestamp,\n    primary key (id)\n);\n```\n\n### Menambahkan Primary Key di Tabel (Alter)\n\n```sql\nalter table products\n    add primary key (id);\n```\n\n## Where Clause\n\nContoh 1 (Seleksi Number)\n\n```sql\nselect id, name, price, quantity\nfrom products\nwhere price = 20000;\n```\n\nContoh 2 (Seleksi String)\n\n```sql\nselect id, name, price, quantity\nfrom products\nwhere id = 'P0004';\n```\n\n## Update Data\n\n**Menambah Kolom Kategori Terlebih Dahulu**\n\n```sql\ncreate type PRODUCT_CATEGORY as enum ('Makanan', 'Minuman', 'Lain-Lain');\n\nalter table products\n    add column category PRODUCT_CATEGORY;\n```\n\n### Mengubah data Satu Kolom\n\n```sql\nupdate products\nset category = 'Makanan'\nwhere id = 'P0001';\n```\n\n### Mengubah Data Beberapa Kolom\n\n```sql\nupdate products\nset category = 'Makanan',\n    description = 'Mie Ayam + Ceker'\nwhere id = 'P0003';\n```\n\n### Mengubah data dengan Value di Kolom\n\n```sql\nupdate products\nset price = price + 5000\nwhere id = 'P0004';\n```\n\n## Menghapus Data (Delete)\n\n```sql\ndelete from products\nwhere id = 'P0009';\n```\n\n## Alias\n\n### Alias untuk Kolom\n\n```sql\nselect id as \"Kode Barang\", price as Harga, description as Deskripsi from products;\n```\n\n### Alias untuk Table\n\n```sql\nselect p.id as \"Kode Barang\",\n       p.price as \"Harga Barang\",\n       p.description as \"Deskripsi Barang\"\nfrom products as p;\n```\n\n## Where Operator\n\nWhere dengan operator perbandingan\n\n### Operator Lebih Dari (\u003e)\n\n```sql\nselect * from products where price \u003e 15000;\n```\n\n### Operator Kurang Dari Sama Dengan (\u003c=)\n\n```sql\nselect * from products where price \u003c= 15000;\n```\n\n### Operator Tidak Sama Dengan (!=)\n\n```sql\nselect * from products where category != 'Minuman';\n```\n\n### Operator AND\n\nUntuk Operasi AND kedua kondisi harus benar, jika salah satu salah maka akan bernilai salah (false)\n\n```sql\nselect * from products where price \u003e 15000 and category = 'Minuman';\n```\n\n### Operasi OR\n\nUntuk Operasi OR, Jika salah satu kondisi terpenuhi, maka akan tetap muncul. Kecuali jika keduanya `false`\n\n```sql\nselect * from products where price \u003e 15000 or category = 'Makanan';\n```\n\n### Prioritas dengan Kurung ()\n\n```sql\nselect * from products where category = 'Makanan' or (quantity \u003e 100 and price \u003e 15000);\n```\n\n### LIKE Operator\n\nKata kunci `LIKE` case sensitif, jika ingin mencari incase sensitif gunakan kata kunci `ILIKE`.\n\n| LIKE Operator |                         Hasil                         |\n| ------------- | :---------------------------------------------------: |\n| LIKE 'b%'     |                String dengan awalan b                 |\n| LIKE '%a'     |                String dengan akhiran b                |\n| LIKE '%eko%'  | String berisi eko tanpa peduli depan atau belakangnya |\n| NOT LIKE      |                      Tidak LIKE                       |\n\n---\n\n```sql\nselect * from products where name ilike '%es%';\n```\n\n### NULL Operator\n\nMencari null operator tidak bisa menggunakan operator perbandingan = NULL, Hanya ada dua, yaitu `IS NULL` dan `IS NOT NULL`.\n\n```sql\n-- null\nselect * from products where description is null;\n\n-- tidak null\nselect * from products where description is not null;\n```\n\n### BETWEEN Operator\n\nTerdapat operator `BETWEEN` dan `NOT BETWEEN`.\n\n```sql\n-- diantara\nselect * from products where price between 10000 and 20000;\n\n-- tidak diantara\nselect * from products where price not between 10000 and 20000;\n```\n\n### IN Operator\n\nOperator **IN** adalah operator untuk mencari kolom dengan beberapa nilai, untuk kebalikannya gunakan `NOT IN`.\n\n```sql\nselect * from products where category in ('Makanan', 'Minuman');\n```\n\n## Order by Clause\n\nUntuk mengurutkan gunakan syntax `ORDER BY`, terdapat dua jenis pengurutan ada Ascending (secara menaik) dengan perintah `ASC` dan Descending (secara menurun) dengan perintah `DESC`. Juga bisa mengurutkan lebih dari satu kolom.\n\n```sql\nselect * from products order by price asc;\n\n-- lebih dari satu kolom\nselect * from products order by price asc, id desc;\n```\n\n## Limit Clause\n\nLimit dibutuhkan untuk membatasi data, di limit juga bisa melewatkan sejumlah data yang tidak kita ingin lihat. `LIMIT` digunakan untuk paging, dengan kombinasi `OFFSET`.\n\n```sql\nselect * from products where price \u003e 0 order by price asc, id desc limit 2;\n```\n\nDengan offset, misal untuk page ke-2, kita tentukan `OFFSET`2.\n\n```sql\nselect * from products where price \u003e 0 order by price asc, id desc limit 2 offset 2;\n```\n\n## SELECT DISTINCT\n\nSelect distinct digunakan untuk menghilangkan data duplikat.\n\n```sql\nselect distinct category from products;\n```\n\n## Numeric Function\n\nFitur di dalam PostgreSQL untuk memanipulasi data angka, dibagi menjadi dua, **Arithmetic Operator** dan **Mathematical Function**.\n\n### Arithmetic Operator\n\n| Operator |              Hasil              |\n| -------- | :-----------------------------: |\n| +        |        Tambah (Addition)        |\n| -        |      Kurang (Substraction)      |\n| \\*       |      Kali (Multiplication)      |\n| /        |         Bagi (Division)         |\n| %        | Modulus, menghasilkan remainder |\n\n---\n\n```sql\nselect 10 + 10 as hasil;\n\nselect id, name, price / 1000 as price_in_k from products;\n```\n\n### Mathematical Function\n\n[PostgreSQL Math Function](https://www.postgresql.org/docs/15/functions-math.html)\n\n```sql\nselect pi();\n\nselect power(10,2);\n\nselect cos(10), sin(10), tan(10);\n\nselect id, name, power(quantity, 2) as quantity_power_2 from products;\n```\n\n## Auto Increment\n\nPostgreSQL memiliki tipe data Number bernama `SERIAL` untuk menambah nilai otomatis (berurut).\n\n```sql\ncreate table admin\n(\n    id serial not null,\n    first_name varchar(100) not null,\n    last_name varchar(100),\n    primary key (id)\n);\n```\n\n### Melihat Id / Nilai saat ini\n\n```sql\nselect currval('admin_id_seq');\n```\n\n## Sequence\n\nSequence adalah fitur dimana kita bisa membuat function auto increment.\n\n```sql\n-- Membuat sequence\ncreate sequence contoh_sequence;\n\n-- Memanggil sequence, otomatis increment\nselect nextval('contoh_sequence');\n\n-- Mengambil nilai terakhir sequence\nselect currval('contoh_sequence');\n```\n\nMelihat Semua Sequence:\n\n```console\n\\ds\n\\d admin_id_seq\n```\n\n## String Function\n\n[String Functions](https://www.postgresql.org/docs/15/functions-string.html)\n\n```sql\nselect id, lower(name), length(name), lower(description) from products;\n```\n\n## Date \u0026 Time Function\n\n[Date \u0026 Time Functions](https://www.postgresql.org/docs/15/functions-datetime.html)\n\n```sql\nselect id, extract(year from created_at), extract(month from created_at) from products;\n```\n\n## Flow Control Function\n\nMirip if else dibahasa pemrograman.\n[Flow Control Functions](https://www.postgresql.org/docs/15/functions-conditional.html)\n\n### Menggunakan Case\n\n```sql\nselect id,\n       category,\n       case category\n            when 'Makanan' then 'Enak'\n            when 'Minuman' then 'Seger'\n            else 'Apa itu?'\n        end as category_case\nfrom products;\n```\n\n### Menggunakan Case dengan Operator\n\n```sql\nselect id,\n       price,\n       case\n           when price \u003c= 15000 then 'Murah'\n           when price \u003c= 20000 then 'Mahal'\n           else 'Mahal Banget'\n           end as \"Apakah murah?\"\nfrom products;\n```\n\n### Menggunakan Check Null\n\n```sql\nselect id,\n       name,\n       case\n           when description is null then 'Kosong'\n           else description\n           end as description\nfrom products;\n```\n\n## Aggregate Function\n\n[Aggregate Function](https://www.postgresql.org/docs/15/functions-aggregate.html)\n\n```sql\nselect count(id) from products;\n\nselect avg(price) from products;\n\nselect max(price) from products;\n\nselect min(price) from products;\n```\n\n## Group By\n\n`GROUP BY` clouse ini hanya bisa digunakan bersama aggregate function.\n\n```sql\nselect category, count(id) as \"Total Product\" from products group by category;\n\nselect category,\n       avg(price) as \"Rata Rata Harga\",\n       min(price) as \"Harga Termurah\",\n       max(price) as \"Harga Termahal\"\nfrom products\ngroup by category;\n```\n\n## Having Clause\n\nTerkadang ingin melakukan filter terhadap data yang telah digroup, untuk memfilter hasil dari aggregate function harus menggunakan `HAVING` clause.\n\n```sql\nselect category, count(id) as \"Total Product\"\nfrom products\ngroup by category\nhaving count(id) \u003e 3;\n\nselect category,\n       avg(price) as \"Rata Rata Harga\",\n       min(price) as \"Harga Termurah\",\n       max(price) as \"Harga Termahal\"\nfrom products\ngroup by category\nhaving avg(price) \u003e= 20000;\n```\n\n## Constraint\n\nKita bisa menambahkan constraint untuk menjaga data di tabel tetap baik, Constraint sangat bagus ditambahkan untuk menjaga terjadi validasi yang salah pada program kita, sehingga data yang masuk ke database tetap akan terjaga.\n\n### Unique Constraint\n\nUnique constraint adalah constraint yang memastikan bahwa data kita tetap unique.\n\n```sql\ncreate table customer\n(\n    id         serial       not null,\n    email      varchar(100) not null,\n    first_name varchar(100) not null,\n    last_name  varchar(100),\n    primary key (id),\n    constraint unique_email unique (email)\n);\n```\n\nOperasi mengubah tabel agar menambah/menghapus constraint.\n\n```sql\n-- menghapus constraint\nalter table customer\ndrop constraint unique_email;\n\n-- menambah constraint\nalter table customer\nadd constraint unique_email unique (email);\n```\n\n### Check Constraint\n\nMembuat tabel dengan check constraint\n\n```sql\ncreate table products\n(\n    id          varchar(100) not null,\n    name        varchar(100) not null,\n    description text,\n    price       int          not null,\n    quantity    int          not null,\n    created_at  timestamp    not null default current_timestamp,\n    primary key (id),\n    constraint price_check check ( price \u003e= 1000 )\n);\n```\n\nMenambah/Menghapus Check Constraint\n\n```sql\n-- menambah check constraint\nalter table products add constraint price_check check (price \u003e 1000);\n\n-- menghapus check constraint\n```\n\n## Index\n\nIndex (btree) digunakan agar memudahkan pencarian data, dan pengurutan menggunakan ORDER BY. Bisa membuat lebih dari satu index di table. Namun untuk proses manipulasi data (insert, update, \u0026 delete) akan menjadi lebih lambat.\n\n### Menambah Index\n\n```sql\ncreate index sellers_id_and_name_index on sellers (id,name);\ncreate index sellers_email_and_name_index on sellers (email,name);\n```\n\n## Full-Text Search\n\nFull-text search memungkinkan kita mencari sebagian kata di kolom dengan tipe data String. Full-text search menggunakan function to_tsvector(text) dan to_tsquery(query). Operator full-text search menggunakan @@.\n\n### Full-Text Search tanpa Index\n\n```sql\nselect * from products\nwhere to_tsvector(name) @@ to_tsquery('mie');\n```\n\n### Membuat Index Full-Text Search\n\n```sql\n-- mengambil bahasa yang tersedia\nselect cfgname from pg_ts_config;\n\ncreate index products_name_search on products using gin (to_tsvector('indonesian', name));\ncreate index products_description_search on products using gin (to_tsvector('indonesian', description));\n\n```\n\n### Mencari Menggunakan Full-Text Search\n\n```sql\nselect * from products where name @@ to_tsquery('mie');\nselect * from products where description @@ to_tsquery('mie');\n```\n\n### Query Operator\n\n`to_tsquery()` mendukung banyak operator. `\u0026` untuk AND, `|` untuk OR `!` untuk NOT, dan `''''` untuk semua data.\n\n```sql\nselect * from products where name @@ to_tsquery('mie \u0026 ayam');\nselect * from products where name @@ to_tsquery('''ayam bakso''');\n```\n\n### Tipe Data TSVECTOR\n\nKita bisa secara otomatis membuat kolom dengan tipe data `TSVECTOR`. Secara otomatis kolomnya berisi text yang memiliki index Full-Text Search\n\n## Table Relationships\n\nRelasi antar table sering dilakukan di dunia nyata. Biasanya kita akan buat sebuah kolom sebagai referensi ke table lain dimana referensi ini berupa **primary key** di tabel asalnya, ini dinamakan **foreign key**.\n\n### Membuat Table dengan Foreign Key\n\n```sql\ncreate table wishlist\n(\n    id  serial  not null,\n    id_product varchar(10) not null,\n    description text,\n    primary key (id),\n    constraint fk_wishlist_product foreign key (id_product) references products (id)\n);\n```\n\n### Menambah / Menghapus Foreign Key\n\n```sql\n-- Menambah foreign key\nalter table wishlist add constraint fk_wishlist_product foreign key (id_product) references products (id);\n\n-- Menghapus foreign key\nalter table wishlist drop constraint fk_wishlist_product;\n```\n\n| Behavior    | ON DELETE                 | ON UPDATE                 |\n| ----------- | ------------------------- | ------------------------- |\n| RESTRICT    | Ditolak                   | Ditolak                   |\n| CASCADE     | Data akan dihapus         | Data akan ikut diubah     |\n| NO ACTION   | Data dibiarkan            | Data akan dibiarkan       |\n| SET NULL    | Diubah jadi NULL          | Diubah jadi NULL          |\n| SET DEFAULT | Diubah jadi Default Value | Diubah jadi Default Value |\n\n### Mengubah Behavior Menghapus Relasi\n\n```sql\n-- contoh ubah behavior\nalter table wishlist\nadd constraint fk_wishlist_product foreign key (id_product) references products (id)\non delete cascade on update cascade;\n```\n\n## Join\n\nJoin digunakan menseleksi beberapa tabel sekaligus, tetapi perlu menentukan tabel yang mana yang merupakan referensi ke tabel lain (cocok dengan foreign key). Namun `JOIN` ini idealnya **tidak lebih dari 5 tabel** karena mengakibatkan performa menjadi berat dan lambat.\n\n### JOIN Semua Field\n\n```sql\nSELECT * from wishlist join products on wishlist.id_product = products.id;\n```\n\n### JOIN beberapa field\n\n```sql\nSELECT products.id, products.name, wishlist.description from wishlist join products on wishlist.id_product = products.id;\n\n-- memakai alias (AS)\nSELECT p.id, p.name, w.description from wishlist as w join products as p on w.id_product = p.id;\n```\n\n### JOIN Multiple Table\n\n```sql\nselect c.email, p.id, p.name, w.description\nfrom wishlist as w\njoin products as p on w.id_product = p.id\njoin customer as c on c.id = w.id_customer;\n```\n\n## Jenis Relasi Tabel\n\n### One to One Relationship\n\nOne to one artinya sebuah table hanya boleh berelasi ke maksimal 1 data di tabel lain. Misal toko online customer hanya boleh punya 1 wallet.\n\n![Contoh](/img/contoh-one-to-one.png)\n\n### Membuat Table Wallet (dengan unique)\n\n```sql\ncreate table wallet\n(\n    id          serial not null,\n    id_customer int not null,\n    balance     int not null default 0,\n    primary key (id),\n    constraint wallet_customer_unique unique (id_customer),\n    constraint fk_wallet_customer foreign key (id_customer) references customer (id)\n);\n```\n\n### One to Many Relationship\n\nOne to many artinya satu data bisa digunakan lebih dari satu kali di tabel relasinya. One to many tidak ada batasan berapa banyak data digunakan, contohnya relasi tabel categories dan products, dimana satu category bisa digunakan oleh lebih dari satu product.\n\n![Contoh](/img/one-to-many.png)\n\n### Contoh Implementasi One To Many\n\n```sql\n-- membuat table category\ncreate table categories(\n    id  varchar(10) not null,\n    name varchar(100) not null,\n    primary key (id)\n);\n\n-- edit table products and make constraint fk\nalter table products\nadd constraint fk_product_category foreign key (id_category) references categories(id);\n\n-- select join one to many relationship\nselect * from products join categories on products.id_category = categories.id;\n```\n\n### Many to Many Relationship\n\nMany to many adalah relasi dimana ada relasi antara 2 tabel, dimana tabel pertama bisa punyai banyak relasi di tabel kedua, dan tabel kedua pun punya banyak relasi di tabel pertama. Contoh relasi antara produk dan penjualan, setiap produk bisa dijual berkali kali, dan setiap penjualan bisa untuk lebih dari satu produk.\n\nMany to many membutuhkan tabel relasi yang bertugas sebagai jembatan untuk menggabungkan relasi many to many, isi table ini ada id dari tabel pertama dan id tabel kedua. Contoh kasusnya berarti id_product dan id_order.\n\n![Contoh](/img/many-to-many.png)\n\n#### Membuat Tabel Order\n\n```sql\ncreate table orders\n(\n    id          serial      not null,\n    total       int         not null,\n    order_date  timestamp   not null default current_timestamp,\n    primary key (id)\n);\n\n```\n\n#### Membuat Tabel Order Detail\n\n```sql\ncreate table orders_detail\n(\n    id_product  varchar(10) not null,\n    id_order    int         not null,\n    price       int         not null,\n    quantity    int         not null,\n    primary key (id_product, id_order)\n);\n```\n\n#### Membuat Foreign Key\n\n```sql\nalter table orders_detail\nadd constraint fk_orders_detail_product foreign key (id_product) references products (id);\n\nalter table orders_detail\nadd constraint fk_orders_detail_order foreign key (id_order) references orders (id);\n```\n\n## Jenis Join\n\nJoin ada banyak jenis-jenisnya di PostgreSQL antara lain:\n\n- INNER JOIN\n- LEFT JOIN\n- RIGHT JOIN\n- FULL JOIN\n\n### Inner Join\n\n![Contoh](/img/img_inner_join.png)\n\nInner join hanya menampilkan data yang memiliki relasi di tabel lainnya, jika tidak memiliki relasi maka tidak akan ditampilkan. Inner join ini dipakai secara default di PostgreSQL ketika kita menulis `join` di sql.\n\n```sql\nselect * from categories\ninner join products on products.id_category = categories.id;\n```\n\n### Left Join\n\n![Contoh](/img/img_left_join.png)\n\nLeft join mirip seperti inner join, hanya saja semua data di tabel pertama akan diambil, jika ada yang tak memiliki relasi di tabel kedua, maka hasilnya `NULL`.\n\n```sql\nselect * from categories\nleft join products on products.id_category = categories.id;\n```\n\n### Right Join\n\n![Contoh](/img/img_right_join.png)\n\nRight join mirip seperti inner join, hanya saja semua data di tabel kedua akan diambil, jika ada yang tak memiliki relasi di tabel pertama, maka hasilnya `NULL`.\n\n```sql\nselect * from categories\nright join products on products.id_category = categories.id;\n```\n\n### Full Join\n\n![Contoh](/img/img_full_outer_join.png)\n\nFull join adalah join dimana semua data di tabel pertama dan kedua akan ditampilkan, jika tidak ada join maka hasilnya akan berisi data null.\n\n```sql\nselect * from categories\nfull join products on products.id_category = categories.id;\n```\n\n## Subqueries\n\n### Subquery di WHERE\n\nSubquery di WHERE\nPostgreSQL mendukung pencarian data menggunakan WHERE dari hasil SELECT query, fitur ini dinamakan subquery. Contoh ketika kita ingin mencari products yang harganya diatas rata-rata, artinya melakukan `SELECT` denagn `WHERE price \u003e harga rata`, dimana harga rata-rata perlu kita hitung menggunakan **query SELECT** lainnya menggunakan **aggregate function** `AVG`.\n\n```sql\nselect * from products where price \u003e (select avg(price) from products);\n```\n\n### Subquery di FROM\n\nSubquery bisa dilakukan di `FROM` clause, Misal ingin mencari data dari hasil query `SELECT` juga bisa dilakukan di PostgreSQL.\n\n```sql\nselect max(price)\nfrom (select products.price as price\nfrom categories join products on products.id_category = categories.id) as contoh;\n```\n\n## Set Operator\n\nPostgreSQL mendukung operator set, yaitu operasi antara hasil dua `SELECT` query. Antara lain:\n\n- UNION\n- UNION ALL\n- INTERSECT\n- EXCEPT\n\n### UNION\n\nUnion adalah operasi menggabungkan dua buah `SELECT` query, dimana jika terdapat data yang duplikat, data duplikatnya dihapus dari hasil query.\n\n```sql\nselect distinct email from customer\nunion select distinct email from guestbooks;\n```\n\n### UNION ALL\n\nUnion all adalah operasi yang sama dengan `UNION`, namun data duplikat tetap akan ditampilkan di hasil querynya.\n\n```sql\nselect distinct email from customer\nunion all select distinct email from guestbooks;\n\n-- dikombinasikan dengan subquery\nselect email, count(email)\nfrom (select email from customer union all\nselect email from guestbooks) as contoh\ngroup by email;\n```\n\n### INTERSECT\n\nIntersect adalah operasi menggabungkan dua query, namun yang diambil hanya data yang terdapat pada hasil query pertama dan kedua (irisan). Data yang tidak hanya ada di salah satu query, akan dihapus di hasil operasi `INTERSECT`. Datanya muncul tidak dalam keadaan duplikat.\n\n```sql\nselect distinct email from customer\nintersect\nselect distinct email from guestbooks;\n```\n\n### EXCEPT\n\nExcept adalah operasi dimana query pertama akan dihilangkan oleh query kedua, artinya jika ada data di query pertama yang sama dengan data yang ada di query kedua, maka data tersebut akan dihpuas dari hasil query `EXCEPT`.\n\n```sql\nselect distinct email from customer\nexcept\nselect distinct email from guestbooks;\n```\n\n## Database Transaction\n\nDatabase Transaction adalah fitur di DBMS dimana kita bisa melakukan beberapa perintah dan dianggap menjadi sebuah kesatuan perintah yang disebut _transaction_. Jika satu proses gagal, maka perintah perintah yang lain akan dibatalkan, dan jika sukses, maka semua perintah akan dipastikan sukses.\n\nTransaction di PostgreSQL\n\n| Perintah          | Keterangan                                                                                                    |\n| ----------------- | ------------------------------------------------------------------------------------------------------------- |\n| START TRANSACTION | Memulai proses transaksi, proses selanjutnya akan dianggap transaksi sampai perintah `COMMIT` atau `ROLLBACK` |\n| COMMIT            | Menyimpan secara permanen seluruh proses transaksi                                                            |\n| ROLLBACK          | Membatalkan secara permanen seluruh proses transaksi                                                          |\n\n\u003e [!WARNING]\n\u003e Perintah DDL (Data Definition Language) tidak bisa menggunakan fitur transaction, DDL adalah perintah-perintah yang digunakan untuk merubah struktur, seperti membuat tabel, menambah kolom, menghapus tabel, menghapus database dan sejenisnya. Transaction hanya bisa dilakukan pada perintah DML (Data Manipulation Language), seperti Operasi `INSERT`, `UPDATE`, dan `DELETE`.\n\n```sql\n-- commit\nstart transaction ;\n\ninsert into guestbooks (email, title, content)\nvalues ('transaction@pzn.com', 'transaction', 'transaction');\n\ninsert into guestbooks (email, title, content)\nvalues ('transaction@pzn.com', 'transaction', 'transaction 2');\n\ninsert into guestbooks (email, title, content)\nvalues ('transaction@pzn.com', 'transaction', 'transaction 3');\n\ninsert into guestbooks (email, title, content)\nvalues ('transaction@pzn.com', 'transaction', 'transaction 4');\n\ninsert into guestbooks (email, title, content)\nvalues ('transaction@pzn.com', 'transaction', 'transaction 5');\n\ncommit;\n\n-- rollback\nstart transaction ;\n\ninsert into guestbooks (email, title, content)\nvalues ('transaction@pzn.com', 'transaction', 'rollback');\n\ninsert into guestbooks (email, title, content)\nvalues ('transaction@pzn.com', 'transaction', 'rollback 2');\n\ninsert into guestbooks (email, title, content)\nvalues ('transaction@pzn.com', 'transaction', 'rollback 3');\n\ninsert into guestbooks (email, title, content)\nvalues ('transaction@pzn.com', 'transaction', 'rollback 4');\n\ninsert into guestbooks (email, title, content)\nvalues ('transaction@pzn.com', 'transaction', 'rollback 5');\n\nrollback;\n```\n\n## Locking\n\nLocking adalah proses mengunci data di DBMS. Proses mengunci data sangat penting, salah satunya agar data benar benar terjamin konsistensinya. Karena pada kenyataannya, aplikasi yang akan dibuat pasti digunakan oleh banyak pengguna, dan banyak pengguna bisa saja akan mengakses data yang sama, jika tidak ada proses locking, bisa dipastikan akan terjadi **RACE CONDITION**, yaitu proses balapan ketika mengubah data yang sama.\n\nContoh ketika belanja di toko online, kita akan balapan membeli barang yang sama, jika data tidak terjaga, bisa jadi kita salah update stock karena pada saat yang bersamaan banyak yang melakukan perubahan stock barang.\n\n### Locking Record\n\nSaat kita melakukan proses `TRANSACTION`, lalu kita melakukan proses perubahan data, data yang kita ubah tersebut akan secara otomatis di LOCK. Hal ini membuat proses **TRANSACTION** menjadi sangat aman. Oleh karena itu, sangat disarankan untuk selalu menggunakan fitur `TRANSACTION` ketika memanipulasi data di database, terutama ketika perintah manipulasinya lebih dari satu kali. Locking membuat sebuah proses perubahan yang dilakukan oleh pihak lain akan diminta untuk menunggu. Data akan dilocak sampai kita melakukan commit atau rollback transaksi tersebut.\n\n```sql\n-- di client X\nstart transaction ;\n\nupdate products\nset description = 'Mie ayam original enak'\nwhere id = 'P0001';\n\nselect * from products where id = 'P0001';\n\ncommit;\n\n-- di client Y (akan menunggu prosesnya sebelum melakukan commit atau rollback)\nupdate products set quantity = 200 where id = 'P0001';\n\n```\n\n### Locking Record Manual\n\nSelain secara otomatis, kadang saat kita membuat aplikasi, kita juga sering melakukan `SELECT` query terlebih dahulu sebelum melakukan proses `UPDATE` misalnya. Cara locking sebuah data secara manual, kita bisa tambahkan perintah `FOR UPDATE` di belakang query `SELECT`. Saat kita lock record yang kita select, maka jika ada proses lain akan melakukan `UPDATE, DELETE, SELECT FOR UPDATE` lagi maka proses lain diminta menunggu sampai kita selesai `COMMIT` atau `ROLLBACK` transaction.\n\n```sql\n-- di client X\nstart transaction ;\n\nselect * from products where id = 'P0001' for update;\n\nrollback;\n\n-- di client Y (Menunggu proses client X commit atau rollback)\nupdate products set price = 30000 where id = 'P0001';\n```\n\n### Deadlock\n\nDeadlock adalah situasi 2 proses yang saling menuggu satu sama lain, namun data yang ditunggu dua-duanya dilock oleh proses lainnya, sehingga proses menunggu ini tidak akan pernah selesai.\n\nContoh\n\n- Proses 1 melakukan SELECT FOR UPDATE untuk data 001\n- Proses 2 melakukan SELECT FOR UPDATE untuk data 002\n- Proses 1 melakukan SELECT FOR UPDATE untuk data 002, diminta menunggu karena dilock oleh proses 2\n- Proses 2 melakukan SELECT FOR UPDATE untuk data 001, diminta menunggu karena dilock oleh proses 1\n- Akhirnya proses 1 dan proses 2 saling menuggu\n- Deadlock terjadi\n\n```sql\nstart transaction ; -- di client 1 \u0026 client 2\n\nselect * from products where id = 'P0001' for update;  -- di client 1\n\nselect * from products where id = 'P0002' for update;  -- di client 2\n\nselect * from products where id = 'P0002' for update;  -- di client 1\n\n-- anggap proses ini dilakukan secara bersamaan, sebelum rollback atau commit. Maka akan terjadi Deadlock, namun PostgreSQL akan mendeteksi Deadlock dan menghentikan salah satu proses\nselect * from products where id = 'P0001' for update; -- di client 2 (dibatalkan)\n\nrollback; -- di client 1 \u0026 2\n```\n\nDeadlock error:\n![Deadlock Error dan Locking dilepas](/img/deadlock%20error.png)\n\n## Schema\n\nDi awal kita ibaratkan bahwa database adalah sebuah folder, dan tabel adalah file-filenya. Di PostgreSQL terdapat fitur bernama **Schema**. Anggap saja folder di dalam database, sebenarnya ketika membuat database, secara tidak sadar kita menyimpan semua tabel kita di _schema public_. Kita bisa membuat schema lain, dan pada schema yang berbeda, kita bisa membuat tabel dengan nama yang sama.\n\nKetika membuat database, secara otomatis terdapat schema bernama public, dan ketika membuat table, secara otomatis kita akan membuat table tersebut berada di **schema public**.\n\n### Melihat Schema Saat Ini\n\n```sql\nselect current_schema();\n\n-- or\n\nshow search_path;\n```\n\n### Membuat dan Menghapus Schema\n\n```sql\n-- membuat\ncreate schema contoh;\n\n-- menghapus\ndrop schema contoh;\n```\n\n### Pindah Schema\n\n```sql\nset search_path to contoh;\n\nshow search_path;\n\nselect current_schema();\n```\n\n### Membuat Table di Schema\n\nSatt kita membuat table, secara otomatis PostgreSQL akan membuat table di schema yang sedang kita pilih, jika kita ingin menentukan schema secara manual tanpa menggunakan schema yang sedang dipilih, kita bisa menambahkan prefix nama schema di awal nama tablenya.\n\nMisal namaschema namatable\n\nTermasuk jika ingin melakukan operasi DML ke table, bisa gunakan prefix namaschema.\n\n```sql\n-- membuat tabel di schema contoh\ncreate table contoh.products\n(\n    id serial not null,\n    name varchar(100) not null,\n    primary key (id)\n);\n\n-- memasukkan data tabel di schema contoh\ninsert into contoh.products(name)\nvalues ('iPhone'),\n('Play Station');\n\n-- seleksi tabel di schema contoh\nselect * from contoh.products;\n```\n\n## User Management\n\n### Root User\n\nSecara default, PostgreSQL membuat user utama sebagai super administrator, namun **best practicenya** saat menjalankan PostgreSQL dengan aplikasi yang kita buat, sangat disarankan tidak menggunakan user utama. Lebih baik buat user khusus untuk tiap aplikasi, bahkan bisa batasi dengan hak akses user.\n\nMisalnya hanya bisa `SELECT`, dan tidak boleh melakukan `INSERT`, `UPDATE` atau `DELETE`.\n\n### Membuat / Menghapus User\n\n```sql\n-- membuat\ncreate role nama;\ncreate role bagus;\n\n-- menghapus\ndrop role nama;\ndrop role bagus;\n```\n\n### Menambah / Mengubah Option Role Ke User\n\nPostgreSQL Documentation Role:\n\n- [Create Role Docs.](https://www.postgresql.org/docs/15/sql-createrole.html)\n- [Alter Role Docs.](https://www.postgresql.org/docs/15/sql-alterrole.html)\n\n```sql\ncreate role budi login password 'rahasia';\n\nalter role bagus login password 'rahasia';\n\n-- Melihat role\nSELECT rolname FROM pg_roles;\n```\n\n### Daftar atau Hapus Hak Akses\n\nDokumentasi Hak Akses:\n\n- [GRANT (Daftar Hak Akses)](https://www.postgresql.org/docs/15/sql-grant.html)\n- [REVOKE (Hapus Hak Akses)](https://www.postgresql.org/docs/15/sql-revoke.html)\n\n```sql\ngrant insert, update, select on all tables in schema public to bagus;\ngrant insert, update, select on customer to budi;\n\n-- grant sequence\ngrant usage, select, update on guestbooks_id_seq to bagus;\n\nrevoke insert, update, select on customer from budi;\n```\n\n## Backup Database\n\nSaat membuat aplikasi menggunakan database, ada baiknya kita selalu melakukan backup data secara reguler, Untungnya PostgreSQL mendukung proses backup database. Untuk melakukan backup, kita tidak menggunakan perintah SQL, melainkan PostgreSQL menyediakan sebuah aplikasi khusus untuk backup db, namanya `pg_dump` \u003chttps://www.postgresql.org/docs/15/app-pgdump.html\u003e.\n\n```sql\npg_dump --host=localhost --port=5432 --dbname=belajar --username=user --format=plain --file=/Users/bagus/backup.sql\n```\n\n## Restore Database\n\nSelain backup, PostgreSQL mendukung kita untuk bisa melakukan proses restore data dari file hasil backup. untuk restore bisa menggunakan aplikasi `psql`.\n\n```sql\npsql --host=localhost --port=5432 --dbname=belajar_restore --username=user --file=Downloads/backup.sql\n```\n\n## Referensi\n\n- YouTube Programmer Zaman Now\n- w3schools.com (Gambar Join)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbagusperdanay7%2Fpostgresql-notes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbagusperdanay7%2Fpostgresql-notes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbagusperdanay7%2Fpostgresql-notes/lists"}