Fungsi vs Prosedur Tersimpan

88

Katakanlah saya harus mengimplementasikan sepotong kode T-SQL yang harus mengembalikan tabel sebagai hasilnya. Saya dapat mengimplementasikan fungsi nilai tabel atau prosedur tersimpan yang mengembalikan sekumpulan baris. Apa yang harus saya gunakan?

Singkatnya, yang ingin saya ketahui adalah:

Apa perbedaan utama antara fungsi dan prosedur tersimpan? Pertimbangan apa yang harus saya pertimbangkan untuk menggunakan salah satunya?

Auron
sumber
1
Ini sepertinya jawaban yang sempurna: stackoverflow.com/a/1179778/365188
Ozair Kafray

Jawaban:

51

Jika Anda cenderung ingin menggabungkan hasil dari potongan kode ini dengan tabel lain, maka jelas fungsi nilai tabel akan memungkinkan Anda untuk membuat hasil dalam satu pernyataan SELECT.

Umumnya, ada hierarki (View <TV Function <Stored Proc). Anda dapat melakukan lebih banyak pada masing-masingnya, tetapi kemampuan untuk menyusun keluaran, dan agar pengoptimal benar-benar terlibat menurun seiring dengan peningkatan fungsionalitas.

Jadi gunakan salah satu yang minimal memungkinkan Anda untuk mengekspresikan hasil yang Anda inginkan.

Damien_The_Tidak percaya
sumber
50

Fungsi harus deterministik, dan tidak dapat digunakan untuk membuat perubahan pada database, sedangkan prosedur tersimpan memungkinkan Anda untuk melakukan penyisipan dan pembaruan, dll.

Anda harus membatasi penggunaan fungsi, karena fungsi tersebut menimbulkan masalah skalabilitas yang sangat besar untuk kueri yang besar dan kompleks. Mereka menjadi semacam "kotak hitam" untuk pengoptimal kueri, dan Anda akan melihat perbedaan besar dalam kinerja antara menggunakan fungsi dan cukup memasukkan kode ke dalam kueri.

Tapi mereka pasti berguna untuk pengembalian nilai tabel dalam kasus yang sangat spesifik.

Jika Anda perlu mengurai daftar yang dipisahkan koma, untuk mensimulasikan pengalihan array ke prosedur, fungsi dapat mengubah daftar menjadi tabel untuk Anda. Ini adalah praktik umum dengan Sql Server 2005, karena kita belum bisa meneruskan tabel ke prosedur tersimpan (kita bisa dengan 2008).

Eric Z Beard
sumber
1
Tetapi Anda DAPAT mengirim XML ke prosedur yang tersimpan: stackoverflow.com/questions/144550/…
cllpse
2
Salah, sebagian besar fungsi server SQL tidak bersifat deterministik, seperti getdate di server MS-SQL. Hanya fungsi ODBC yang merupakan fungsi kanonik (= jauh lebih cepat + dapat diindeks) ... Tetapi Anda sangat benar, seseorang harus membatasi penggunaan fungsi dalam kueri sebanyak mungkin untuk alasan kinerja.
Stefan Steiger
45

Dari dokumen :

Jika prosedur tersimpan memenuhi kriteria berikut, itu adalah kandidat yang baik untuk ditulis ulang sebagai fungsi nilai tabel:

  • Logikanya dapat diekspresikan dalam pernyataan SELECT tunggal tetapi merupakan prosedur tersimpan, bukan tampilan, hanya karena kebutuhan parameter.

  • Prosedur tersimpan tidak melakukan operasi pembaruan, kecuali variabel tabel.

  • Tidak perlu pernyataan EXECUTE dinamis.

  • Prosedur tersimpan mengembalikan satu set hasil.

  • Tujuan utama dari prosedur tersimpan adalah untuk membangun hasil antara yang akan dimuat ke dalam tabel sementara, yang kemudian ditanyai dalam pernyataan SELECT.

Christoffer Lette
sumber
12

