Cara memeriksa apakah suatu fungsi ada di database SQL

141

Saya perlu mencari tahu apakah suatu fungsi ada di database, sehingga saya bisa melepaskannya dan membuatnya lagi. Ini pada dasarnya harus menjadi sesuatu seperti kode berikut yang saya gunakan untuk prosedur tersimpan:

IF EXISTS (
     SELECT  *
     FROM    dbo.sysobjects
     WHERE   id = OBJECT_ID(N'[dbo].[SP_TEST]')
             AND OBJECTPROPERTY(id, N'IsProcedure') = 1 )
Dr Greenthumb
sumber

Jawaban:

210

Inilah yang digunakan SSMS saat Anda membuat skrip menggunakan DROP and CREATEopsi

IF EXISTS (SELECT *
           FROM   sys.objects
           WHERE  object_id = OBJECT_ID(N'[dbo].[foo]')
                  AND type IN ( N'FN', N'IF', N'TF', N'FS', N'FT' ))
  DROP FUNCTION [dbo].[foo]

GO 

Pendekatan untuk menerapkan perubahan ini berarti Anda perlu membuat ulang semua izin pada objek sehingga Anda dapat mempertimbangkan ALTER-ing jika Ada.

Martin Smith
sumber
17
Membuat saya semakin bertanya - tanya mengapa tidak ada tampilan katalog sistem sys.functions .....
marc_s
61

Saya cenderung menggunakan Information_Schema:

IF EXISTS ( SELECT  1
            FROM    Information_schema.Routines
            WHERE   Specific_schema = 'dbo'
                    AND specific_name = 'Foo'
                    AND Routine_Type = 'FUNCTION' ) 

untuk fungsi, dan perubahan Routine_Typeuntuk prosedur yang tersimpan

IF EXISTS ( SELECT  1
            FROM    Information_schema.Routines
            WHERE   Specific_schema = 'dbo'
                    AND specific_name = 'Foo'
                    AND Routine_Type = 'PROCEDURE' ) 
Law Metzler
sumber
2
Keren saya mencari sesuatu seperti ini dan tidak pernah menemukannya. Saya yakin lebih baik menggunakan information_schema secara umum karena tidak terikat pada RDBMS tertentu. (btw gagasan tentang kompatibel lintas platform berasal dari jawaban ini: stackoverflow.com/a/14290099/420667 )
pengguna420667
40

Mengapa tidak hanya:

IF object_id('YourFunctionName', 'FN') IS NOT NULL
BEGIN
    DROP FUNCTION [dbo].[YourFunctionName]
END
GO

Argumen kedua object_idadalah opsional, tetapi dapat membantu mengidentifikasi objek yang benar. Ada banyak kemungkinan nilai untuk argumen tipe ini, khususnya:

  • FN: Fungsi skalar
  • JIKA: Fungsi nilai tabel sebaris
  • TF: Fungsi-nilai-tabel
  • FS: Fungsi skalar Assembly (CLR)
  • FT: Fungsi nilai tabel Assembly (CLR)
Kapé
sumber
4
Secara teknis ini bisa gagal karena hanya memeriksa bahwa ada objek dengan nama itu. Bukan berarti ada objek dan itu adalah fungsi. EG Jika CREATE TABLE YourFunctionName(X INT);kemudian menjalankan kode tersebut akan gagal.
Martin Smith
1
@MartinSmith: Mudah dibuat kuat. Cukup gunakan object_id('YourFunction', 'FN')atau penanda lain (argumen kedua) yang menjelaskan jenis objek yang Anda maksud.
darlove
@darlove menggunakan 'FN' sebagai parameter kedua mungkin tidak berfungsi. Saya baru saja belajar. 'FN' berarti fungsi skalar. Tautan ini memberi tahu Anda nilai parameter berbeda yang dapat Anda berikan sqlhints.com/tag/how-to-check-if-function-exists . Saya tetap menggunakan 'FN' untuk memeriksa fungsi nilai Tabel yang ada, dan tidak berhasil. Saya harus menggunakan 'TF'
user12345
9

Saya telah menemukan Anda dapat menggunakan pendekatan yang sangat tidak bertele-tele dan langsung untuk memeriksa keberadaan berbagai objek SQL Server dengan cara ini:

IF OBJECTPROPERTY (object_id('schemaname.scalarfuncname'), 'IsScalarFunction') = 1
IF OBJECTPROPERTY (object_id('schemaname.tablefuncname'), 'IsTableFunction') = 1
IF OBJECTPROPERTY (object_id('schemaname.procname'), 'IsProcedure') = 1

Ini didasarkan pada fungsi OBJECTPROPERTY yang tersedia di SQL 2005+. Artikel MSDN dapat ditemukan di sini .

Fungsi OBJECTPROPERTY menggunakan tanda tangan berikut:

OBJECTPROPERTY ( id , property ) 

Anda meneruskan nilai literal ke dalam parameter properti, yang menunjukkan tipe objek yang Anda cari. Ada banyak sekali daftar nilai yang dapat Anda berikan.

Jeremy
sumber
Saya pikir akan lebih mudah untuk melihat kesederhanaan jawaban ini jika menyertakan contoh if / drop yang lengkap.
Jonathan
7

Saya tahu utas ini sudah tua tetapi saya hanya ingin menambahkan jawaban ini untuk mereka yang percaya ini lebih aman Alterdaripada Dropdan Create. Di bawah ini akan Altermenjadi Functionjika itu ada atau Createjika tidak:

  IF NOT EXISTS (SELECT *
               FROM   sys.objects
               WHERE  object_id = OBJECT_ID(N'[dbo].[foo]')
                      AND type IN ( N'FN', N'IF', N'TF', N'FS', N'FT' ))
       EXEC('CREATE FUNCTION [dbo].[foo]() RETURNS INT AS BEGIN RETURN 0 END')
  GO
  ALTER FUNCTION [dbo].[foo]
  AS
  ...
jamiedanq
sumber
2
Saya suka ini, tapi menurut saya seharusnya "ALTER FUNCTION", bukan?
Erik
Saya sukaALTER OR CREATE
AgentFire