Memigrasikan pengguna dan skema Oracle® Database ke Cloud SQL untuk PostgreSQL

Dokumen ini adalah bagian dari sebuah seri yang menyajikan informasi dan panduan penting terkait perencanaan dan pelaksanaan migrasi database Oracle® 11g/12c ke Cloud SQL untuk PostgreSQL versi 12. Dokumen ini membahas perbedaan mendasar antara Database Oracle® dan Cloud SQL untuk PostgreSQL dalam kaitannya dengan membuat pengguna, skema, tabel, indeks, dan tabel virtual.

Selain bagian penyiapan pendahuluan, seri ini mencakup bagian-bagian berikut:

Perbedaan terminologi antara Oracle dan Cloud SQL untuk PostgreSQL

Oracle dan Cloud SQL untuk PostgreSQL memiliki arsitektur dan terminologi yang berbeda untuk instance, database, pengguna, dan skema. Untuk melihat ringkasan perbedaan ini, lihat bagian terminologi dalam seri ini.

Mengekspor konfigurasi Oracle

Salah satu langkah pertama saat merencanakan migrasi ke Cloud SQL untuk PostgreSQL adalah meninjau setelan parameter yang sudah ada di database Oracle sumber. Setelan terkait alokasi memori, himpunan karakter, dan parameter penyimpanan sangat berguna karena dapat menentukan konfigurasi awal dan penyesuaian ukuran lingkungan target Cloud SQL untuk PostgreSQL. Ada beberapa metode untuk mengekstrak setelan parameter Oracle. Berikut beberapa metode yang umum:

  • Laporan Automatic Workload Repository (AWR) berisi data alokasi resource (CPU, RAM), konfigurasi parameter instance, dan sesi aktif maksimum.
  • DBA_HIST, V$OSSTAT, dan V$LICENSE untuk detail penggunaan CPU.
  • Tabel virtual V$PARAMETER untuk parameter konfigurasi database.
  • Tabel virtual V$NLS_PARAMETERS untuk parameter bahasa database.
  • Tabel virtual DBA_DATA_FILES untuk menghitung ukuran penyimpanan database.
  • SPFILE Oracle untuk konfigurasi instance database.
  • Alat scheduler tugas (misalnya crontab) untuk mengidentifikasi pencadangan rutin atau masa pemeliharaan yang harus dipertimbangkan.

Mengimpor dan mengonfigurasi pengguna di Cloud SQL untuk PostgreSQL

Secara umum, setiap skema Oracle harus dibuat sebagai skemanya sendiri di PostgreSQL. Di database Oracle, pengguna sama dengan skema. Artinya, skema akan dibuat saat Anda membuat pengguna. Selalu ada hubungan 1:1 antara pengguna dan skema. Di PostgreSQL, pengguna dan skema dibuat secara terpisah. Pengguna dapat dibuat tanpa menciptakan skema yang terkait. Untuk mempertahankan struktur skema atau pengguna Oracle yang sama di PostgreSQL, Anda dapat membuat skema untuk setiap pengguna.

Tabel berikut menampilkan contoh konversi:

Jenis tindakan Jenis database Perbandingan perintah
Membuat pengguna dan skema Oracle CREATE USER username IDENTIFIED BY password;
PostgreSQL Pengguna dan skema merupakan dua konsep yang berbeda di PostgreSQL dan, karenanya, memerlukan dua pernyataan CREATE berbeda

CREATE USER username WITH PASSWORD 'password';
CREATE SCHEMA schema_name;
Menetapkan peran Oracle GRANT CONNECT TO username;
PostgreSQL GRANT pg_monitor TO username;
Memberikan hak istimewa Oracle GRANT SELECT, INSERT, UPDATE ON HR.EMPLOYEES TO username;
PostgreSQL GRANT SELECT, INSERT, UPDATE ON HR.EMPLOYEES TO username;
Mencabut hak istimewa Oracle REVOKE UPDATE ON HR.EMPLOYEES FROM username;
PostgreSQL REVOKE UPDATE ON HR.EMPLOYEES FROM username;
Memberikan akses DBA/superuser Oracle GRANT DBA TO username;
PostgreSQL GRANT cloudsqlsuperuser TO username;
Menghapus pengguna Oracle DROP USER username CASCADE;
PostgreSQL Pengguna dan skema merupakan dua konsep yang berbeda di PostgreSQL dan, karenanya, memerlukan dua pernyataan DROP berbeda

DROP USER username;
DROP SCHEMA schema_name CASCADE;
Metadata pengguna Oracle DBA_USERS
PostgreSQL pg_catalog.pg_user
Metadata izin Oracle DBA_SYS_PRIVS
DBA_ROLE_PRIVS
SESSION_PRIVS
PostgreSQL pg_catalog.pg_roles
String koneksi CLI Oracle sqlplus username/password@host/tns_alias
Sqlplus username/password@host:IP/sid
PostgreSQL Tanpa prompt sandi:

PGPASSWORD=password psql -h hostname -U username -d database_name

Dengan prompt sandi:

psql -h hostname -U username -W -d database_name

Pengguna database Oracle 12c:

Ada dua jenis pengguna di Oracle 12c, pengguna global dan pengguna lokal. Pengguna global dibuat di CDB root yang mencakup PDB. Pengguna ini diidentifikasi berdasarkan awalan C## dalam nama pengguna mereka. Pengguna lokal dibuat hanya di PDB tertentu. Pengguna database yang berbeda dengan nama pengguna yang sama dapat dibuat di beberapa PDB. Saat bermigrasi dari Oracle 12c ke PostgreSQL, ubah pengguna dan izin agar sesuai dengan arsitektur PostgreSQL. Berikut dua contoh umum untuk menggambarkan perbedaan ini:

# Oracle local user
SQL> ALTER SESSION SET CONTAINER=pdb;
SQL> CREATE USER username IDENTIFIED BY password QUOTA 50M ON USERS;

# PostgreSQL user for a single database and schema
postgres=> CREATE USER username WITH PASSWORD 'password';
postgres=> GRANT CONNECT TO DATABASE database_name TO username;
postgres=> GRANT USAGE ON SCHEMA schema_name TO username;
postgres=> -- Optionally, grant object privileges in the schema
postgres=> GRANT ALL ON ALL TABLES IN SCHEMA schema_name TO username;
postgres=> GRANT ALL ON ALL SEQUENCES IN SCHEMA schema_name TO username;
postgres=> GRANT ALL ON ALL FUNCTIONS IN SCHEMA schema_name TO username;
postgres=> GRANT ALL ON ALL PROCEDURES IN SCHEMA schema_name TO username;
postgres=> GRANT ALL ON ALL ROUTINES IN SCHEMA schema_name TO username;

