T-SQL - berfungsi dengan parameter default

155

Saya punya skrip ini:

CREATE FUNCTION dbo.CheckIfSFExists(@param1 INT, @param2 BIT = 1 )
RETURNS BIT
AS
BEGIN
    IF EXISTS ( bla bla bla )
        RETURN 1;
    RETURN 0;
END
GO

Saya ingin menggunakannya dalam prosedur dengan cara ini:

IF dbo.CheckIfSFExists( 23 ) = 0
    SET @retValue = 'bla bla bla';

Tapi saya mendapatkan kesalahan:

Jumlah argumen yang disediakan untuk prosedur atau fungsi dbo.CheckIfSFExists tidak mencukupi.

Mengapa itu tidak berhasil?

nirmus
sumber

Jawaban:

227

Anda harus menyebutnya seperti ini

SELECT dbo.CheckIfSFExists(23, default)

Dari Technet :

Ketika parameter fungsi memiliki nilai default, kata kunci DEFAULT harus ditentukan ketika fungsi dipanggil untuk mengambil nilai default. Perilaku ini berbeda dari menggunakan parameter dengan nilai default dalam prosedur tersimpan di mana menghilangkan parameter juga menyiratkan nilai default. Pengecualian untuk perilaku ini adalah ketika menjalankan fungsi skalar dengan menggunakan pernyataan EXECUTE. Saat menggunakan EXECUTE, kata kunci DEFAULT tidak diperlukan.

SQLMenace
sumber
80
Melihat ini saya frustrasi. Saya tidak mendapatkan keuntungan dari defaultkonsep di sini ... Saya harus pergi dan mengubah semua tempat sekarang.
LCJ
8
@ Lijo, Anda masih mendapatkan keuntungan karena tidak menduplikasi nilai default konkret Anda di setiap panggilan.
Frédéric
9
Karena kita tidak diizinkan untuk overlay, dan "default" dengan demikian memiliki kegunaan yang terbatas, seringkali pendekatan terbaik adalah membuat versi baru dengan akhiran (katakanlah CheckIfSFExistsEX di sini) dengan parameter tambahan, dan mengubah fungsi asli menjadi hanya memanggil versi yang diperluas dengan parameter "default". Dengan cara ini SEMUA kode yang ada berfungsi, dan Anda hanya memiliki satu tempat untuk dipelihara.
Eske Rahn
39

Anda dapat menyebutnya tiga cara - dengan parameter, dengan DEFAULT dan melalui EXECUTE

SET NOCOUNT ON;

DECLARE
@Table  SYSNAME = 'YourTable',
@Schema SYSNAME = 'dbo',
@Rows   INT;

SELECT dbo.TableRowCount( @Table, @Schema )

SELECT dbo.TableRowCount( @Table, DEFAULT )

EXECUTE @Rows = dbo.TableRowCount @Table

SELECT @Rows
Douglas Osborne
sumber
11
Mengapa DEFAULTkata kunci diperlukan di pilih, tetapi dapat dihilangkan dalam mengeksekusi? Ini menyebalkan: / Semoga ini akan diperbaiki suatu hari nanti.
Misiu
@Misiu, itu bukan sesuatu yang perlu "diperbaiki". Itu dengan desain. Saya membaca banyak alternatif untuk mendekati tujuan "ideal" dengan hanya dapat memanggil fungsi tanpa menentukan setiap argumen, tetapi saya tidak melihat penjelasan yang jelas mengapa itu diperlukan. Kode harus jelas dan salah satu strategi untuk mencapai itu adalah membutuhkan pembuat kode untuk selalu sadar bahwa "hei, Anda memanggil fungsi yang TIDAK memiliki argumen ini dan ini, yang kebetulan memiliki nilai default. Jangan lupa bahwa nilai standar DAPAT DIUBAH ". Jadi, IMO, ini adalah "hal buruk" yang baik untuk dimiliki.
Gustavo Pinsard
16

Dengan fungsi yang ditentukan pengguna, Anda harus mendeklarasikan setiap parameter, bahkan jika mereka memiliki nilai default.

Berikut ini akan dieksekusi dengan sukses:

IF dbo.CheckIfSFExists( 23, default ) = 0
    SET @retValue = 'bla bla bla;
Singkat
sumber
-1

Salah satu cara mengatasi masalah ini adalah dengan menggunakan prosedur tersimpan dengan parameter output.

exec sp_mysprocname @returnvalue output, @firstparam = 1, @ secondparam = 2

nilai yang Anda tidak lulus secara default ke default yang ditetapkan dalam prosedur tersimpan itu sendiri. Dan Anda bisa mendapatkan hasil dari variabel output Anda.

Jereme Guenther
sumber
1
Mengubah fungsi Anda ke prosedur tersimpan pada umumnya bukan solusi yang baik, karena prosedur tersimpan tidak dapat dipanggil dari dalam kueri, tetapi fungsi dapat.
Blade
Benar, namun tidak semua blok kode perlu dipanggil dari dalam kueri. Telah ditunjukkan bahwa sql tidak memiliki metode yang baik dalam menangani nilai-nilai default untuk fungsi-fungsi (menggunakan kata kunci default hampir sama bermanfaatnya dengan menambahkan nilai). Ini bukan solusi umum yang baik, tetapi bekerja dengan baik dalam kasus penggunaan tertentu.
Jereme Guenther
Orang-orang terus menandainya, namun saya tetap menggunakannya. Jika Anda perlu memiliki potongan kode yang dapat digunakan kembali, itu tidak akan dipanggil di dalam kueri, dan Anda menginginkan fleksibilitas parameter opsional sejati dengan nilai default, prosedur tersimpan masih lebih baik daripada fungsi.
Jereme Guenther
1
Menggunakan prosedur tersimpan tidak berarti menggunakannya alih-alih menggunakan fungsi - ini bisa berarti menggunakan prosedur tersimpan sebagai pembungkus fungsi. Saya sering menggunakan teknik ini; yang standar kata kunci sekarang tersembunyi di dalam proc. Saya pikir ide ini baik-baik saja. Ini juga memungkinkan saya membuat default yang lebih rumit jika saya mau - terpisah dari fungsi, yang dapat dibiarkan dalam keadaan yang lebih murni.
J Bryan Harga