So überprüfen Sie, ob eine Funktion in einer SQL-Datenbank vorhanden ist

138

Ich muss herausfinden, ob eine Funktion in einer Datenbank vorhanden ist, damit ich sie löschen und erneut erstellen kann. Es sollte im Grunde so etwas wie der folgende Code sein, den ich für gespeicherte Prozeduren verwende:

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

Antworten:

206

Dies wird von SSMS verwendet, wenn Sie mit der DROP and CREATEOption ein Skript erstellen

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 

Dieser Ansatz zum Bereitstellen von Änderungen bedeutet, dass Sie alle Berechtigungen für das Objekt neu erstellen müssen, damit Sie in Betracht ziehen können, ALTERob stattdessen vorhanden ist.

Martin Smith
quelle
17
Ich frage mich noch mehr, warum es keine Systemkatalogansicht für sys.functions gibt .....
marc_s
61

Ich neige dazu, das Information_Schema zu verwenden:

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

für Funktionen und Änderung Routine_Typefür gespeicherte Prozeduren

IF EXISTS ( SELECT  1
            FROM    Information_schema.Routines
            WHERE   Specific_schema = 'dbo'
                    AND specific_name = 'Foo'
                    AND Routine_Type = 'PROCEDURE' ) 
Gesetz Metzler
quelle
2
Cool Ich habe nach so etwas gesucht und es nie gefunden. Ich glaube, es ist besser, information_schema im Allgemeinen zu verwenden, da es nicht an ein bestimmtes RDBMS gebunden ist. (Übrigens kam der Gedanke, plattformübergreifend kompatibel zu sein, aus dieser Antwort: stackoverflow.com/a/14290099/420667 )
user420667
40

Warum nicht einfach:

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

Das zweite Argument von object_idist optional, kann jedoch dazu beitragen, das richtige Objekt zu identifizieren. Für dieses Typargument gibt es zahlreiche mögliche Werte , insbesondere:

  • FN: Skalarfunktion
  • IF: Inline-Tabellenwertfunktion
  • TF: Tabellenwertfunktion
  • FS: CLR-Skalarfunktion (Assembly)
  • FT: CLR-Tabellenfunktion (Assembly)
Kapé
quelle
4
Technisch kann dies fehlschlagen, da nur überprüft wird, ob ein Objekt mit diesem Namen vorhanden ist. Nicht dass es ein Objekt gibt und dass es eine Funktion ist. EG Wenn CREATE TABLE YourFunctionName(X INT);dann das Ausführen des Codes fehlschlägt.
Martin Smith
1
@ MartinSmith: Einfach robust zu machen. Verwenden Sie einfach object_id('YourFunction', 'FN')einen anderen Bezeichner (zweites Argument), der klar macht, auf welche Art von Objekt Sie sich beziehen.
Liebling
@darlove mit 'FN' als zweitem Parameter funktioniert möglicherweise nicht. Ich habe gerade gelernt. 'FN' bedeutet Skalarfunktion. Dieser Link informiert Sie über verschiedene Parameterwerte, die Sie an sqlhints.com/tag/how-to-check-if-function-exists übergeben können . Ich verwende weiterhin 'FN', um nach vorhandenen Tabellenwertfunktionen zu suchen, und es funktioniert nicht. Ich muss 'TF' verwenden
user12345
9

Ich habe festgestellt, dass Sie auf sehr unkomplizierte und unkomplizierte Weise die Existenz verschiedener SQL Server-Objekte auf folgende Weise überprüfen können:

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

Dies basiert auf der Funktion OBJECTPROPERTY, die in SQL 2005+ verfügbar ist. Den MSDN-Artikel finden Sie hier .

Die Funktion OBJECTPROPERTY verwendet die folgende Signatur:

OBJECTPROPERTY ( id , property ) 

Sie übergeben einen Literalwert an den Eigenschaftsparameter und geben den gewünschten Objekttyp an. Es gibt eine riesige Liste von Werten, die Sie angeben können.

Jeremy
quelle
Ich denke, es wäre einfacher, die Einfachheit dieser Antwort zu erkennen, wenn sie ein vollständiges if / drop-Beispiel enthalten würde.
Jonathan
6

Ich weiß, dass dieser Thread alt ist, aber ich wollte diese Antwort nur für diejenigen hinzufügen, die glauben, dass es sicherer ist Alterals Dropund Create. Das Folgende wird Alterdas, Functionwenn es existiert oder Createwenn es nicht existiert:

  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
quelle
2
Ich mag das, aber ich denke, es sollte "ALTER FUNCTION" sein, nein?
Erik
Ich magALTER OR CREATE
AgentFire