# Oracle common user
SQL> CREATE USER c##username IDENTIFIED BY password CONTAINER=ALL;

# PostgreSQL user with permissions for all database (use the local user script above and repeat it for each database and schema)

Mengelola pengguna melalui Konsol Google Cloud

Guna melihat pengguna Cloud SQL untuk PostgreSQL yang saat ini dikonfigurasi, buka halaman berikut di Konsol Google Cloud :

Google Cloud > Storage > SQL > Instance > Users

Screenshot halaman Users.

Mengimpor definisi tabel dan tabel virtual

Oracle dan PostgreSQL berbeda dalam hal kepekaan huruf besar/kecil. Nama di Oracle tidak peka huruf besar/kecil. Nama di PostgreSQL tidak peka huruf besar/kecil kecuali jika diapit oleh tanda kutip ganda. Ada banyak alat ekspor skema dan penghasil SQL untuk Oracle yang otomatis menambahkan tanda kutip ganda ke nama objek, misalnya DBMS_METADATA.GET_DDL. Tanda kutip ini dapat menimbulkan berbagai masalah setelah migrasi. Sebaiknya hapus semua tanda kutip yang mengapit nama objek dari pernyataan bahasa definisi data (DDL) sebelum Anda membuat objek tersebut di PostgreSQL.

Sintaksis create table

Saat mengonversi tabel dari Oracle ke jenis data PostgreSQL, langkah pertama adalah mengekstrak pernyataan create table Oracle dari database sumbernya. Contoh kueri berikut mengekstrak DDL untuk tabel locations dari skema HR:

SQL> SELECT DBMS_METADATA.GET_DDL('TABLE', 'LOCATIONS') FROM DUAL;

