全部产品
Search
文档中心

Hologres:Prosedur Tersimpan

更新时间:Jul 02, 2025

Prosedur tersimpan adalah kumpulan pernyataan SQL yang telah dikompilasi sebelumnya, disimpan dalam database, dan dapat dipanggil berulang kali. Topik ini menjelaskan cara menggunakan prosedur tersimpan di Hologres.

Batasan

  • Hologres V3.0 dan versi lebih baru mendukung prosedur tersimpan dengan sintaksis PL/pgSQL. Untuk informasi lebih lanjut tentang sintaksis PL/pgSQL, lihat Bahasa Prosedural SQL.

  • Prosedur tersimpan Hologres memungkinkan Anda mengeksekusi beberapa pernyataan bahasa definisi data (DDL) dalam satu transaksi atau beberapa pernyataan bahasa manipulasi data (DML) dalam satu transaksi. Namun, Anda tidak dapat mengeksekusi pernyataan DDL dan DML dalam transaksi yang sama. Untuk informasi lebih lanjut, lihat Kemampuan Transaksi SQL.

  • Prosedur tersimpan tidak mengizinkan pengaturan nilai balikan, sehingga tidak dapat digunakan sebagai fungsi yang ditentukan pengguna (UDF).

Izin

  • Untuk mengeksekusi pernyataan CREATE PROCEDURE, Anda memerlukan izin CREATE pada sebuah database, sama seperti izin yang diperlukan untuk mengeksekusi pernyataan CREATE TABLE. Untuk informasi lebih lanjut, lihat CREATE PROCEDURE.

  • Untuk mengeksekusi pernyataan CREATE OR REPLACE PROCEDURE, Anda memerlukan izin CREATE pada sebuah database serta kepemilikan atas prosedur tersimpan yang akan diganti. Untuk informasi lebih lanjut, lihat CREATE PROCEDURE.

  • Untuk memanggil prosedur tersimpan, Anda memerlukan izin EXECUTE pada prosedur tersebut. Untuk informasi lebih lanjut, lihat CALL.

Sintaksis

Prosedur tersimpan Hologres kompatibel dengan PostgreSQL. Bagian ini menjelaskan sintaksis prosedur tersimpan Hologres.

Membuat prosedur tersimpan

CREATE [ OR REPLACE ] PROCEDURE
    <procedure_name> ([<argname> <argtype>])
LANGUAGE 'plpgsql'
AS <definition>;

Parameter

Deskripsi

procedure_name

Nama dari prosedur tersimpan.

argname

Nama parameter. Parameter ini opsional tergantung pada desain prosedur tersimpan.

argtype

Tipe parameter.

definition

Pernyataan SQL atau blok kode yang mendefinisikan implementasi prosedur tersimpan.

Untuk informasi lebih lanjut tentang parameter, lihat CREATE PROCEDURE.

Memodifikasi prosedur tersimpan

ALTER PROCEDURE <procedure_name> ([<argname> <argtype>])
    OWNER TO <new_owner> | CURRENT_USER | SESSION_USER;

Parameter

Deskripsi

new_owner

Nama pengguna baru.

CURRENT_USER

Nama pengguna saat ini.

SESSION_USER

Nama pengguna sesi.

Untuk informasi lebih lanjut tentang parameter, lihat ALTER PROCEDURE.

Menghapus prosedur tersimpan

DROP PROCEDURE [ IF EXISTS ] <procedure_name> ([<argname> <argtype>]); 

Untuk informasi lebih lanjut tentang parameter, lihat DROP PROCEDURE.

Memanggil prosedur tersimpan

CALL <procedure_name> ([<argument>]);

Parameter

Deskripsi

argument

Parameter yang dibutuhkan oleh prosedur tersimpan. Parameter ini opsional tergantung pada desain prosedur tersimpan.

Untuk informasi lebih lanjut tentang parameter, lihat CALL.

