Як перевірити, чи існує функція в базі даних SQL


138

Мені потрібно з’ясувати, чи існує функція в базі даних, щоб я міг її скинути і створити заново. В основному це повинен бути щось на зразок наступного коду, який я використовую для збережених процедур:

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

Відповіді:


206

Це те, що використовує 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-ing, якщо натомість існує.


17
Змушує мене ще більше цікавитись, чому немає системного каталогу каталогу
sys.functions

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. (До речі поняття є крос-платформної сумісності прийшов з цієї відповіді: 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: Скалярна функція
  • ЯКЩО: функція вбудованої таблиці
  • TF: Таблиця-функція
  • FS: Скалярна функція складання (CLR)
  • FT: функція, що оцінюється за столом (CLR)

4
Технічно це може бути невдалим, оскільки він лише перевіряє наявність об'єкта цього імені. Не те, що є об’єкт і що це функція. EG Якщо CREATE TABLE YourFunctionName(X INT);запустити код не вдасться.
Мартін Сміт

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.
Джонатан

6

Я знаю , що ця нитка старий , але я просто хотів би додати цю відповідь для тих , хто вважає , що це безпечніше , Alterніж Dropта Create. Нижче буде , якщо вона існує , або він , якщо не робить:AlterFunctionCreate

  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 OR CREATE
AgentFire
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.