CREATE TABLE "HR"."LOCATIONS"
   (  "LOCATION_ID" NUMBER(4,0),
  "STREET_ADDRESS" VARCHAR2(40),
  "POSTAL_CODE" VARCHAR2(12),
  "CITY" VARCHAR2(30) CONSTRAINT "LOC_CITY_NN" NOT NULL ENABLE,
  "STATE_PROVINCE" VARCHAR2(25),
  "COUNTRY_ID" CHAR(2),
  CONSTRAINT "LOC_ID_PK" PRIMARY KEY ("LOCATION_ID")
...
      CONSTRAINT "LOC_C_ID_FK" FOREIGN KEY ("COUNTRY_ID")
          REFERENCES "HR"."COUNTRIES" ("COUNTRY_ID") ENABLE

Output lengkapnya mencakup elemen penyimpanan, indeks, dan informasi tablespace, yang dihilangkan karena elemen tambahan tersebut tidak didukung oleh pernyataan CREATE TABLE PostgreSQL.

Setelah DDL diekstrak, hapus tanda kutip yang mengapit nama dan lakukan konversi tabel sesuai dengan tabel konversi jenis data Oracle ke PostgreSQL. Periksa jenis data di setiap kolom untuk mengetahui apakah jenis data tersebut dapat dikonversi apa adanya. Jika tidak, pilih jenis data lain sesuai dengan tabel konversi. Misalnya, berikut adalah DDL yang dikonversi untuk tabel locations.

CREATE TABLE HR.LOCATIONS (
  LOCATION_ID NUMERIC(4,0),
  STREET_ADDRESS VARCHAR(40),
  POSTAL_CODE VARCHAR(12),
  CITY VARCHAR(30) CONSTRAINT LOC_CITY_NN NOT NULL,
  STATE_PROVINCE VARCHAR(25),
  COUNTRY_ID CHAR(2),
  CONSTRAINT LOC_ID_PK PRIMARY KEY (LOCATION_ID),
  CONSTRAINT LOC_C_ID_FK FOREIGN KEY (COUNTRY_ID)
REFERENCES HR.COUNTRIES (COUNTRY_ID)
)

Create Table As Select (CTAS)

Pernyataan CREATE TABLE AS SELECT (CTAS) digunakan untuk membuat tabel baru berdasarkan tabel yang sudah ada. Perhatikan bahwa hanya nama kolom dan jenis data kolom yang disalin, sedangkan batasan dan indeks tidak. PostgreSQL mendukung standar ANSI SQL untuk fungsionalitas CTAS, dan kompatibel dengan pernyataan CTAS Oracle.

Kolom tak terlihat di Oracle 12c

PostgreSQL tidak mendukung kolom tak terlihat. Sebagai solusinya, buat tabel virtual yang hanya menampung kolom terlihat.

Batasan tabel

Oracle menyediakan enam jenis batasan tabel yang dapat ditetapkan pada atau setelah langkah pembuatan tabel menggunakan perintah ALTER TABLE. Jenis batasan Oracle adalah PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK, NOT NULL, dan REF. Selain itu, Oracle mengizinkan pengguna mengontrol status batasan melalui opsi berikut:

  • INITIALLY IMMEDIATE: Memeriksa batasan di akhir setiap pernyataan SQL berikutnya (status default).
  • DEFERRABLE/NOT DEFERRABLE: Mengaktifkan penggunaan klausa SET CONSTRAINT dalam transaksi berikutnya sebelum pernyataan COMMIT dikirim.
  • INITIALLY DEFERRED: Memeriksa batasan di akhir transaksi berikutnya.
  • VALIDATE/NO VALIDATE: Memeriksa (atau sengaja tidak memeriksa) error pada baris baru atau baris yang diubah. Parameter ini bergantung pada apakah batasannya adalah ENABLED atau DISABLED.
  • ENABLED/DISABLED: Menentukan apakah batasan harus diterapkan setelah pembuatan (ENABLED secara default).

PostgreSQL juga mendukung enam jenis batasan tabel: PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK, NOT NULL, dan EXCLUDE. Namun, ada beberapa perbedaan penting antara jenis batasan di Oracle dan PostgreSQL, termasuk:

  • PostgreSQL tidak mendukung batasan REF Oracle.
  • PostgreSQL tidak otomatis membuat indeks di kolom referensi untuk batasan kunci asing. Jika indeks dibutuhkan, pernyataan CREATE INDEX berbeda diperlukan di kolom referensi.
  • PostgreSQL tidak mendukung klausa ON DELETE SET NULL Oracle. Klausa ini meminta Oracle menetapkan semua nilai dependen dalam tabel turunan ke NULL saat kumpulan data dalam tabel induk dihapus.
  • Batasan terkait VIEWS tidak didukung, kecuali untuk CHECK OPTION.
  • PostgreSQL tidak mendukung batasan penonaktifan. PostgreSQL mendukung opsi NOT VALID saat batasan kunci asing atau pemeriksaan baru ditambahkan menggunakan pernyataan ALTER TABLE. Opsi ini meminta PostgreSQL melewati pemeriksaan integritas referensial pada kumpulan data yang ada dalam tabel turunan.

Tabel berikut merangkum perbedaan utama antara jenis batasan di Oracle dan di PostgreSQL:

Jenis batasan di Oracle Dukungan di Cloud SQL untuk PostgreSQL Setara dengan Cloud SQL untuk PostgreSQL
PRIMARY KEY Ya PRIMARY KEY
FOREIGN KEY Ya Menggunakan sintaksis ANSI SQL yang sama dengan Oracle.

Menggunakan klausa ON DELETE untuk menangani kasus penghapusan data induk FOREIGN KEY. PostgreSQL menyediakan tiga opsi untuk menangani kasus penghapusan data dari tabel induk dan tabel turunan direferensikan oleh batasan FOREIGN KEY:

  • ON DELETE CASCADE
  • ON DELETE RESTRICT
  • ON DELETE NO ACTION

PostgreSQL tidak mendukung klausa ON DELETE SET NULL Oracle.

Menggunakan klausa ON UPDATE untuk menangani kasus pembaruan kumpulan data induk FOREIGN KEY.
PostgreSQL menyediakan tiga opsi untuk menangani peristiwa pembaruan batasan FOREIGN KEY:

  • ON UPDATE CASCADE
  • ON UPDATE RESTRICT
  • ON UPDATE NO ACTION

PostgreSQL tidak otomatis membuat indeks di kolom referensi untuk batasan kunci asing.
UNIQUE Ya Membuat indeks UNIQUE secara default.
CHECK Ya CHECK
NOT NULL Ya NOT NULL
REF Tidak Tidak didukung.
DEFERRABLE/NOT DEFERRABLE Ya DEFERRABLE/NOT DEFERRABLE
INITIALLY IMMEDIATE Ya INITIALLY IMMEDIATE
INITIALLY DEFERRED Ya INITIALLY DEFERRED
VALIDATE/NO VALIDATE Tidak Tidak didukung.
ENABLE/DISABLE Tidak Diaktifkan secara default. Gunakan opsi NOT VALID saat batasan kunci asing atau pemeriksaan baru ditambahkan ke tabel menggunakan pernyataan ALTER TABLE untuk melewati pemeriksaan integritas referensial di kumpulan data yang sudah ada.
Batasan terkait VIEW Tidak Tidak didukung kecuali VIEW WITH CHECK OPTION.
Metadata batasan Oracle DBA_CONSTRAINTS
PostgreSQL INFORMATION_SCHEMA.TABLE_CONSTRAINTS

Kolom virtual dan kolom buatan

Kolom virtual Oracle didasarkan pada hasil penghitungan kolom lain. Kolom ini muncul sebagai kolom reguler, tetapi nilainya diperoleh dari penghitungan langsung oleh mesin database Oracle dan tidak disimpan di database. Kolom virtual dapat digunakan dengan batasan, indeks, partisi tabel, dan kunci asing, tetapi tidak dapat dimanipulasi melalui operasi bahasa pengolahan data (DML).

Dalam hal fungsionalitas, kolom buatan di PostgreSQL sebanding dengan kolom virtual di Oracle. Namun, tidak seperti di Oracle, kolom buatan di PostgreSQL disimpan dan jenis data untuk setiap kolom yang dibuat harus ditentukan, yang berarti kolom tersebut menggunakan penyimpanan seperti halnya kolom biasa.

Contoh kolom virtual di Oracle:

SQL> CREATE TABLE PRODUCTS (
        PRODUCT_ID     INT PRIMARY KEY,
        PRODUCT_TYPE   VARCHAR2(100) NOT NULL,
        PRODUCT_PRICE  NUMBER(6,2) NOT NULL,
        PRICE_WITH_TAX AS (ROUND(PRODUCT_PRICE * 1.01, 2))
);

SQL> INSERT INTO PRODUCTS(PRODUCT_ID, PRODUCT_TYPE, PRODUCT_PRICE)
     VALUES(1, 'A', 99.99);

SQL> SELECT * FROM PRODUCTS;
PRODUCT_ID PRODUCT_TYPE         PRODUCT_PRICE PRICE_WITH_TAX
---------- -------------------- ------------- --------------
         1 A                            99.99         100.99

Contoh yang setara di PostgreSQL:

postgres=> CREATE TABLE PRODUCTS (
postgres(>         PRODUCT_ID     INT PRIMARY KEY,
postgres(>         PRODUCT_TYPE   VARCHAR(100) NOT NULL,
postgres(>         PRODUCT_PRICE  NUMERIC(6,2) NOT NULL,
postgres(>         PRICE_WITH_TAX NUMERIC GENERATED ALWAYS AS (ROUND(PRODUCT_PRICE * 1.01, 2)) STORED
postgres(> );

postgres=> INSERT INTO PRODUCTS(PRODUCT_ID, PRODUCT_TYPE, PRODUCT_PRICE) VALUES(1, 'A', 99.99);

postgres=> SELECT * FROM PRODUCTS;
 product_id | product_type | product_price | price_with_tax
------------+--------------+---------------+----------------
          1 | A            |         99.99 |         100.99
(1 row)

Indeks tabel

Oracle dan PostgreSQL menyediakan berbagai algoritma pengindeksan dan jenis indeks yang dapat digunakan untuk aneka aplikasi. Berikut daftar algoritma pengindeksan yang tersedia di PostgreSQL:

Algoritma indeks Deskripsi
B-tree
  • Jenis indeks default untuk PostgreSQL, yang digunakan untuk mempercepat kueri kesetaraan dan rentang
  • Mendukung semua jenis data primitif dan dapat digunakan untuk mengambil nilai NULL
  • Nilai indeks diurutkan dalam urutan menaik secara default, tetapi juga dapat dikonfigurasi dalam urutan menurun
Hash
  • Digunakan untuk mempercepat penelusuran kesetaraan
  • Lebih efisien daripada indeks B-tree, tetapi hanya terbatas untuk penanganan penelusuran kesetaraan
GIN
  • Indeks hierarki terbalik
  • Lebih efisien daripada indeks B-tree saat menangani kolom yang berisi banyak nilai komponen, seperti array dan teks
GiST
  • Bukan jenis indeks, melainkan infrastruktur untuk menentukan indeks yang dapat mendukung lebih banyak operator perbandingan daripada yang dapat didukung oleh indeks B-tree normal
  • Berguna untuk data geometri saat pengoptimalan penelusuran "tetangga terdekat" diperlukan
SP-GiST
  • Mirip dengan GiST, SP-GiST adalah infrastruktur untuk strategi pengindeksan yang ditetapkan pengguna
  • Memungkinkan berbagai struktur data tidak seimbang seperti quadtree
  • Tidak tersedia di Cloud SQL untuk PostgreSQL
BRIN
  • Block Range INdexes (Indeks Rentang Blok)
  • Menyimpan ringkasan rentang blok fisik tabel
  • Untuk kolom dengan tata urutan linear
  • Berguna untuk pencarian rentang pada tabel berukuran besar

Tabel berikut membandingkan jenis indeks antara Oracle dan PostgreSQL:

Indeks di Oracle Deskripsi Didukung oleh PostgreSQL Indeks setara di PostgreSQL
Indeks bitmap Menyimpan bitmap untuk setiap kunci indeks, ideal untuk mendukung pengambilan data cepat untuk workload OLAP Tidak T/A
Indeks B-tree Jenis indeks yang paling umum, sangat cocok untuk berbagai workload dan dapat dikonfigurasi dalam pengurutan ASC|DESC. Ya Indeks B-tree
Indeks komposit Membuat dua kolom atau lebih untuk meningkatkan performa pengambilan data. Urutan kolom di dalam indeks menentukan jalur akses. Ya Indeks multi-kolom
Hingga 32 kolom dapat ditentukan saat membuat indeks multi-kolom.
Indeks berbasis fungsi Menyimpan output dari fungsi yang diterapkan pada nilai kolom tabel. Ya Indeks terkait ekspresi
Indeks unik Indeks B-tree yang menerapkan batasan UNIQUE pada nilai yang diindeks per kolom. Ya Indeks unik
Indeks domain aplikasi Cocok untuk mengindeks data non-relasional seperti data audio/video, data LOB, dan jenis non-tekstual lainnya. Tidak T/A
Indeks tak terlihat Fitur Oracle yang memungkinkan Anda mengelola, memelihara, dan menguji indeks tanpa memengaruhi pengambilan keputusan pengoptimal. Tidak Sebagai solusi alternatif, Anda dapat membuat indeks tambahan di replika baca untuk tujuan pengujian tanpa memengaruhi aktivitas yang sedang berlangsung.
Tabel yang diatur indeks Jenis indeks yang mengontrol cara data disimpan di tingkat tabel dan indeks. Tidak PostgreSQL tidak mendukung tabel yang diatur indeks. Di PostgreSQL, penyimpanan tabel sesuai dengan indeks tertentu diatur menggunakan pernyataan CLUSTER. Pernyataan ini memiliki fungsi yang mirip dengan tabel yang diatur indeks di Oracle. Namun, pengelompokan merupakan operasi satu kali, dan PostgreSQL tidak mempertahankan struktur tabel pada pembaruan berikutnya. Pengelompokan manual dan berkala diperlukan.
Indeks lokal dan global Digunakan untuk mengindeks tabel berpartisi di database Oracle. Setiap indeks ditetapkan sebagai LOCAL atau GLOBAL. Tidak Indeks kerja partisi di PostgreSQL memiliki fungsionalitas yang sama dengan indeks lokal di Oracle (yaitu indeks ditetapkan di tingkat partisi; tingkat global tidak didukung).
Indeks parsial untuk tabel berpartisi (Oracle 12c) Membuat indeks di sebagian partisi tabel. Mendukung LOCAL dan GLOBAL. Ya Di PostgreSQL, partisi dibuat dengan melampirkan tabel turunan ke dalam tabel induk. Indeks hanya dapat dibuat di sebagian tabel turunan.
CREATE/DROP INDEX Perintah yang digunakan untuk membuat dan menghapus indeks. Ya PostgreSQL mendukung perintah CREATE INDEX. Selain itu, ALTER TABLE tableName ADD INDEX indexName columnName juga didukung.
ALTER INDEX ... REBUILD Membuat ulang indeks, yang dapat menyebabkan penguncian eksklusif pada tabel yang diindeks. Perlu sintaksis berbeda PostgreSQL mendukung pembuatan ulang indeks menggunakan pernyataan REINDEX. Tabel dikunci untuk operasi tulis selama operasi ini berlangsung dan hanya operasi baca yang diizinkan.
ALTER INDEX ... REBUILD ONLINE Membuat ulang indeks tanpa menimbulkan penguncian eksklusif di tabel itu. Perlu sintaksis berbeda PostgreSQL mendukung pembuatan ulang indeks serentak menggunakan pernyataan REINDEX TABLE CONCURRENTLY. Dalam mode ini, PostgreSQL mencoba membuat ulang indeks menggunakan penguncian minimum, meskipun konsekuensinya pembuatan ulang indeks memerlukan waktu dan resource lebih banyak.
Kompresi indeks Fitur untuk mengurangi ukuran fisik indeks. Tidak T/A
Mengalokasikan
indeks ke tablespace
Membuat tablespace indeks yang dapat disimpan di disk terpisah dari data tabel untuk mengurangi bottleneck I/O disk. Tidak Meskipun PostgreSQL memungkinkan pembuatan indeks dalam tablespace yang ditetapkan pengguna, Anda tidak dapat membuat tablespace di Cloud SQL untuk PostgreSQL, dan indeks harus dibuat di tablespace default.
Mengindeks metadata (tabel/tabel virtual) Oracle DBA_INDEXES
DBA_PART_INDEXES
DBA_IND_COLUMNS
PostgreSQL pg_catalog.pg_index
pg_catalog.pg_attribute
pg_catalog.pg_class

Pertimbangan konversi indeks

Pada umumnya, indeks Oracle dapat dengan mudah dikonversi menjadi indeks B-tree PostgreSQL, karena jenis indeks ini paling umum digunakan. Seperti dalam database Oracle, indeks otomatis dibuat di kolom PRIMARY KEY pada tabel. Demikian pula, indeks UNIQUE otomatis dibuat di kolom yang memiliki batasan UNIQUE. Selain itu, indeks sekunder dibuat menggunakan pernyataan CREATE INDEX standar.

Contoh berikut menunjukkan cara mengonversi tabel Oracle yang berisi beberapa kolom terindeks ke dalam PostgreSQL:

SQL> CREATE TABLE ORA_IDX_TO_PG (
        col1 INT PRIMARY KEY,
        col2 VARCHAR2(60),
        col3 DATE,
        col4 CLOB,
        col5 VARCHAR2(20)
      );

-- Single-field index
SQL> CREATE INDEX idx_col2 ON ora_idx_to_pg(col2);

-- Composite index
SQL> CREATE INDEX idx_cols3_2 ON ora_idx_to_pg(col3 DESC, col2);

-- Unique index
SQL> CREATE UNIQUE INDEX idx_col3_uni ON ora_idx_to_pg(col3);

-- Function-based index
SQL> CREATE INDEX idx_func_col3 ON
        ora_idx_to_pg(EXTRACT(MONTH FROM col3));

-- CLOB index
SQL> CREATE INDEX idx_col4 ON
       ora_idx_to_pg(col4) INDEXTYPE IS CTXSYS.CONTEXT;

-- Invisible index
SQL> CREATE INDEX idx_col5_inv ON
        ora_idx_to_pg(col5) INVISIBLE;

-- Drop index
SQL> DROP INDEX idx_col5_inv;

postgres=> CREATE TABLE ORA_IDX_TO_PG (
postgres(> col1 INT PRIMARY KEY,
postgres(> col2 VARCHAR(60),
postgres(> col3 DATE,
postgres(> col4 TEXT,
postgres(> col5 VARCHAR(20)
postgres(> );

-- Single index (supported)
postgres=> CREATE INDEX idx_col2 ON ora_idx_to_pg(col2);

-- Composite index (supported)
postgres=> CREATE INDEX idx_cols3_2 ON ora_idx_to_pg(col3 DESC, col2);

-- Unique index (supported)
postgres=> CREATE UNIQUE INDEX idx_col3_uni ON ora_idx_to_pg(COL3);

-- Function-based index (supported)
postgres=> CREATE INDEX idx_func_col3 ON
postgres->         ora_idx_to_pg(EXTRACT(MONTH FROM col3));

-- CLOB (Supported, but requires different syntax. See Full Text Search for details)
postgres=> CREATE INDEX idx_col4 ON ora_idx_to_pg
postgres->         USING GIN (to_tsvector('english', col4));

-- Invisible index (not supported)
-- Optional - create the index as a B-tree index
postgres=> CREATE INDEX idx_col5 ON ora_idx_to_pg(col5);

-- Drop index
postgres=> DROP INDEX idx_col2;

SQL> SELECT ui.table_name,
            ui.index_name,
            ui.index_type,
            ic.column_name
     FROM user_indexes ui JOIN user_ind_columns ic
     ON ui.index_name = ic.index_name
     WHERE ui.table_name = 'ORA_IDX_TO_PG'
     ORDER BY 4;

postgres=> select distinct
postgres->     t.relname as table_name,
postgres->     i.relname as index_name,
postgres-> pg_get_indexdef(ix.indexrelid) index_definition
postgres-> from
postgres->     pg_class t,
postgres->     pg_class i,
postgres->     pg_index ix
postgres-> where
postgres->     t.oid = ix.indrelid
postgres->     and i.oid = ix.indexrelid
postgres->     and t.relname = 'ora_idx_to_pg'
postgres-> order by
postgres->     t.relname,
postgres->     i.relname;

-- OR Use psql \d command:
postgres=> \d ora_idx_to_pg
                  Table "public.ora_idx_to_pg"
 Column |         Type          | Collation | Nullable | Default
--------+-----------------------+-----------+----------+---------
 col1   | integer               |           | not null |
 col2   | character varying(60) |           |          |
 col3   | date                  |           |          |
 col4   | text                  |           |          |
 col5   | character varying(20) |           |          |
Indexes:
    "ora_idx_to_pg_pkey" PRIMARY KEY, btree (col1)
    "idx_col2" btree (col2)
    "idx_col4" gin (to_tsvector('english'::regconfig, col4))
    "idx_col5" btree (col5)
    "idx_cols3_2" btree (col3 DESC, col2)
    "idx_func_col3" btree (date_part('month'::text, col3))

postgres=>

Partisi tabel

Oracle dan PostgreSQL sama-sama menawarkan kapabilitas pembuatan partisi untuk memecah tabel berukuran besar. Partisi dibuat dengan menyegmentasikan tabel secara fisik menjadi bagian-bagian lebih kecil. Setiap bagian berisi sekumpulan baris horizontal. Tabel yang dipartisi disebut sebagai tabel induk dan baris-barisnya disimpan secara fisik di partisinya. Meskipun tidak semua jenis partisi Oracle didukung di PostgreSQL, PostgreSQL mendukung jenis yang paling umum.

Bagian berikut menjelaskan jenis-jenis partisi yang didukung di PostgreSQL. Setiap jenis disertai contoh cara membuat partisi yang berkaitan dengan jenis tersebut.

Partisi RANGE

Jenis partisi ini menetapkan baris ke partisi berdasarkan nilai kolom yang berada dalam rentang tertentu. Setiap partisi berisi baris yang nilai ekspresi pemartisiannya berada dalam rentang tertentu. Perlu diperhatikan bahwa rentang tidak tumpang-tindih pada partisi.

Contoh

CREATE TABLE employees (
 empid     INT,
 fname     VARCHAR(30),
 lname     VARCHAR(30),
 hired     DATE,
 separated DATE,
 job_code  INT,
 store_id  INT)
 PARTITION BY RANGE (store_id);

CREATE TABLE employees_p0 PARTITION OF employees
 FOR VALUES FROM (MINVALUE) TO (6);
CREATE TABLE employees_p1 PARTITION OF employees
 FOR VALUES FROM (6) TO (11);
CREATE TABLE employees_p2 PARTITION OF employees
 FOR VALUES FROM (11) TO (16);
CREATE TABLE employees_p3 PARTITION OF employees
 FOR VALUES FROM (16) TO (21);

Partisi LIST

Mirip dengan partisi RANGE, partisi LIST menetapkan baris ke partisi berdasarkan nilai kolom yang berada dalam kumpulan nilai yang telah ditetapkan. Nilai kunci yang muncul di setiap partisi tercantum secara eksplisit untuk partisi LIST.

Contoh

CREATE TABLE employees (
 empid     INT,
 fname     VARCHAR(30),
 lname     VARCHAR(30),
 hired     DATE,
 separated DATE,
 job_code  INT,
 store_id  INT)
 PARTITION BY LIST (store_id);

CREATE TABLE employees_pNorth PARTITION OF employees
 FOR VALUES IN (3,5,6);
CREATE TABLE employees_pEast PARTITION OF employees
 FOR VALUES IN (1,2,10);
CREATE TABLE employees_pWest PARTITION OF employees
 FOR VALUES IN (4,12,13);
CREATE TABLE employees_pCnrl PARTITION OF employees
 FOR VALUES IN (7,8,15);

Partisi HASH

Partisi HASH paling cocok digunakan jika sasarannya adalah mencapai distribusi data yang merata di antara semua partisi. Nilai kolom (atau ekspresi berdasarkan nilai kolom yang akan di-hash) dan nilai baris ditetapkan ke partisi yang sesuai dengan nilai hash tersebut. Nilai hash harus ditetapkan secara unik ke partisi, dan semua nilai yang disisipkan harus dipetakan ke satu partisi saja.

Contoh

CREATE TABLE employees (
 empid     INT,
 fname     VARCHAR(30),
 lname     VARCHAR(30),
 hired     DATE,
 separated DATE,
 job_code  INT,
 store_id  INT)
 PARTITION BY HASH (date_part('year', hired));

CREATE TABLE employees_p0 PARTITION OF employees
 FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE employees_p1 PARTITION OF employees
 FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE employees_p2 PARTITION OF employees
 FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE employees_p3 PARTITION OF employees
 FOR VALUES WITH (MODULUS 4, REMAINDER 3);

Partisi multi-level

Partisi multi-level adalah metode pembuatan hierarki partisi untuk satu tabel. Setiap partisi dibagi lagi menjadi sejumlah partisi berbeda. Jumlah sub-partisi dapat bervariasi antara satu partisi dan partisi lainnya.

Contoh

CREATE TABLE sales (
 Saleid    INT,
 sale_date DATE,
 cust_code VARCHAR(15),
 income    DECIMAL(8,2))
PARTITION BY RANGE(date_part('year', sale_date));

CREATE TABLE sales_2019 PARTITION OF sales
 FOR VALUES FROM (2019) TO (2020)
 PARTITION BY RANGE(date_part('month', sale_date));

CREATE TABLE sales_2019_q1 PARTITION OF sales_2019
 FOR VALUES FROM (1) TO (4);
CREATE TABLE sales_2019_q2 PARTITION OF sales_2019
 FOR VALUES FROM (4) TO (7);
CREATE TABLE sales_2019_q3 PARTITION OF sales_2019
 FOR VALUES FROM (7) TO (10);
CREATE TABLE sales_2019_q4 PARTITION OF sales_2019
 FOR VALUES FROM (10) TO (13);

CREATE TABLE sales_2020 PARTITION OF sales
 FOR VALUES FROM (2020) TO (2021)
 PARTITION BY RANGE(date_part('month', sale_date));

CREATE TABLE sales_2020_q1 PARTITION OF sales_2020
 FOR VALUES FROM (1) TO (4);
CREATE TABLE sales_2020_q2 PARTITION OF sales_2020
 FOR VALUES FROM (4) TO (7);
CREATE TABLE sales_2020_h2 PARTITION OF sales_2020
 FOR VALUES FROM (7) TO (13);

Memasang atau melepas partisi

Di PostgreSQL, partisi dapat ditambahkan atau dihapus dari tabel induk. Partisi yang dilepas nantinya dapat dipasang kembali ke tabel yang sama. Selain itu, kondisi pemartisian yang baru dapat ditentukan saat memasang kembali partisi tersebut, sehingga batas partisi dapat disesuaikan.

Contoh

CREATE TABLE employees (
 empid     INT,
 fname     VARCHAR(30),
 lname     VARCHAR(30),
 hired     DATE,
 separated DATE,
 job_code  INT,
 store_id  INT)
 PARTITION BY RANGE (date_part('year', hired));

CREATE TABLE employees_p0 PARTITION OF employees
 FOR VALUES FROM (2010) TO (2015);
CREATE TABLE employees_p1 PARTITION OF employees
 FOR VALUES FROM (2015) TO (2020);

-- changing partition boundaries
BEGIN TRANSACTION;
ALTER TABLE employees DETACH PARTITION employees_p1;
ALTER TABLE employees ATTACH PARTITION employees_p1 FOR VALUES FROM (2015) TO (2022);
COMMIT TRANSACTION;

Tabel berikut menjelaskan elemen jenis partisi yang sama di Oracle dan Cloud SQL untuk PostgreSQL, dan elemen yang perlu dikonversi:

Jenis partisi di Oracle Didukung oleh PostgreSQL Implementasi di PostgreSQL
Partisi RANGE Ya PARTITION BY RANGE
Partisi LIST Ya PARTITION BY LIST
Partisi HASH Ya PARTITION BY HASH
SUB-PARTITIONING Ya Partisi multi-level
Partisi interval Tidak Tidak didukung
Penasihat partisi Tidak Tidak didukung
Partisi preferensi Tidak Tidak didukung
Partisi berbasis kolom virtual Tidak Sebagai solusinya, pertimbangkan membuat partisi dengan ekspresi kolom virtual secara langsung:

CREATE TABLE users (
id INT,
username VARCHAR(20),
first_letter VARCHAR(1)
GENERATED ALWAYS AS
(
UPPER(SUBSTR(TRIM(username), 1, 1))
) STORED
)
PARTITION BY LIST (UPPER(SUBSTR(TRIM(username), 1, 1)));

Partisi daftar otomatis Tidak Tidak didukung
Memecah
partisi
Tidak Sebagai solusinya, pertimbangkan melepas atau memasang partisi tabel untuk menyesuaikan batas partisi
Menukar partisi Ya DETACH / ATTACH PARTITION
Partisi multi-jenis (partisi komposit) Ya Partisi multi-level
Metadata partisi Oracle DBA_TAB_PARTITIONS
DBA_TAB_SUBPARTITIONS
PostgreSQL pg_catalog.pg_class
pg_catalog.pg_partitioned_table

Contoh berikut menunjukkan perbandingan per aspek dari pembuatan partisi tabel di kedua platform. Perhatikan bahwa PostgreSQL tidak mendukung pereferensian tablespace dalam klausa PARTITIONS perintah CREATE TABLE.

Implementasi di Oracle

CREATE TABLE employees (
empid NUMBER,
fname VARCHAR2(30),
lname VARCHAR2(30),
hired DATE,
separated DATE,
job_code NUMBER,
store_id NUMBER)
PARTITION BY LIST (store_id) (
PARTITION employees_pNorth VALUES (3,5,6) TABLESPACE users,
PARTITION employees_pEast VALUES (1,2,10) TABLESPACE users,
PARTITION employees_pWest VALUES (4,12,13) TABLESPACE users,
PARTITION employees_pCnrl VALUES (7,8,15) TABLESPACE users
);

Implementasi di PostgreSQL

CREATE TABLE employees (
empid INT,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE,
separated DATE,
job_code INT,
store_id INT)
PARTITION BY LIST (store_id);

CREATE TABLE employees_pNorth PARTITION OF employees
FOR VALUES IN (3,5,6);
CREATE TABLE employees_pEast PARTITION OF employees
FOR VALUES IN (1,2,10);
CREATE TABLE employees_pWest PARTITION OF employees
FOR VALUES IN (4,12,13);
CREATE TABLE employees_pCnrl PARTITION OF employees
FOR VALUES IN (7,8,15);

Tabel sementara

Di database Oracle, tabel sementara disebut GLOBAL TEMPORARY TABLES, sedangkan di PostgreSQL, tabel sementara cukup disebut tabel sementara. Fungsionalitas dasar tabel sementara di kedua platform sama persis. Namun, ada beberapa perbedaan penting:

  • Oracle menyimpan struktur tabel sementara untuk penggunaan berulang bahkan setelah database dimulai ulang. Di sisi lain, PostgreSQL menyimpan tabel sementara hanya selama durasi sesi.
  • Tabel sementara di database Oracle dapat diakses oleh berbagai pengguna dengan izin yang sesuai. Sebaliknya, tabel sementara di PostgreSQL hanya dapat diakses selama sesi yang dibuat untuknya, kecuali jika tabel sementara tersebut direferensikan dengan nama yang memenuhi syarat skema.
  • Di database Oracle, terdapat perbedaan jelas antara tabel sementara GLOBAL dan LOCAL yang menentukan apakah isi tabel bersifat global atau khusus sesi. Di PostgreSQL, kata kunci GLOBAL dan LOCAL didukung karena alasan kompatibilitas, tetapi tidak berpengaruh pada visibilitas data.
  • Jika klausa ON COMMIT dihilangkan saat membuat tabel sementara, perilaku default di database Oracle adalah ON COMMIT DELETE ROWS. Artinya, Oracle akan memotong tabel sementara setelah setiap commit. Sebaliknya, di PostgreSQL, perilaku defaultnya adalah mempertahankan baris dalam tabel sementara setelah setiap commit.

Tabel berikut menunjukkan perbedaan tabel sementara antara Oracle dan Cloud SQL untuk PostgreSQL.

Fitur tabel sementara Implementasi di Oracle Implementasi di PostgreSQL
Sintaksis CREATE GLOBAL TEMPORARY TABLE CREATE TEMPORARY TABLE
Aksesibilitas Dapat diakses dari banyak sesi Dapat diakses dari sesi pembuat saja, kecuali jika direferensikan dengan nama yang memenuhi syarat skema
Dukungan indeks Ya Ya
Dukungan kunci asing Ya Ya
Mempertahankan DDL Ya Tidak
Tindakan default ON COMMIT Kumpulan data dihapus Kumpulan data dipertahankan
ON COMMIT PRESERVE ROWS Ya Ya
ON COMMIT DELETE ROWS Ya Ya
ON COMMIT DROP Tidak Ya
Dukungan ALTER TABLE Ya Ya
Statistik pengumpulan DBMS_STATS.GATHER_TABLE_STATS ANALYZE
Oracle 12c GLOBAL_TEMP_

TABLE_STATS
DBMS_STATS.SET_TABLE_PREFS ANALYZE

Kolom yang tidak digunakan

Di Oracle, fitur penandaan kolom tertentu sebagai UNUSED sering digunakan untuk menghapus kolom dari tabel tanpa menghapus data kolom secara fisik. Tindakan ini dilakukan untuk mencegah potensi muatan tinggi yang terjadi saat menghapus kolom dari tabel besar.

Di PostgreSQL, data kolom tidak akan terhapus dari penyimpanan fisik jika kolom besar dihapus. Oleh karena itu, operasi penghapusan berjalan cepat meskipun tabel berukuran besar. Anda tidak perlu menandai kolom sebagai UNUSED seperti di database Oracle. Ruang yang semula ditempati kolom yang dihapus akan diklaim kembali dengan pernyataan DML baru atau selama operasi VACUUM berikutnya.

Tabel hanya baca

Tabel hanya-baca adalah fitur di Oracle yang menandai tabel sebagai hanya-baca menggunakan perintah ALTER TABLE. Di Oracle 12c R2, fitur ini juga tersedia untuk tabel yang memiliki partisi dan subpartisi. PostgreSQL tidak menawarkan fitur yang setara, tetapi ada dua kemungkinan alternatif:

  • Memberikan izin SELECT atas tabel untuk pengguna tertentu. Perlu diperhatikan bahwa izin ini tidak menghalangi pemilik tabel untuk melakukan operasi DML di tabel miliknya.
  • Membuat replika baca Cloud SQL untuk PostgreSQL dan mengarahkan pengguna ke tabel replika yang merupakan tabel hanya baca. Solusi ini memerlukan penambahan instance replika baca ke instance Cloud SQL untuk PostgreSQL yang ada.
  • Membuat pemicu database yang memunculkan pengecualian pada pernyataan DML—misalnya:

    -- Define trigger function
    CREATE OR REPLACE FUNCTION raise_readonly_exception() RETURNS TRIGGER AS $$
    BEGIN
      RAISE EXCEPTION 'Table is readonly!';
      RETURN NULL;
    END;
    $$ LANGUAGE 'plpgsql';
    
    -- Fire trigger when DML statements is executed on read only table
    CREATE TRIGGER myTable_readonly_trigger
    BEFORE INSERT OR UPDATE OR DELETE OR TRUNCATE ON myTable FOR EACH STATEMENT
    EXECUTE PROCEDURE raise_readonly_exception();
    
    -- Testing the trigger
    postgres=> INSERT INTO myTable (id) VALUES (1);
    ERROR:  Table is readonly!
    CONTEXT:  PL/pgSQL function raise_readonly_exception() line 3 at RAISE
    postgres=>
    

Himpunan karakter

Oracle dan PostgreSQL sama-sama mendukung berbagai himpunan karakter, kolasi, dan unicode, termasuk dukungan untuk bahasa byte tunggal dan multi-byte. Selain itu, database PostgreSQL yang berada di instance yang sama dapat dikonfigurasi dengan himpunan karakter berbeda. Lihat daftar himpunan karakter yang didukung di PostgreSQL.

Di database Oracle, himpunan karakter ditentukan di tingkat database (Oracle 12g R1 atau yang lebih lama) atau di tingkat database pluggable (Oracle 12g R2 atau yang lebih baru). Di PostgreSQL, himpunan karakter default ditentukan saat instance Cloud SQL untuk PostgreSQL baru dibuat. Setiap database yang dibuat dalam instance tersebut dapat dibuat dengan himpunan karakter yang berbeda. Tata urutan dan klasifikasi karakter dapat ditentukan per kolom tabel.

Contoh

-- Create a database using UTF-8 character set and ja_JP.UTF collation
postgres=> CREATE DATABASE jpdb WITH ENCODING 'UTF8' LC_COLLATE='ja_JP.UTF8' LC_CTYPE='ja_JP.UTF8' TEMPLATE=template0;

-- Query the character set and collation settings of all databases
postgres=> SELECT datname AS DATABASE_NAME, datcollate AS LC_COLLATE, datctype AS LC_CTYPE from pg_database;
 database_name | lc_collate |  lc_ctype
---------------+------------+------------
 cloudsqladmin | en_US.UTF8 | en_US.UTF8
 template0     | en_US.UTF8 | en_US.UTF8
 template1     | en_US.UTF8 | en_US.UTF8
 postgres      | en_US.UTF8 | en_US.UTF8
 jpdb          | ja_JP.UTF8 | ja_JP.UTF8
(5 rows)

-- Alternatively, use psql \l command to query the database settings
postgres=> \l
                                                List of databases
     Name      |       Owner       | Encoding |  Collate   |   Ctype    |            Access privileges
---------------+-------------------+----------+------------+------------+-----------------------------------------
 cloudsqladmin | cloudsqladmin     | UTF8     | en_US.UTF8 | en_US.UTF8 |
 postgres      | cloudsqlsuperuser | UTF8     | en_US.UTF8 | en_US.UTF8 | =Tc/cloudsqlsuperuser                  +
               |                   |          |            |            | cloudsqlsuperuser=CTc/cloudsqlsuperuser+
               |                   |          |            |            | testuser=CTc/cloudsqlsuperuser
 template0     | cloudsqladmin     | UTF8     | en_US.UTF8 | en_US.UTF8 | =c/cloudsqladmin                       +
               |                   |          |            |            | cloudsqladmin=CTc/cloudsqladmin
 template1     | cloudsqlsuperuser | UTF8     | en_US.UTF8 | en_US.UTF8 | =c/cloudsqlsuperuser                   +
               |                   |          |            |            | cloudsqlsuperuser=CTc/cloudsqlsuperuser
-- Specifying column level collation
postgres=> CREATE TABLE test1 (
postgres(>     a text COLLATE "de_DE",
postgres(>     b text COLLATE "es_ES"
postgres(> );

Tabel virtual

Baik tabel virtual sederhana maupun kompleks didukung di PostgreSQL. Untuk opsi pembuatan tabel virtual, ada beberapa perbedaan antara Oracle dan PostgreSQL. Tabel berikut menunjukkan perbedaan tersebut.

Fitur tabel virtual di Oracle Deskripsi Dukungan di Cloud SQL untuk PostgreSQL Pertimbangan konversi
FORCE Membuat tabel virtual tanpa memverifikasi keberadaan tabel/tabel virtual sumber. Tidak Tidak tersedia opsi yang setara.
CREATE OR REPLACE Membuat tabel virtual yang belum ada atau menimpa tabel virtual yang sudah ada. Ya PostgreSQL mendukung perintah CREATE OR REPLACE untuk tabel virtual.
WITH CHECK OPTION Menentukan tingkat penerapan saat menjalankan operasi DML terhadap tabel virtual. Ya Setelan defaultnya adalah CASCADED, yang menyebabkan tabel virtual yang direferensikan juga dievaluasi.

Kata kunci LOCAL menyebabkan hanya tabel virtual saat ini yang dievaluasi.
WITH READ-ONLY Hanya mengizinkan operasi baca di tabel virtual. Operasi DML dilarang. Tidak Solusinya adalah memberikan hak istimewa SELECT atas tabel virtual kepada semua pengguna.
VISIBLE | INVISIBLE (Oracle 12c) Menentukan apakah kolom yang didasarkan pada tabel virtual terlihat atau tidak terlihat oleh pengguna. Tidak Membuat VIEW dengan kolom yang diperlukan saja.

Contoh konversi berikut menunjukkan cara mengonversi tabel virtual dari Oracle ke Cloud SQL PostgreSQL.

-- Create view to retrieve employees from department 100 using the WITH CHECK -- OPTION option
SQL> CREATE OR REPLACE FORCE VIEW vw_emp_dept100
AS
SELECT EMPLOYEE_ID,
       FIRST_NAME,
       LAST_NAME,
       SALARY,
       DEPARTMENT_ID
FROM EMPLOYEES
WHERE DEPARTMENT_ID=100
WITH CHECK OPTION;

-- Perform an UPDATE operation on the VIEW
SQL> UPDATE vw_emp_dept100
     SET salary=salary+1000;

postgres=> CREATE OR REPLACE VIEW vw_emp_dept100
postgres-> AS
postgres-> SELECT EMPLOYEE_ID,
postgres->        FIRST_NAME,
postgres->        LAST_NAME,
postgres->        SALARY,
postgres->        DEPARTMENT_ID
postgres-> FROM EMPLOYEES
postgres-> WHERE DEPARTMENT_ID=100
postgres-> WITH CHECK OPTION;

-- Perform an UPDATE operation on the VIEW
postgres=> UPDATE vw_emp_dept100
postgres-> SET salary=salary+1000;

-- Update one employee department id to 60
postgres=> UPDATE vw_emp_dept100
postgres-> SET DEPARTMENT_ID=60
postgres-> WHERE EMPLOYEE_ID=110;

ERROR:  new row violates check option for view "vw_emp_dept100"
DETAIL:  Failing row contains (110, John, Chen, JCHEN, 515.124.4269, 1997-09-28, FI_ACCOUNT, 9200.00, null, 108, 60).

Pengelolaan akses tabel virtual:

Pemilik tabel virtual harus memiliki hak istimewa atas tabel dasar untuk membuat tabel virtual. Pengguna tabel virtual memerlukan izin SELECT yang sesuai atas tabel virtual. Izin INSERT, UPDATE, dan DELETE yang sesuai atas tabel virtual juga diperlukan saat operasi DML dijalankan terhadap tabel virtual. Dalam kasus mana pun, pengguna tidak memerlukan izin atas tabel dasar.

Langkah berikutnya