Contoh

  • Contoh 1: Membuat dan memanggil prosedur tersimpan yang berisi beberapa pernyataan DDL dalam satu transaksi.

    1. Membuat prosedur tersimpan.

      CREATE OR REPLACE PROCEDURE procedure_1()
      LANGUAGE 'plpgsql'
      AS $$
      BEGIN
          --- TXN1 --- 
          CREATE TABLE a1(key int);
          CREATE TABLE a2(key int);
          COMMIT; 
      
          --- TXN2 ---
          CREATE TABLE a3(key int);
          CREATE TABLE a4(key int);
          ROLLBACK;
      END; 
      $$;
    2. Memanggil prosedur tersimpan. Tabel a1 dan a2 dibuat, sedangkan tabel a3 dan a4 tidak dibuat.

      CALL procedure_1();
  • Contoh 2: Membuat dan memanggil prosedur tersimpan yang berisi beberapa pernyataan DML dalam satu transaksi.

    1. Membuat prosedur tersimpan.

      CREATE OR REPLACE PROCEDURE procedure_2()
      LANGUAGE 'plpgsql'
      AS $$
      BEGIN
          INSERT INTO a1 VALUES(1);
          INSERT INTO a2 VALUES(2);
          ROLLBACK;
      END;
      $$;
      
      CREATE OR REPLACE PROCEDURE procedure_3()
      LANGUAGE 'plpgsql'
      AS $$
      BEGIN
          INSERT INTO a1 VALUES(1);
          INSERT INTO a2 VALUES(2);
      END;
      $$;
    2. Memanggil prosedur tersimpan.

      • Memanggil procedure_2. Operasi rollback didukung, dan data tidak ditulis.

        -- Aktifkan fitur transaksi DML.
        SET hg_experimental_enable_transaction = ON;
        
        -- Panggil prosedur tersimpan.
        CALL procedure_2();
      • Memanggil procedure_3. Data ditulis.

        -- Aktifkan fitur transaksi DML.
        SET hg_experimental_enable_transaction = ON;
        
        -- Panggil prosedur tersimpan.
        CALL procedure_3();
  • Contoh 3: Membuat dan memanggil prosedur tersimpan yang berisi pernyataan DDL dan DML.

    1. Membuat prosedur tersimpan di mana pernyataan DDL dan DML dilakukan secara terpisah. Hologres tidak mengizinkan Anda mengeksekusi pernyataan DDL dan DML dalam transaksi yang sama.

      CREATE OR REPLACE PROCEDURE procedure_4()
      LANGUAGE 'plpgsql'
      AS $$
      BEGIN
          INSERT INTO a1 VALUES(1);
          COMMIT;	
          CREATE TABLE bb(key int);
          COMMIT;	
          INSERT INTO a1 VALUES(2);
          INSERT INTO bb VALUES(1);    
          COMMIT;	
      END;
      $$;
    2. Memanggil prosedur tersimpan. Pembuatan tabel dan penulisan data berhasil.

      -- Aktifkan fitur transaksi DML.
      SET hg_experimental_enable_transaction = ON;
      
      -- Panggil prosedur tersimpan.
      CALL procedure_4();
  • Contoh 4: Membuat dan memanggil prosedur tersimpan yang berisi klausa umum, seperti klausa untuk mendefinisikan parameter input, variabel antara, loop, kondisi IF, dan penanganan kesalahan.

    1. Membuat prosedur tersimpan.

      CREATE OR REPLACE PROCEDURE procedure_5(input text)
      LANGUAGE 'plpgsql'
      AS $$
      -- Definisikan variabel antara.
      DECLARE
      sql1 text;
      BEGIN
          -- Masukkan baris data ke dalam tabel parameter input.
          EXECUTE 'insert into ' || input || ' values(1);';
          COMMIT;
      
          -- Buat tabel bernama a3.
          CREATE TABLE a3(key int);
          COMMIT;
      
          -- Gunakan variabel antara untuk menulis catatan data ke tabel a3.
          sql1 = 'insert into a3 values(1);';
          EXECUTE sql1;
      
          -- Definisikan loop FOR.
          FOR i IN 1..10 LOOP
              BEGIN
                  -- i=1 sudah ada di tabel, dan satu catatan dicatat.
                  IF i IN (SELECT KEY FROM a3) THEN
                      RAISE NOTICE 'Data sudah ada.';
                  -- Nilai lain tidak ada di tabel. Sesi mencoba menulis nilai-nilai tersebut ke tabel dan menggunakan RAISE EXCEPTION untuk melempar pengecualian. Kemudian, operasi commit dilakukan.
                  ELSE
                      INSERT INTO a3 VALUES(i);
                      RAISE EXCEPTION 'HG_PLPGSQL_NEED_RETRY';
                      COMMIT; 
                  END IF;
              -- Pengecualian yang dilaporkan dicatat.
              EXCEPTION 
                  WHEN OTHERS THEN
                      RAISE NOTICE 'Tangkap kesalahan.';
              END;
          END LOOP;
      
      END;
      $$;
    2. Memanggil prosedur tersimpan. Hanya nilai 1 yang ditulis ke tabel a3, dan log terkait dicatat.

      -- Aktifkan fitur transaksi DML.
      SET hg_experimental_enable_transaction = ON;
      
      -- Panggil prosedur tersimpan.
      CALL procedure_5('a1');

