Come verificare se esiste una funzione su un database SQL


138

Devo scoprire se esiste una funzione in un database, in modo da poterla eliminare e crearla di nuovo. Fondamentalmente dovrebbe essere qualcosa di simile al seguente codice che utilizzo per le stored procedure:

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

Risposte:


206

Questo è ciò che SSMS utilizza quando si esegue lo script utilizzando l' DROP and CREATEopzione

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 

Questo approccio alla distribuzione delle modifiche implica la necessità di ricreare tutte le autorizzazioni sull'oggetto, in modo da poter considerare ALTERse esiste invece.


17
Mi chiedo ancora di più perché non esiste una vista del catalogo del sistema sys.functions .....
marc_s

61

Tendo a usare Information_Schema:

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

per le funzioni e modifica Routine_Typeper le stored procedure

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

2
Fantastico stavo cercando qualcosa del genere e non l'ho mai trovato. Credo che sia meglio usare information_schema in generale in quanto non è legato a un RDBMS specifico. (a proposito la nozione di essere cross-platform è venuto da questa risposta: stackoverflow.com/a/14290099/420667 )
user420667

40

Perché non solo:

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

Il secondo argomento di object_idè facoltativo, ma può aiutare a identificare l'oggetto corretto. Esistono numerosi valori possibili per questo argomento di tipo, in particolare:

  • FN: funzione scalare
  • IF: funzione con valori di tabella incorporata
  • TF: funzione con valori di tabella
  • Vendo: funzione scalare di assemblaggio (CLR)
  • FT: Funzione con valori di tabella Assembly (CLR)

4
Tecnicamente questo può fallire in quanto controlla solo che esiste un oggetto con quel nome. Non che ci sia un oggetto e che sia una funzione. Ad esempio, se l' CREATE TABLE YourFunctionName(X INT);esecuzione del codice fallisce.
Martin Smith,

1
@MartinSmith: facile da rendere robusto. Basta usare object_id('YourFunction', 'FN')o qualsiasi altro designatore (secondo argomento) che chiarisca a quale tipo di oggetto ti riferisci.
darlove,

@darlove usando 'FN' come secondo parametro potrebbe non funzionare. Ho appena imparato 'FN' significa funzione scalare. Questo link ti dice diversi valori di parametri che puoi passare a sqlhints.com/tag/how-to-check-if-function-exists . Continuo a usare 'FN' per verificare la funzione del valore tabella esistente e non funziona. Devo usare 'TF'
user12345

9

Ho scoperto che puoi usare un approccio molto non verboso e diretto per verificare l'esistenza di vari oggetti di SQL Server in questo modo:

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

Questo si basa sulla funzione OBJECTPROPERTY che è disponibile in SQL 2005+. L'articolo di MSDN è disponibile qui .

La funzione OBJECTPROPERTY utilizza la seguente firma:

OBJECTPROPERTY ( id , property ) 

Si passa un valore letterale al parametro proprietà, designando il tipo di oggetto che si sta cercando. C'è un enorme elenco di valori che puoi fornire.


Penso che sarebbe più facile vedere la semplicità di questa risposta se includesse un esempio completo if / drop.
Jonathan,

6

So che questa discussione è vecchia ma volevo solo aggiungere questa risposta per coloro che credono che sia più sicuro Alterdi Drope Create. Il sotto sarà Alterla Functionse esiste o Create, se non lo fa:

  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
Mi piace questo, ma penso che dovrebbe essere "ALTER FUNCTION", no?
Erik

Mi piaceALTER OR CREATE
AgentFire
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.