【问题标题】:How to check if a function exists in a SQL database?如何检查 SQL 数据库中是否存在函数?
【发布时间】:2023-04-03 14:00:02
【问题描述】:

我需要确定一个函数是否存在于数据库中,以便我可以删除它并重新创建它。它基本上应该类似于我用于存储过程的以下代码:

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

【问题讨论】:

    标签: sql sql-server sql-function


    【解决方案1】:

    这是 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 if Exists 代替。

    【讨论】:

    【解决方案2】:

    我倾向于使用 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' ) 
    

    【讨论】:

    • 酷我一直在寻找这样的东西,但从未找到它。我认为通常使用 information_schema 会更好,因为它不依赖于特定的 RDBMS。 (顺便说一句,跨平台兼容的概念来自这个答案:stackoverflow.com/a/14290099/420667
    【解决方案3】:

    我发现您可以使用一种非常简洁且直接的方法来检查各种 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
    

    这是基于 SQL 2005+ 中可用的 OBJECTPROPERTY 函数。 MSDN文章可以找到here

    OBJECTPROPERTY 函数使用以下签名:

    OBJECTPROPERTY ( id , property ) 
    

    您将文字值传递给属性参数,指定您要查找的对象的类型。您可以提供大量的值。

    【讨论】:

    • 我认为如果包含完整的 if/drop 示例,则更容易看出这个答案的简单性。
    【解决方案4】:

    为什么不只是:

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

    object_id 的第二个参数是可选的,但可以帮助识别正确的对象。这个类型参数有numerous possible values,特别是:

    • FN:标量函数
    • IF : 内联表值函数
    • TF:表值函数
    • FS:汇编 (CLR) 标量函数
    • FT:汇编 (CLR) 表值函数

    【讨论】:

    • 从技术上讲,这可能会失败,因为它只检查是否存在该名称的对象。并不是说有一个对象,它是一个函数。例如。如果CREATE TABLE YourFunctionName(X INT); 则运行代码将失败。
    • @MartinSmith:很容易变得健壮。只需使用 object_id('YourFunction', 'FN') 或任何其他指示符(第二个参数),以明确您指的是哪种对象。
    • @darlove 使用 'FN' 作为第二个参数可能不起作用。我刚学会。 'FN' 表示标量函数。此链接告诉您可以传递sqlhints.com/tag/how-to-check-if-function-exists 的不同参数值。我一直使用“FN”来检查现有的表值函数,但它不起作用。我必须使用“TF”
    【解决方案5】:

    我知道这个帖子很旧,但我只是想为那些认为AlterDropCreate 更安全的人添加这个答案。以下将AlterFunction(如果存在)或Create(如果不存在):

      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
      ...
    

    【讨论】:

    • 我喜欢这个,但我认为应该是“ALTER FUNCTION”,不是吗?
    • 我喜欢ALTER OR CREATE
    猜你喜欢
    • 2010-10-15
    • 2020-05-11
    • 2020-08-16
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多