Kebutuhan laporan tidak pernah diam: bulan ini laporan per kategori cukup dengan total unit dan total nilai, bulan depan manajemen minta kolom tanggal transaksi terakhir. Definisi view kini harus menyesuaikan — dan di sinilah banyak pemula tersandung, karena PostgreSQL memperlakukan kolom view sebagai kontrak: query pemakai, laporan aplikasi, bahkan view lain sudah ditulis dengan nama dan urutan kolom yang ada sekarang. Mengubah view dengan sembarangan bisa memutus kontrak itu secara diam-diam. Chapter ini membahas dua keluarga perintah pengubah view — CREATE OR REPLACE VIEW untuk isi query dan ALTER VIEW untuk identitas — beserta batas ketat yang membedakan perubahan yang diizinkan dari yang ditolak keras oleh server.
Domain Latihan yang Sama #
Chapter ini melanjutkan domain Toko Maju Jaya dari chapter Membuat View
: tabel produk, pelanggan, dan penjualan dengan data yang sama. Karena setiap chapter dijalankan di database latihan masing-masing, file setup berikut membuat ulang ketiga tabel itu dari nol — sehingga contoh-contoh di chapter ini bisa diuji sendiri tanpa prasyarat:
-- Domain latihan section View dan Materialized View:
-- katalog produk, pelanggan, dan transaksi Toko Maju Jaya.
CREATE TABLE produk (
id integer PRIMARY KEY,
nama text NOT NULL,
kategori text NOT NULL,
harga numeric(10,2) NOT NULL,
stok integer NOT NULL
);
CREATE TABLE pelanggan (
id integer PRIMARY KEY,
nama text NOT NULL,
kota text NOT NULL
);
CREATE TABLE penjualan (
id integer PRIMARY KEY,
tanggal date NOT NULL,
produk_id integer NOT NULL REFERENCES produk(id),
pelanggan_id integer NOT NULL REFERENCES pelanggan(id),
jumlah integer NOT NULL
);
INSERT INTO produk (id, nama, kategori, harga, stok) VALUES
(1, 'Kopi Gayo', 'Kopi', 85000.00, 40),
(2, 'Kopi Toraja', 'Kopi', 90000.00, 25),
(3, 'Teh Melati', 'Teh', 35000.00, 100),
(4, 'Teh Hijau', 'Teh', 40000.00, 60),
(5, 'Gula Merah', 'Gula', 15000.00, 200),
(6, 'Gula Putih', 'Gula', 16000.00, 150),
(7, 'Kopi Lampung', 'Kopi', 78000.00, 0);
INSERT INTO pelanggan (id, nama, kota) VALUES
(1, 'Budi Santoso', 'Jakarta'),
(2, 'Siti Aminah', 'Bandung'),
(3, 'Andi Wijaya', 'Surabaya'),
(4, 'Dewi Lestari', 'Yogyakarta'),
(5, 'Rina Marlina', 'Medan');
INSERT INTO penjualan (id, tanggal, produk_id, pelanggan_id, jumlah) VALUES
( 1, DATE '2026-01-05', 1, 1, 10),
( 2, DATE '2026-01-08', 3, 2, 25),
( 3, DATE '2026-01-12', 5, 3, 40),
( 4, DATE '2026-01-15', 2, 1, 8),
( 5, DATE '2026-01-20', 4, 4, 15),
( 6, DATE '2026-01-22', 1, 2, 12),
( 7, DATE '2026-02-02', 3, 5, 20),
( 8, DATE '2026-02-05', 6, 3, 30),
( 9, DATE '2026-02-10', 2, 4, 6),
(10, DATE '2026-02-14', 4, 1, 18);
SELECT id, nama, kategori, harga, stok FROM produk ORDER BY id;
SELECT id, nama, kota FROM pelanggan ORDER BY id;
SELECT id, tanggal, produk_id, pelanggan_id, jumlah FROM penjualan ORDER BY id;Output yang Dihasilkan:
CREATE TABLE
CREATE TABLE
CREATE TABLE
INSERT 0 7
INSERT 0 5
INSERT 0 10
id | nama | kategori | harga | stok
----+--------------+----------+----------+------
1 | Kopi Gayo | Kopi | 85000.00 | 40
2 | Kopi Toraja | Kopi | 90000.00 | 25
3 | Teh Melati | Teh | 35000.00 | 100
4 | Teh Hijau | Teh | 40000.00 | 60
5 | Gula Merah | Gula | 15000.00 | 200
6 | Gula Putih | Gula | 16000.00 | 150
7 | Kopi Lampung | Kopi | 78000.00 | 0
(7 rows)
id | nama | kota
----+--------------+------------
1 | Budi Santoso | Jakarta
2 | Siti Aminah | Bandung
3 | Andi Wijaya | Surabaya
4 | Dewi Lestari | Yogyakarta
5 | Rina Marlina | Medan
(5 rows)
id | tanggal | produk_id | pelanggan_id | jumlah
----+------------+-----------+--------------+--------
1 | 2026-01-05 | 1 | 1 | 10
2 | 2026-01-08 | 3 | 2 | 25
3 | 2026-01-12 | 5 | 3 | 40
4 | 2026-01-15 | 2 | 1 | 8
5 | 2026-01-20 | 4 | 4 | 15
6 | 2026-01-22 | 1 | 2 | 12
7 | 2026-02-02 | 3 | 5 | 20
8 | 2026-02-05 | 6 | 3 | 30
9 | 2026-02-10 | 2 | 4 | 6
10 | 2026-02-14 | 4 | 1 | 18
(10 rows)Dua Jalan Mengubah View #
Kesalahpahaman pertama yang perlu diluruskan: ALTER VIEW tidak bisa mengubah isi query. PostgreSQL tidak menyediakan sintaks ALTER VIEW ... AS SELECT .... Isi query hanya bisa diganti lewat CREATE OR REPLACE VIEW, sementara ALTER VIEW mengurus identitas view — namanya, nama kolomnya, schema, dan pemiliknya. Tabel berikut memetakan kebutuhan ke perintahnya:
| Yang ingin diubah | Perintah | Catatan |
|---|---|---|
| Isi query (tubuh view) | CREATE OR REPLACE VIEW | Kolom lama wajib dipertahankan; kolom baru hanya boleh di ujung |
| Nama view | ALTER VIEW ... RENAME TO | Nama lama langsung hilang |
| Nama kolom | ALTER VIEW ... RENAME COLUMN | Nama baru diteruskan ke view pemakai |
| Hapus kolom / ubah tipe / ubah urutan | DROP VIEW + CREATE VIEW ulang | Tidak ada jalan pintas — kontrak kolom dianggap putus |
| Schema, pemilik, opsi view | ALTER VIEW ... SET SCHEMA / OWNER TO / SET | Administratif, tidak menyentuh query |
Mengapa CREATE OR REPLACE VIEW lebih dipilih daripada menjatuhkan lalu membuat ulang? Karena DROP VIEW memutus semua objek yang bergantung pada view itu — view lain, izin akses (GRANT), dan komentar ikut hilang. CREATE OR REPLACE VIEW menimpa definisi di tempatnya, sehingga seluruh rantai dependensi tetap utuh.
CREATE OR REPLACE VIEW: Menambah Kolom di Ujung #
Kita mulai dari posisi bersih: ringkasan_penjualan versi empat kolom seperti chapter sebelumnya. Manajemen kemudian meminta kolom transaksi_terakhir — tanggal penjualan paling baru per kategori. Karena kebutuhan itu murni penambahan kolom di posisi terakhir, CREATE OR REPLACE VIEW menerimanya:
-- CREATE OR REPLACE VIEW menimpa definisi lama tanpa menjatuhkan objeknya:
-- kolom lama dipertahankan, kolom baru BOLEH ditambahkan di ujung.
CREATE VIEW ringkasan_penjualan AS
SELECT pr.kategori,
count(*) AS transaksi,
sum(pe.jumlah) AS total_unit,
sum(pe.jumlah * pr.harga) AS total_nilai
FROM penjualan pe
JOIN produk pr ON pr.id = pe.produk_id
GROUP BY pr.kategori;
SELECT kategori, transaksi, total_unit, total_nilai
FROM ringkasan_penjualan
ORDER BY kategori;
-- Definisi baru: empat kolom yang sama, urutan dan tipe yang sama,
-- ditambah satu kolom baru DI POSISI TERAKHIR.
CREATE OR REPLACE VIEW ringkasan_penjualan AS
SELECT pr.kategori,
count(*) AS transaksi,
sum(pe.jumlah) AS total_unit,
sum(pe.jumlah * pr.harga) AS total_nilai,
max(pe.tanggal) AS transaksi_terakhir
FROM penjualan pe
JOIN produk pr ON pr.id = pe.produk_id
GROUP BY pr.kategori;
SELECT kategori, transaksi, total_unit, total_nilai, transaksi_terakhir
FROM ringkasan_penjualan
ORDER BY kategori;Output yang Dihasilkan:
CREATE VIEW
kategori | transaksi | total_unit | total_nilai
----------+-----------+------------+-------------
Gula | 2 | 70 | 1080000.00
Kopi | 4 | 36 | 3130000.00
Teh | 4 | 78 | 2895000.00
(3 rows)
CREATE VIEW
kategori | transaksi | total_unit | total_nilai | transaksi_terakhir
----------+-----------+------------+-------------+--------------------
Gula | 2 | 70 | 1080000.00 | 2026-02-05
Kopi | 4 | 36 | 3130000.00 | 2026-02-10
Teh | 4 | 78 | 2895000.00 | 2026-02-14
(3 rows)Mari kita bedah aturan mainnya dari contoh di atas:
CREATE VIEW ringkasan_penjualan AS ...(statement pertama) — membuat versi awal empat kolom; outputCREATE VIEWmenandai objek baru tercipta.CREATE OR REPLACE VIEW ... AS ...(statement kedua) — menimpa definisi dengan versi lima kolom. Output-nya jugaCREATE VIEW, bukanALTER VIEW: server memperlakukan penggantian ini sebagai pembuatan ulang definisi di objek yang sama.- Empat kolom pertama identik — nama (
kategori,transaksi,total_unit,total_nilai), tipe, dan urutannya sama persis dengan versi lama. Hanya kolom kelima,max(pe.tanggal) AS transaksi_terakhir, yang baru — dan posisinya di ujung. - Query ketiga — memilih kelima kolom;
transaksi_terakhirterisi tanggal transaksi terakhir tiap kategori, misalnya2026-02-14untuk Teh dan2026-02-10untuk Kopi.
Perhatikan pula bahwa CREATE VIEW ringkasan_penjualan AS ... biasa — tanpa OR REPLACE — di atas view yang sudah ada akan gagal dengan error relation "ringkasan_penjualan" already exists. Kata kunci OR REPLACE adalah satu-satunya cara mengganti definisi tanpa menjatuhkan objeknya.
Batas OR REPLACE: Nama, Urutan, dan Tipe Kolom #
Sekarang bagian yang ditolak keras. Aturan lengkapnya: daftar kolom definisi baru harus cocok dengan daftar kolom lama satu per satu — nama sama, tipe sama, urutan sama — dan hanya boleh lebih panjang, tidak boleh lebih pendek atau berbeda bentuk. Tiga pelanggaran paling umum kita uji langsung; dua yang pertama sebagai contoh error nyata:
-- Mencoba mengubah nama kolom di tengah daftar lewat CREATE OR REPLACE VIEW:
-- kolom kedua "transaksi" diganti nama menjadi "jumlah_transaksi".
-- PostgreSQL MENOLAK karena nama kolom adalah kontrak view --
-- pemakai dan view lain sudah menulis query dengan nama lama.
CREATE OR REPLACE VIEW ringkasan_penjualan AS
SELECT pr.kategori,
count(*) AS jumlah_transaksi,
sum(pe.jumlah) AS total_unit,
sum(pe.jumlah * pr.harga) AS total_nilai,
max(pe.tanggal) AS transaksi_terakhir
FROM penjualan pe
JOIN produk pr ON pr.id = pe.produk_id
GROUP BY pr.kategori;Output yang Dihasilkan:
psql:or-replace-error-nama.sql:13: ERROR: cannot change name of view column "transaksi" to "jumlah_transaksi"
HINT: Use ALTER VIEW ... RENAME COLUMN ... to change name of view column instead.-- Mencoba MENGHAPUS kolom lewat CREATE OR REPLACE VIEW:
-- definisi baru hanya berisi empat kolom, tanpa transaksi_terakhir.
-- PostgreSQL menolak: menghapus kolom dari view harus lewat
-- DROP VIEW lalu CREATE VIEW ulang.
CREATE OR REPLACE VIEW ringkasan_penjualan AS
SELECT pr.kategori,
count(*) AS transaksi,
sum(pe.jumlah) AS total_unit,
sum(pe.jumlah * pr.harga) AS total_nilai
FROM penjualan pe
JOIN produk pr ON pr.id = pe.produk_id
GROUP BY pr.kategori;Output yang Dihasilkan:
psql:or-replace-error-kolom.sql:12: ERROR: cannot drop columns from viewDua error itu berasal dari dua pelanggaran berbeda: mengganti nama kolom di tengah daftar menghasilkan cannot change name of view column "transaksi" to "jumlah_transaksi" (lengkap dengan HINT yang menunjuk ke ALTER VIEW ... RENAME COLUMN — jalan yang benar untuk kebutuhan itu), sedangkan memperpendek daftar kolom menghasilkan cannot drop columns from view. Pelanggaran ketiga, mengubah tipe kolom (misalnya mengganti sum(pe.jumlah * pr.harga) menjadi ::text), ditolak dengan error cannot change data type of view column "total_nilai" from numeric to text. Ketiganya bermuara pada alasan yang sama:
ALTER VIEW: Mengganti Nama View dan Kolomnya #
Untuk urusan nama, ALTER VIEW adalah alat yang benar. RENAME TO mengganti nama view itu sendiri; RENAME COLUMN mengganti nama salah satu kolomnya tanpa menyentuh query:
-- ALTER VIEW mengurus identitas view, bukan isi query-nya.
-- Mengganti nama view:
ALTER VIEW ringkasan_penjualan RENAME TO ringkasan_kategori;
-- Nama lama hilang; nama baru langsung terpakai.
SELECT kategori, transaksi
FROM ringkasan_kategori
ORDER BY kategori;
-- Mengganti nama satu kolom view:
ALTER VIEW ringkasan_kategori RENAME COLUMN transaksi TO jumlah_transaksi;
SELECT kategori, jumlah_transaksi, total_nilai
FROM ringkasan_kategori
ORDER BY kategori;Output yang Dihasilkan:
ALTER VIEW
kategori | transaksi
----------+-----------
Gula | 2
Kopi | 4
Teh | 4
(3 rows)
ALTER VIEW
kategori | jumlah_transaksi | total_nilai
----------+------------------+-------------
Gula | 2 | 1080000.00
Kopi | 4 | 3130000.00
Teh | 4 | 2895000.00
(3 rows)Setelah RENAME TO, view bernama ringkasan_kategori; query yang masih menulis ringkasan_penjualan gagal dengan error relation "ringkasan_penjualan" does not exist. Setelah RENAME COLUMN, kolom kedua bernama jumlah_transaksi — nama lama transaksi tidak lagi dikenal. Keduanya berjalan tanpa menyentuh isi query: tubuh view tetap query join-agregat yang sama; yang berubah hanya label di level katalog. Berbeda dengan OR REPLACE yang menolak perubahan nama kolom, RENAME COLUMN justru dirancang untuk itu — perbedaan dua perintah ini sering membingungkan pemula: OR REPLACE mengganti isi, RENAME mengganti nama.
View di Atas View: Rantai Dependensi #
View boleh membaca view lain, dan praktik ini umum di laporan bertingkat: ringkasan_kategori sebagai lapisan dasar, lalu view tipis di atasnya yang menyaring atau memilih ulang kolom. Kita buat laporan_besar yang hanya menampilkan kategori dengan nilai jual di atas satu setengah juta rupiah:
-- Rantai dependensi: view yang membaca view lain.
CREATE VIEW laporan_besar AS
SELECT kategori, total_nilai
FROM ringkasan_kategori
WHERE total_nilai >= 1500000;
SELECT kategori, total_nilai
FROM laporan_besar
ORDER BY kategori;
-- Ganti nama kolom pada view yang DIBACA ...
ALTER VIEW ringkasan_kategori RENAME COLUMN total_nilai TO nilai_total;
-- ... dan view pemakai tetap hidup: PostgreSQL menulis ulang
-- definisinya secara otomatis agar memakai nama yang baru.
SELECT kategori, total_nilai
FROM laporan_besar
ORDER BY kategori;
\d+ laporan_besarOutput yang Dihasilkan:
CREATE VIEW
kategori | total_nilai
----------+-------------
Kopi | 3130000.00
Teh | 2895000.00
(2 rows)
ALTER VIEW
kategori | total_nilai
----------+-------------
Kopi | 3130000.00
Teh | 2895000.00
(2 rows)
View "public.laporan_besar"
Column | Type | Collation | Nullable | Default | Storage | Description
-------------+---------+-----------+----------+---------+----------+-------------
kategori | text | | | | extended |
total_nilai | numeric | | | | main |
View definition:
SELECT kategori,
nilai_total AS total_nilai
FROM ringkasan_kategori
WHERE nilai_total >= 1500000::numeric;Urutan kejadian di file tersebut adalah pelajaran utamanya. laporan_besar tercipta dengan membaca kolom total_nilai milik ringkasan_kategori. ALTER VIEW ringkasan_kategori RENAME COLUMN total_nilai TO nilai_total kemudian mengganti nama kolom di lapisan bawah — dan query SELECT kategori, total_nilai FROM laporan_besar tetap berhasil. Bagian View definition: dari \d+ laporan_besar memperlihatkan alasannya: definisi tersimpannya kini berbunyi SELECT kategori, nilai_total AS total_nilai FROM ringkasan_kategori WHERE nilai_total >= 1500000::numeric — PostgreSQL melacak dependensi sampai ke tingkat kolom dan menulis ulang pohon query semua view pemakai saat nama berubah. Perilaku yang sama berlaku untuk kolom tabel dasar: ALTER TABLE produk RENAME COLUMN harga TO harga_satuan juga diteruskan otomatis ke setiap view yang membacanya. Ini bukti terkuat bahwa yang disimpan bukan teks query mentah, melainkan pohon query dengan referensi internal.
Definisi view kini bisa tumbuh (kolom baru di ujung), berganti nama (view maupun kolom), dan rantai view-atas-view tetap terpelihara secara otomatis. Satu kartu tersisa di deck: bagaimana menghapus view dengan benar — kapan IF EXISTS menyelamatkan script, apa yang terjadi saat view lain masih bergantung, dan kapan CASCADE menjadi pilihan yang aman versus berbahaya. Itu seluruh isi chapter berikutnya.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
alter-rename.sql
Unduh berkas-- ALTER VIEW mengurus identitas view, bukan isi query-nya.
-- Mengganti nama view:
ALTER VIEW ringkasan_penjualan RENAME TO ringkasan_kategori;
-- Nama lama hilang; nama baru langsung terpakai.
SELECT kategori, transaksi
FROM ringkasan_kategori
ORDER BY kategori;
-- Mengganti nama satu kolom view:
ALTER VIEW ringkasan_kategori RENAME COLUMN transaksi TO jumlah_transaksi;
SELECT kategori, jumlah_transaksi, total_nilai
FROM ringkasan_kategori
ORDER BY kategori;
buat-tabel.sql
Unduh berkas-- Domain latihan section View dan Materialized View:
-- katalog produk, pelanggan, dan transaksi Toko Maju Jaya.
CREATE TABLE produk (
id integer PRIMARY KEY,
nama text NOT NULL,
kategori text NOT NULL,
harga numeric(10,2) NOT NULL,
stok integer NOT NULL
);
CREATE TABLE pelanggan (
id integer PRIMARY KEY,
nama text NOT NULL,
kota text NOT NULL
);
CREATE TABLE penjualan (
id integer PRIMARY KEY,
tanggal date NOT NULL,
produk_id integer NOT NULL REFERENCES produk(id),
pelanggan_id integer NOT NULL REFERENCES pelanggan(id),
jumlah integer NOT NULL
);
INSERT INTO produk (id, nama, kategori, harga, stok) VALUES
(1, 'Kopi Gayo', 'Kopi', 85000.00, 40),
(2, 'Kopi Toraja', 'Kopi', 90000.00, 25),
(3, 'Teh Melati', 'Teh', 35000.00, 100),
(4, 'Teh Hijau', 'Teh', 40000.00, 60),
(5, 'Gula Merah', 'Gula', 15000.00, 200),
(6, 'Gula Putih', 'Gula', 16000.00, 150),
(7, 'Kopi Lampung', 'Kopi', 78000.00, 0);
INSERT INTO pelanggan (id, nama, kota) VALUES
(1, 'Budi Santoso', 'Jakarta'),
(2, 'Siti Aminah', 'Bandung'),
(3, 'Andi Wijaya', 'Surabaya'),
(4, 'Dewi Lestari', 'Yogyakarta'),
(5, 'Rina Marlina', 'Medan');
INSERT INTO penjualan (id, tanggal, produk_id, pelanggan_id, jumlah) VALUES
( 1, DATE '2026-01-05', 1, 1, 10),
( 2, DATE '2026-01-08', 3, 2, 25),
( 3, DATE '2026-01-12', 5, 3, 40),
( 4, DATE '2026-01-15', 2, 1, 8),
( 5, DATE '2026-01-20', 4, 4, 15),
( 6, DATE '2026-01-22', 1, 2, 12),
( 7, DATE '2026-02-02', 3, 5, 20),
( 8, DATE '2026-02-05', 6, 3, 30),
( 9, DATE '2026-02-10', 2, 4, 6),
(10, DATE '2026-02-14', 4, 1, 18);
SELECT id, nama, kategori, harga, stok FROM produk ORDER BY id;
SELECT id, nama, kota FROM pelanggan ORDER BY id;
SELECT id, tanggal, produk_id, pelanggan_id, jumlah FROM penjualan ORDER BY id;
or-replace-append.sql
Unduh berkas-- CREATE OR REPLACE VIEW menimpa definisi lama tanpa menjatuhkan objeknya:
-- kolom lama dipertahankan, kolom baru BOLEH ditambahkan di ujung.
CREATE VIEW ringkasan_penjualan AS
SELECT pr.kategori,
count(*) AS transaksi,
sum(pe.jumlah) AS total_unit,
sum(pe.jumlah * pr.harga) AS total_nilai
FROM penjualan pe
JOIN produk pr ON pr.id = pe.produk_id
GROUP BY pr.kategori;
SELECT kategori, transaksi, total_unit, total_nilai
FROM ringkasan_penjualan
ORDER BY kategori;
-- Definisi baru: empat kolom yang sama, urutan dan tipe yang sama,
-- ditambah satu kolom baru DI POSISI TERAKHIR.
CREATE OR REPLACE VIEW ringkasan_penjualan AS
SELECT pr.kategori,
count(*) AS transaksi,
sum(pe.jumlah) AS total_unit,
sum(pe.jumlah * pr.harga) AS total_nilai,
max(pe.tanggal) AS transaksi_terakhir
FROM penjualan pe
JOIN produk pr ON pr.id = pe.produk_id
GROUP BY pr.kategori;
SELECT kategori, transaksi, total_unit, total_nilai, transaksi_terakhir
FROM ringkasan_penjualan
ORDER BY kategori;
or-replace-error-kolom.sql
Unduh berkas-- Mencoba MENGHAPUS kolom lewat CREATE OR REPLACE VIEW:
-- definisi baru hanya berisi empat kolom, tanpa transaksi_terakhir.
-- PostgreSQL menolak: menghapus kolom dari view harus lewat
-- DROP VIEW lalu CREATE VIEW ulang.
CREATE OR REPLACE VIEW ringkasan_penjualan AS
SELECT pr.kategori,
count(*) AS transaksi,
sum(pe.jumlah) AS total_unit,
sum(pe.jumlah * pr.harga) AS total_nilai
FROM penjualan pe
JOIN produk pr ON pr.id = pe.produk_id
GROUP BY pr.kategori;
or-replace-error-nama.sql
Unduh berkas-- Mencoba mengubah nama kolom di tengah daftar lewat CREATE OR REPLACE VIEW:
-- kolom kedua "transaksi" diganti nama menjadi "jumlah_transaksi".
-- PostgreSQL MENOLAK karena nama kolom adalah kontrak view --
-- pemakai dan view lain sudah menulis query dengan nama lama.
CREATE OR REPLACE VIEW ringkasan_penjualan AS
SELECT pr.kategori,
count(*) AS jumlah_transaksi,
sum(pe.jumlah) AS total_unit,
sum(pe.jumlah * pr.harga) AS total_nilai,
max(pe.tanggal) AS transaksi_terakhir
FROM penjualan pe
JOIN produk pr ON pr.id = pe.produk_id
GROUP BY pr.kategori;
view-atas-view.sql
Unduh berkas-- Rantai dependensi: view yang membaca view lain.
CREATE VIEW laporan_besar AS
SELECT kategori, total_nilai
FROM ringkasan_kategori
WHERE total_nilai >= 1500000;
SELECT kategori, total_nilai
FROM laporan_besar
ORDER BY kategori;
-- Ganti nama kolom pada view yang DIBACA ...
ALTER VIEW ringkasan_kategori RENAME COLUMN total_nilai TO nilai_total;
-- ... dan view pemakai tetap hidup: PostgreSQL menulis ulang
-- definisinya secara otomatis agar memakai nama yang baru.
SELECT kategori, total_nilai
FROM laporan_besar
ORDER BY kategori;
\d+ laporan_besar