Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Mengapa memilih dari prosedur tersimpan tidak didukung dalam database relasional?

TL;DR :kamu bisa pilih dari fungsi (bernilai tabel), atau dari fungsi apa pun di PostgreSQL. Tapi tidak dari prosedur tersimpan.

Inilah penjelasan "intuitif", agak agnostik basis data, karena saya percaya bahwa SQL dan banyak dialeknya terlalu banyak merupakan bahasa/konsep yang tumbuh secara organik sehingga tidak ada penjelasan "ilmiah" yang mendasar untuk ini.

Prosedur vs. Fungsi, secara historis

Saya tidak benar-benar melihat gunanya memilih dari prosedur tersimpan, tetapi saya bias oleh pengalaman bertahun-tahun dan menerima status quo, dan saya tentu melihat bagaimana perbedaan antara prosedur dan fungsi dapat membingungkan dan bagaimana orang ingin mereka menjadi lebih fleksibel dan kuat. Khususnya di SQL Server, Sybase atau MySQL, prosedur dapat mengembalikan jumlah set hasil / jumlah pembaruan yang berubah-ubah, meskipun ini tidak sama dengan fungsi yang mengembalikan tipe yang terdefinisi dengan baik.

Pikirkan prosedur sebagai rutinitas penting (dengan efek samping) dan berfungsi sebagai rutinitas murni tanpa efek samping. Sebuah SELECT pernyataan itu sendiri juga "murni" tanpa efek samping (terlepas dari efek penguncian potensial), jadi masuk akal untuk menganggap fungsi sebagai satu-satunya jenis rutinitas yang dapat digunakan dalam SELECT pernyataan.

Faktanya, anggap fungsi sebagai rutinitas dengan batasan kuat pada perilaku, sedangkan prosedur diizinkan untuk mengeksekusi program sewenang-wenang.

Bahasa 4GL vs. 3GL

Cara lain untuk melihat ini adalah dari perspektif SQL sebagai bahasa pemrograman generasi ke-4 (4GL) . Sebuah 4GL hanya dapat bekerja secara wajar jika sangat dibatasi dalam apa yang dapat dilakukannya. Ekspresi Tabel Umum membuat SQL turing-complete , ya, tetapi sifat deklaratif SQL masih mencegahnya menjadi bahasa tujuan umum dari perspektif praktis sehari-hari.

Prosedur tersimpan adalah cara untuk menghindari batasan ini. Terkadang, Anda ingin menjadi turing lengkap dan praktis. Jadi, prosedur tersimpan menjadi keharusan, memiliki efek samping, bersifat transaksional, dll.

Fungsi tersimpan adalah cara cerdas untuk memperkenalkan beberapa 3GL / fitur bahasa prosedural ke dunia 4GL yang lebih murni dengan harga melarang efek samping di dalamnya (kecuali jika Anda ingin membuka kotak pandora dan memiliki SELECT yang sama sekali tidak terduga pernyataan).

Fakta bahwa beberapa basis data mengizinkan prosedur tersimpannya untuk mengembalikan jumlah set/kursor hasil yang berubah-ubah adalah ciri dari perilaku sewenang-wenang yang diizinkan, termasuk efek samping. Pada prinsipnya, tidak ada yang saya katakan akan mencegah perilaku khusus ini juga dalam fungsi yang tersimpan, tetapi akan sangat tidak praktis dan sulit untuk dikelola jika diizinkan untuk melakukannya dalam konteks SQL, bahasa 4GL.

Jadi:

  • Prosedur dapat memanggil prosedur, fungsi apa pun, dan SQL
  • Fungsi "Murni" dapat memanggil fungsi "murni" dan SQL
  • SQL dapat memanggil fungsi "murni" dan SQL

Tapi:

  • Fungsi "murni" memanggil prosedur menjadi fungsi "tidak murni" (seperti prosedur)

Dan:

  • SQL tidak dapat memanggil prosedur
  • SQL tidak dapat memanggil fungsi "tidak murni"

Contoh fungsi bernilai tabel "murni":

Berikut adalah beberapa contoh penggunaan fungsi "murni" bernilai tabel:

Oracle

CREATE TYPE numbers AS TABLE OF number(10);
/

CREATE OR REPLACE FUNCTION my_function (a number, b number)
RETURN numbers
IS
BEGIN
    return numbers(a, b);
END my_function;
/

Dan kemudian:

SELECT * FROM TABLE (my_function(1, 2))

SQL Server

CREATE FUNCTION my_function(@v1 INTEGER, @v2 INTEGER)
RETURNS @out_table TABLE (
    column_value INTEGER
)
AS
BEGIN
    INSERT @out_table
    VALUES (@v1), (@v2)
    RETURN
END

Dan kemudian

SELECT * FROM my_function(1, 2)

PostgreSQL

Biarkan saya berbicara tentang PostgreSQL.

PostgreSQL luar biasa dan karenanya merupakan pengecualian. Ini juga aneh dan mungkin 50% fiturnya tidak boleh digunakan dalam produksi. Itu hanya mendukung "fungsi", bukan "prosedur", tetapi fungsi-fungsi itu dapat bertindak sebagai apa saja. Simak berikut ini:

CREATE OR REPLACE FUNCTION wow ()
RETURNS SETOF INT
AS $$
BEGIN
    CREATE TABLE boom (i INT);

    RETURN QUERY
    INSERT INTO boom VALUES (1)
    RETURNING *;
END;
$$ LANGUAGE plpgsql;

Efek samping:

  • Sebuah tabel telah dibuat
  • Sebuah catatan dimasukkan

Namun:

SELECT * FROM wow();

Hasil

wow
---
1


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Malas mengambil di MyBatis

  2. Oracle:Cara Tercepat di PL/SQL untuk Melihat apakah Ada Nilai:Daftar, VARRAY, atau Tabel Temp

  3. Daftar pencarian Oracle kata-kata dalam string dan retruen yang sudah ada

  4. Oracle SQL secara otomatis membuat PK VARCHAR yang bertambah

  5. Oracle - Gabung luar kiri dengan klausa where