Cómo verificar si existe una función en una base de datos SQL

138

Necesito averiguar si existe una función en una base de datos, para poder soltarla y volver a crearla. Básicamente debería ser algo como el siguiente código que utilizo para los procedimientos almacenados:

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

Respuestas:

206

Esto es lo que SSMS usa cuando se escribe usando la DROP and CREATEopción

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 

Este enfoque para implementar cambios significa que necesita volver a crear todos los permisos en el objeto, por lo que puede considerar la ALTERopción si existe en su lugar.

Martin Smith
fuente
17
Hace que me pregunte aún más por qué no hay una vista de catálogo del sistema sys.functions .....
marc_s
61

Tiendo a usar el Information_Schema:

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

para funciones y cambio Routine_Typepara procedimientos almacenados

IF EXISTS ( SELECT  1
            FROM    Information_schema.Routines
            WHERE   Specific_schema = 'dbo'
                    AND specific_name = 'Foo'
                    AND Routine_Type = 'PROCEDURE' ) 
Ley Metzler
fuente
2
Genial, estaba buscando algo como esto y nunca lo encontré. Creo que es mejor usar información_esquema en general, ya que no está vinculado a un RDBMS específico. (por cierto, la noción de ser compatible con varias plataformas surgió de esta respuesta: stackoverflow.com/a/14290099/420667 )
user420667
40

¿Por qué no solo:

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

El segundo argumento de object_ides opcional, pero puede ayudar a identificar el objeto correcto. Existen numerosos valores posibles para este tipo de argumento, particularmente:

  • FN: función escalar
  • IF: función con valores de tabla en línea
  • TF: función de valor de tabla
  • FS: función escalar de ensamblaje (CLR)
  • FT: función de valor de tabla de ensamblado (CLR)
Kapé
fuente
44
Técnicamente, esto puede fallar, ya que solo verifica que haya un objeto con ese nombre. No es que haya un objeto y que sea una función. Por ejemplo, si al CREATE TABLE YourFunctionName(X INT);ejecutar el código fallará.
Martin Smith,
1
@ MartinSmith: Fácil de hacer robusto. Simplemente use object_id('YourFunction', 'FN')o cualquier otro designador (segundo argumento) que deje en claro a qué tipo de objeto se refiere.
Darlove
@darlove usando 'FN' como segundo parámetro puede no funcionar. Acabo de aprender. 'FN' significa función escalar. Este enlace le dice diferentes valores de parámetros que puede pasar sqlhints.com/tag/how-to-check-if-function-exists . Sigo usando 'FN' para verificar la función de valor de tabla existente, y no funciona. Tengo que usar 'TF'
user12345
9

Descubrí que puede usar un enfoque muy detallado y directo para verificar la existencia de varios objetos de SQL Server de esta manera:

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

Esto se basa en la función OBJECTPROPERTY que está disponible en SQL 2005+. El artículo de MSDN se puede encontrar aquí .

La función OBJECTPROPERTY utiliza la siguiente firma:

OBJECTPROPERTY ( id , property ) 

Usted pasa un valor literal al parámetro de propiedad, designando el tipo de objeto que está buscando. Hay una lista masiva de valores que puede proporcionar.

Jeremy
fuente
Creo que sería más fácil ver la simplicidad de esta respuesta si incluyera un ejemplo completo de si / soltar.
Jonathan
6

Sé que este hilo es antiguo, pero solo quería agregar esta respuesta para aquellos que creen que es más seguro Alterque Dropy Create. El siguiente será Alterel Functionsi existe o Createno:

  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
fuente
2
Me gusta esto, pero creo que debería ser "ALTERAR FUNCIÓN", ¿no?
Erik
Me gustaALTER OR CREATE
AgentFire