วิธีตรวจสอบว่ามีฟังก์ชันอยู่ในฐานข้อมูล SQL หรือไม่


141

ฉันต้องการตรวจสอบว่ามีฟังก์ชันอยู่ในฐานข้อมูลหรือไม่เพื่อที่ฉันจะได้ทิ้งมันและสร้างขึ้นมาใหม่ โดยพื้นฐานแล้วควรเป็นรหัสต่อไปนี้ที่ฉันใช้สำหรับขั้นตอนการจัดเก็บ:

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

คำตอบ:


210

นี่คือสิ่งที่ SSMS ใช้เมื่อคุณเขียนสคริปต์โดยใช้DROP and CREATEตัวเลือก

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 

แนวทางในการปรับใช้การเปลี่ยนแปลงนี้หมายความว่าคุณต้องสร้างสิทธิ์ทั้งหมดบนอ็อบเจ็กต์ใหม่ดังนั้นคุณอาจพิจารณาALTER- หากมีอยู่แทน


17
ทำให้ฉันสงสัยมากยิ่งขึ้นว่าทำไมไม่มีมุมมองแค็ตตาล็อกระบบsys.functions .....
marc_s

61

ฉันมักจะใช้ Information_Schema:

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

สำหรับฟังก์ชันและการเปลี่ยนแปลงRoutine_Typeสำหรับโพรซีเดอร์ที่เก็บไว้

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

2
เจ๋งฉันกำลังมองหาอะไรแบบนี้และไม่เคยเจอ ฉันเชื่อว่าการใช้ information_schema โดยทั่วไปจะดีกว่าเนื่องจากไม่ได้เชื่อมโยงกับ RDBMS ที่เฉพาะเจาะจง (btw ความคิดของการเข้ากันได้ข้ามแพลตฟอร์มมาจากคำตอบนี้: stackoverflow.com/a/14290099/420667 )
user420667

40

ทำไมไม่เพียง:

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

อาร์กิวเมนต์ที่สองของobject_idเป็นทางเลือก แต่สามารถช่วยระบุวัตถุที่ถูกต้องได้ มีค่าที่เป็นไปได้มากมายสำหรับอาร์กิวเมนต์ประเภทนี้โดยเฉพาะ:

  • FN: ฟังก์ชัน Scalar
  • IF: ฟังก์ชันค่าตารางแบบอินไลน์
  • TF: ตารางมูลค่าฟังก์ชั่น
  • FS: แอสเซมบลี (CLR) ฟังก์ชันสเกลาร์
  • FT: ฟังก์ชันค่าตาราง Assembly (CLR)

4
ในทางเทคนิคอาจล้มเหลวเนื่องจากตรวจสอบว่ามีวัตถุชื่อนั้นเท่านั้น ไม่ใช่ว่ามีวัตถุและเป็นฟังก์ชัน EG ถ้าCREATE TABLE YourFunctionName(X INT);รันโค้ดแล้วจะล้มเหลว
Martin Smith

1
@MartinSmith: ง่ายต่อการสร้างความแข็งแกร่ง เพียงใช้object_id('YourFunction', 'FN')หรือตัวกำหนดอื่น ๆ (อาร์กิวเมนต์ที่สอง) ที่ทำให้ชัดเจนว่าคุณกำลังอ้างถึงวัตถุประเภทใด
darlove

@darlove โดยใช้ 'FN' เป็นพารามิเตอร์ที่สองอาจไม่ทำงาน ฉันเพิ่งเรียนรู้ 'FN' หมายถึงฟังก์ชันสเกลาร์ การเชื่อมโยงนี้จะบอกคุณค่าพารามิเตอร์ที่แตกต่างกันคุณสามารถส่งผ่านsqlhints.com/tag/how-to-check-if-function-exists ฉันยังคงใช้ 'FN' เพื่อตรวจสอบฟังก์ชันค่าตารางที่มีอยู่ แต่ก็ไม่ได้ผล ฉันต้องใช้ 'TF'
user12345

9

ฉันพบว่าคุณสามารถใช้วิธีการที่ไม่ละเอียดและตรงไปตรงมาในการตรวจสอบการมีอยู่ของวัตถุ SQL Server ต่างๆด้วยวิธีนี้:

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

สิ่งนี้ขึ้นอยู่กับฟังก์ชัน OBJECTPROPERTY ซึ่งมีอยู่ใน SQL 2005+ บทความ MSDN สามารถพบได้ที่นี่

ฟังก์ชัน OBJECTPROPERTY ใช้ลายเซ็นต่อไปนี้:

OBJECTPROPERTY ( id , property ) 

คุณส่งค่าตามตัวอักษรไปยังพารามิเตอร์คุณสมบัติโดยกำหนดประเภทของวัตถุที่คุณกำลังมองหา มีรายการค่ามากมายที่คุณสามารถจัดหาได้


ฉันคิดว่ามันจะง่ายกว่าที่จะเห็นความเรียบง่ายของคำตอบนี้หากมีตัวอย่าง if / drop ที่สมบูรณ์
Jonathan

7

ฉันรู้ว่าหัวข้อนี้เก่า แต่ฉันแค่อยากจะเพิ่มคำตอบนี้สำหรับผู้ที่เชื่อว่ามันปลอดภัยที่จะAlterกว่าและDrop Createด้านล่างนี้จะAlterเป็นFunctionถ้ามีอยู่หรือCreateไม่:

  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
  ...

2
ฉันชอบสิ่งนี้ แต่ฉันคิดว่ามันควรจะเป็น "ALTER FUNCTION" ไม่ใช่เหรอ?
Erik

ฉันชอบALTER OR CREATE
AgentFire
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.