Comment vérifier si une fonction existe sur une base de données SQL

138

J'ai besoin de savoir si une fonction existe sur une base de données, afin de pouvoir la supprimer et la créer à nouveau. Cela devrait être quelque chose comme le code suivant que j'utilise pour les procédures stockées:

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

Réponses:

206

C'est ce que SSMS utilise lorsque vous créez un script à l'aide de l' DROP and CREATEoption

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 

Cette approche de déploiement des modifications signifie que vous devez recréer toutes les autorisations sur l'objet afin que vous puissiez envisager ALTER-ing s'il existe à la place.

Martin Smith
la source
17
Je me demande encore plus pourquoi il n'y a pas de vue catalogue système sys.functions .....
marc_s
61

J'ai tendance à utiliser Information_Schema:

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

pour les fonctions et changement Routine_Typepour les procédures stockées

IF EXISTS ( SELECT  1
            FROM    Information_schema.Routines
            WHERE   Specific_schema = 'dbo'
                    AND specific_name = 'Foo'
                    AND Routine_Type = 'PROCEDURE' ) 
Loi Metzler
la source
2
Cool, je cherchais quelque chose comme ça et je ne l'ai jamais trouvé. Je pense qu'il est préférable d'utiliser information_schema en général car il n'est pas lié à un SGBDR spécifique. (d'ailleurs la notion de compatibilité multiplateforme est venue de cette réponse: stackoverflow.com/a/14290099/420667 )
user420667
40

Pourquoi pas simplement:

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

Le deuxième argument de object_idest facultatif, mais peut aider à identifier le bon objet. Il existe de nombreuses valeurs possibles pour cet argument de type, en particulier:

  • FN: fonction scalaire
  • IF: fonction table en ligne
  • TF: fonction de table
  • FS: fonction scalaire d'assemblage (CLR)
  • FT: fonction table d'assemblage (CLR)
Kapé
la source
4
Techniquement, cela peut échouer car il vérifie uniquement qu'il existe un objet de ce nom. Non pas qu'il y ait un objet et que ce soit une fonction. EG Si CREATE TABLE YourFunctionName(X INT);alors l'exécution du code échouera.
Martin Smith
1
@MartinSmith: Facile à rendre robuste. Utilisez simplement object_id('YourFunction', 'FN')ou tout autre désignateur (deuxième argument) qui indique clairement le type d'objet auquel vous faites référence.
darlove le
@darlove utilisant «FN» comme deuxième paramètre peut ne pas fonctionner. Je viens d'apprendre. «FN» signifie fonction scalaire. Ce lien vous indique différentes valeurs de paramètres que vous pouvez transmettre à sqlhints.com/tag/how-to-check-if-function-exists . Je continue à utiliser «FN» pour vérifier la fonction de valeur de table existante, et cela ne fonctionne pas. Je dois utiliser 'TF'
user12345
9

J'ai trouvé que vous pouvez utiliser une approche très non verbeuse et directe pour vérifier l'existence de divers objets SQL Server de cette façon:

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

Ceci est basé sur la fonction OBJECTPROPERTY qui est disponible dans SQL 2005+. L'article MSDN peut être trouvé ici .

La fonction OBJECTPROPERTY utilise la signature suivante:

OBJECTPROPERTY ( id , property ) 

Vous passez une valeur littérale dans le paramètre de propriété, désignant le type d'objet que vous recherchez. Il existe une liste massive de valeurs que vous pouvez fournir.

Jérémie
la source
Je pense qu'il serait plus facile de voir la simplicité de cette réponse si elle incluait un exemple complet de if / drop.
Jonathan
6

Je sais que ce fil est vieux mais je voulais juste ajouter cette réponse pour ceux qui croient que c'est plus sûr Alterque Dropet Create. Le ci - dessous Alterla Functionsi elle existe ou Createsi ne pas:

  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
la source
2
J'aime ça, mais je pense que ça devrait être "ALTER FUNCTION", non?
Erik
J'aimeALTER OR CREATE
AgentFire