Saya akan menulis beberapa perbedaan menarik antara prosedur dan fungsi yang tersimpan.

  • Kami dapat menggunakan fungsi dalam kueri pemilihan tetapi kami tidak dapat menggunakan prosedur tersimpan dalam kueri pemilihan.
  • Kami tidak dapat menggunakan fungsi non deterministik dalam Fungsi tetapi kami dapat menggunakan fungsi non deterministik dalam prosedur tersimpan. Sekarang muncul pertanyaan, apa itu fungsi non deterministik .. Jawabnya: -

    Fungsi non deterministik adalah fungsi yang mengembalikan keluaran berbeda untuk nilai masukan yang sama pada waktu berbeda, seperti getdate (). Itu selalu mengembalikan nilai yang berbeda setiap kali dijalankan.

    Pengecualian:-

    Versi sebelumnya dari sql server sebelum sql 2000 tidak memungkinkan untuk menggunakan fungsi getdate () dalam fungsi yang ditentukan pengguna, tetapi versi 2005 dan seterusnya memungkinkan kita untuk menggunakan fungsi getdate () dalam fungsi yang ditentukan pengguna.

    Newid () adalah contoh lain dari fungsi non deterministik tetapi tidak dapat digunakan dalam fungsi yang ditentukan pengguna tetapi kita dapat menggunakannya dalam prosedur tersimpan.

  • Kita dapat menggunakan pernyataan DML (masukkan, perbarui, hapus) dalam prosedur tersimpan tetapi kita tidak dapat menggunakan pernyataan DML dalam fungsi pada tabel fisik atau tabel permanen. Jika kita ingin melakukan operasi DML dalam fungsi kita bisa melakukannya pada variabel tabel bukan pada tabel permanen.

  • Kami tidak dapat menggunakan penanganan kesalahan dalam fungsi tetapi kami dapat melakukan penanganan kesalahan dalam prosedur yang tersimpan.

Neeraj Kumar Yadav
sumber
Mengapa operasi DML didukung dalam fungsi MySQL?
Joey Pinto
@Tokopedia Karena myNONsql bukan keluhan SQL. Tentu, ini memiliki tambahan, tetapi bukan dasar-dasarnya.
PerformanceDBA
8
  1. Prosedur dapat mengembalikan nilai nol atau n sedangkan fungsi dapat mengembalikan satu nilai yang wajib.

  2. Prosedur dapat memiliki parameter input / output untuk itu sedangkan fungsi hanya dapat memiliki parameter input.

  3. Prosedur memungkinkan pilih serta pernyataan DML di dalamnya sedangkan fungsi hanya memungkinkan pernyataan pilih di dalamnya.

  4. Fungsi dapat dipanggil dari prosedur sedangkan prosedur tidak dapat dipanggil dari fungsi.

  5. Pengecualian dapat ditangani oleh blok coba-tangkap dalam suatu prosedur sedangkan blok coba-tangkap tidak dapat digunakan dalam suatu fungsi.

  6. Kita bisa pergi ke manajemen transaksi dalam prosedur sedangkan kita tidak bisa berfungsi.

  7. Prosedur tidak dapat digunakan dalam pernyataan pilih sedangkan fungsi dapat disematkan dalam pernyataan pilih.

  8. UDF (User Defined function) dapat digunakan dalam pernyataan SQL di mana pun di bagian WHERE/ HAVING/ SELECTsedangkan prosedur tersimpan tidak bisa.

  9. UDF yang mengembalikan tabel dapat diperlakukan sebagai kumpulan baris lain. Ini dapat digunakan JOINdengan tabel lain.

  10. UDF sebaris dapat dianggap sebagai tampilan yang mengambil parameter dan dapat digunakan dalam JOINoperasi kumpulan baris dan lainnya.

nathan1138
sumber
6

Jika Anda memiliki sebuah fungsi, Anda dapat menggunakannya sebagai bagian dari pernyataan SQL Anda, misalnya

SELECT function_name(field1) FROM table

Ini tidak bekerja dengan cara ini untuk prosedur yang disimpan.

Ilya Kochetov
sumber
1
Saya pikir dia berbicara tentang fungsi yang mengembalikan nilai tabel.
wcm
1
Baiklah, saya berbicara secara umum. Tetapi untuk kasus khusus saya, saya sekarang berada di antara prosedur tersimpan atau fungsi bernilai tabel.
Auron
5

Saya menjalankan beberapa tes dengan sedikit logika yang berjalan lama, dengan sedikit kode yang sama (pernyataan SELECT panjang) yang berjalan di Fungsi Table Valued dan Prosedur Tersimpan, dan EXEC / SELECT lurus, dan masing-masing dilakukan secara identik.

Menurut pendapat saya, selalu gunakan Fungsi Nilai Tabel daripada prosedur tersimpan untuk mengembalikan kumpulan hasil, karena ini membuat logika lebih mudah dan dapat dibaca dalam kueri yang kemudian bergabung dengannya, dan memungkinkan Anda untuk menggunakan kembali logika yang sama. Untuk menghindari terlalu banyak hit kinerja, saya sering menggunakan parameter "opsional" (yaitu Anda dapat meneruskan NULL ke mereka) untuk mengaktifkan fungsi untuk mengembalikan hasil yang ditetapkan menjadi lebih cepat, misalnya:

CREATE FUNCTION dbo.getSitePermissions(@RegionID int, @optPersonID int, optSiteID int)
AS
RETURN 
    SELECT DISTINCT SiteID, PersonID
    FROM dbo.SiteViewPermissions
    WHERE (@optPersonID IS NULL OR @optPersonID = PersonID)
    AND (@optSiteID IS NULL OR @optSiteID = SiteID)
    AND @RegionID = RegionID

Dengan cara ini Anda dapat menggunakan fungsi ini untuk banyak situasi yang berbeda, dan tidak mengalami penurunan kinerja yang besar. Saya yakin ini lebih efisien daripada memfilter sesudahnya:

SELECT * FROM dbo.getSitePermissions(@RegionID) WHERE SiteID = 1

Saya telah menggunakan teknik ini dalam beberapa fungsi, terkadang dengan daftar panjang parameter "opsional" dari jenis ini.

Paul Grimshaw
sumber
4

Saya pribadi menggunakan fungsi nilai tabel ketika semua yang saya kembalikan adalah tabel tunggal tanpa pengaruh. Pada dasarnya saya memperlakukan mereka seperti pandangan berparameter.

Jika saya memerlukan beberapa kumpulan data yang dikembalikan atau jika akan ada nilai yang diperbarui dalam tabel, saya menggunakan prosedur tersimpan.

2 sen saya

wcm
sumber
4

Seperti disebutkan di atas, fungsi lebih dapat dibaca / disusun / mendokumentasikan sendiri, tetapi secara umum kurang berkinerja, dan dapat menjadi sangat kurang berkinerja jika Anda terbawa dengan mereka dalam gabungan seperti

SELECT *
FROM dbo.tvfVeryLargeResultset1(@myVar1) tvf1
INNER JOIN dbo.tvfVeryLargeResultset1(@myVar2) tvf2
    ON (tvf1.JoinId = tvf2.JoinId)

Seringkali, Anda hanya perlu menerima redundansi kode yang dapat dihilangkan tvf (dengan biaya kinerja yang tidak dapat diterima.)

Satu hal lain yang belum saya lihat disebutkan adalah bahwa Anda tidak dapat menggunakan tabel temporer yang mengubah status database di dalam tvf multi-pernyataan. Mekanisme yang paling setara secara fungsional untuk tabel temp adalah perubahan non-status, dalam variabel tabel memori, dan untuk kumpulan data besar, tabel temp kemungkinan akan lebih berkinerja daripada variabel tabel. (Alternatif lain termasuk tabel dinamis & ekspresi nilai tabel umum, tetapi pada beberapa tingkat kerumitan, ini berhenti menjadi pilihan yang baik IMO.)

6. George Jetson
sumber
1

Saya akan menguji keduanya. Sepertinya pendekatan sp atau tabel turunan akan jauh lebih cepat daripada fungsi dan jika demikian pendekatan itu harus digunakan. Secara umum saya menghindari fungsi karena mereka bisa menjadi babi kinerja.

HLGEM
sumber
1

Itu tergantung :) Jika Anda ingin menggunakan hasil nilai tabel di prosedur lain, Anda lebih baik menggunakan Fungsi TableValued. Jika hasilnya untuk klien, proses yang disimpan biasanya merupakan cara yang lebih baik untuk digunakan.

edosoft.dll
sumber
-1

Prosedur yang disimpan adalah kueri yang telah dikompilasi sebelumnya yang dieksekusi lebih cepat dan menyimpan dari injeksi sql. Mereka dapat mengembalikan nilai 0 atau N. Kami dapat melakukan operasi DML di dalam prosedur yang tersimpan. Kita bisa menggunakan fungsi di dalam prosedur dan bisa menggunakan fungsi di kueri pemilihan. Fungsi digunakan untuk mengembalikan nilai apa pun dan operasi DML tidak dimungkinkan dalam fungsi. fungsi terdiri dari dua jenis skalar dan nilai tabel. fungsi skalar mengembalikan satu nilai, fungsi bernilai tabel yang digunakan untuk mengembalikan baris tabel.

Harish Madaan
sumber
Ini adalah pertanyaan yang sangat lama dengan sejumlah besar jawaban, banyak di antaranya (termasuk jawaban yang diterima) mendapat suara positif. Sebelum menambahkan jawaban lain ke utas seperti itu, Anda harus bertanya pada diri sendiri, "kekurangan apa dari semua jawaban yang ada itu sehingga saya harus menulis yang lain?"
APC