Kelola prosedur tersimpan

  • Query prosedur tersimpan yang telah dibuat.

    SELECT
        p.proname AS procedure_name,
        pg_get_function_identity_arguments(p.oid) AS argument_types,
        REPLACE(pg_get_functiondef(p.oid),'$procedure$','$$') AS procedure_detail,
        n.nspname AS schema_name,
        r.rolname AS owner_name,
        d.description AS description
    FROM
        pg_proc p
        INNER JOIN pg_namespace n ON p.pronamespace = n.oid
        INNER JOIN pg_roles r ON p.proowner = r.oid
        LEFT JOIN pg_description d ON p.oid = d.objoid
    WHERE
        r.rolname != 'holo_admin'
        AND p.prokind = 'p'
    ORDER BY
        n.nspname,
        p.proname;
  • Query definisi prosedur tersimpan.

    SELECT pg_get_functiondef('<procedure_name>'::regproc);

Pemecahan masalah

Hologres adalah sistem terdistribusi. Oleh karena itu, node frontend (FE) dari instance Hologres diterapkan secara terdistribusi. Metadata dari node FE harus disinkronkan secara real-time. Jika operasi DDL dilakukan pada tabel tetapi metadata belum disinkronkan, operasi DDL mungkin gagal. Dalam hal ini, Hologres secara otomatis mencoba ulang operasi DDL ketika fitur coba ulang otomatis didukung. Tidak diperlukan operasi manual. Namun, dalam prosedur tersimpan, pesan kesalahan "HG_PLPGSQL_NEED_RETRY" dikembalikan karena fitur coba ulang otomatis tidak didukung.

Kami merekomendasikan Anda untuk secara manual mendefinisikan logika coba ulang untuk tabel di mana operasi DDL sering dilakukan dalam prosedur tersimpan. Ini membantu mencegah pesan kesalahan dilaporkan secara berulang. Contoh kode:

CREATE OR REPLACE PROCEDURE procedure_6()
LANGUAGE 'plpgsql'
AS $$
BEGIN
    WHILE TRUE LOOP
        BEGIN
            -- Sesi mencoba mengeksekusi pernyataan DDL dan keluar dari loop ketika eksekusi berhasil.
            CREATE TABLE a3(key int);
            COMMIT;
            EXIT;
        EXCEPTION
            -- Jika pesan kesalahan "HG_PLPGSQL_NEED_RETRY" dilaporkan, sesi mencatat kesalahan dan mencoba ulang operasi secara otomatis.
            WHEN HG_PLPGSQL_NEED_RETRY THEN 
                RAISE NOTICE 'DDL perlu coba ulang';
        END;
    END LOOP;
END;
$$;