代码之家  ›  专栏  ›  技术社区  ›  DCNYAM

删除…创建vs更改

  •  51
  • DCNYAM  · 技术社区  · 15 年前

    在创建存储过程、视图、函数等时,对对象执行拖放…创建还是更改更好?

    我已经看到许多“标准”文档声明要做一个DROP…CREATE,但是我已经看到许多支持ALTER方法的评论和论据。

    ALTER方法保留了安全性,而我听说DROP…CREATE方法在第一次执行时强制对整个SP进行重新编译,而不仅仅是语句级的重新编译。

    有人能告诉我使用一种方法比使用另一种方法有哪些优点/缺点吗?

    12 回复  |  直到 15 年前
        1
  •  56
  •   OMG Ponies    15 年前

    什么 更改SQL文本后,服务器将不得不。。。编译它。

    对于所有对象,ALTER总是更好,因为它保留了所有安全性、所有扩展属性、所有依赖项和所有约束。

        2
  •  55
  •   Andomar    10 年前

    我们就是这样做的:

    if object_id('YourSP') is null
        exec ('create procedure dbo.YourSP as select 1')
    go
    alter procedure dbo.YourSP
    as
    ...
    

        3
  •  11
  •   kemiller2002    15 年前

    改变通常更好。如果删除并创建,则可能会丢失与该对象关联的权限。

        4
  •  9
  •   Dan Jagnow Martin Suchanek    7 年前

    CREATE OR ALTER CREATE OR ALTER – another great language enhancement in SQL Server 2016 SP1 在SQL Server数据库引擎博客上。例如:

    CREATE OR ALTER PROCEDURE dbo.MyProc
    AS
    BEGIN
        SELECT * FROM dbo.MyTable
    END;
    
        5
  •  1
  •   Kevin Doyon Zephaniah Grunschlag    15 年前

    例如,如果有一个函数/存储过程经常从网站调用,它可能会导致问题。

    存储的进程将被丢弃几毫秒/秒,在此期间,所有查询都将失败。

    如果你做了改变,你就不会有这个问题。

    新创建的存储过程的模板通常为以下形式:

    IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = '<name>')
        BEGIN
            DROP PROCEDURE <name>
        END
    GO
    
    CREATE PROCEDURE <name>
    ......
    

    然而,相反的情况更好,国际海事组织:

    如果storedproc/function/etc不存在,请使用伪select语句创建它。然后,圣坛将永远工作-它永远不会被丢弃。

    为此,我们有一个存储过程,因此我们的存储过程/函数通常如下所示:

    EXEC Utils.pAssureExistance 'Schema.pStoredProc'
    GO
    
    ALTER PROCECURE Schema.pStoredProc
    ...
    

    我们对函数使用相同的存储过程:

    EXEC Utils.pAssureExistance 'Schema.fFunction'
    GO
    
    ALTER FUNCTION Schema.fFunction
    ...
    

    但是要小心,如果您创建了一个伪标量函数,并且ALTER位于表值函数上,ALTER函数将失败,并表示它不兼容。

    EXEC Utils.pAssureExistance 'Schema.fFunction', 'TableValuedFunction'
    

    将创建一个伪表值函数,

    另外,我可能错了,但我认为如果执行drop过程,并且查询当前正在使用存储过程,那么它将失败。

        6
  •  1
  •   sam yi    11 年前

    我一直喜欢使用拖放/重新创建。我还发现将它们存储在源代码管理中更容易。而不是做。。。。如果存在,则进行更改;如果不存在,则进行创建。

    话虽如此。。。如果你知道你在做什么。。。我认为这不太重要。

        7
  •  1
  •   igelr    7 年前

    如果你执行 ,然后使用 创造 与使用 改变看法 改变 保留任何依赖项信息并设置权限。

        8
  •  0
  •   JL. Hans Passant    15 年前

    您提出了一个与不包含任何数据的DB对象相关的问题,理论上不应该经常更改。

    简单回答,不是真正的问题,只要权限不是问题

        9
  •  0
  •   Cade Roux    15 年前

    DROP 通常会丢失权限和任何扩展属性。

    在一些UDF上, ALTER 还会丢失扩展属性(在SQLServer2005多语句表值函数上是肯定的)。

    我通常不会 CREATE 除非我也在重新创造那些东西(或者知道我想失去它们)。

        10
  •  0
  •   Michael Riley - AKA Gunny    15 年前



    它还允许我们查看我们发送的每个可交付成果的日期。

        11
  •  0
  •   benjamin moskovits    10 年前

    如果存在,则添加并删除会更好,因为如果在将脚本移动到QA或test或prod时有多个环境,则不知道该脚本是否已存在于该环境中。通过添加一个drop(如果它已经存在)然后添加,您将被覆盖,无论它是否存在。然后,您必须重新应用权限,但最好是将安装脚本错误排除。

        12
  •  -1
  •   Kuberchaun    15 年前

    从可用性的角度来看,删除并创建比更改更好。Alter将在不包含该对象的数据库中失败,但如果存在删除,则CREATE将在对象已存在的数据库中或对象不存在的数据库中工作。在Oracle和PostgreSQL中,通常使用create或REPLACE语句创建函数和过程,该语句与SQL SERVER(如果存在)DROP语句和create语句的操作相同。如果SQL Server能够采用这种小但非常方便的语法,那就太好了。

    我会这样做的。将所有这些放在一个给定对象的脚本中。

    IF EXISTS ( SELECT 1
                FROM information_schema.routines
                WHERE routine_schema = 'dbo'
                  AND routine_name   = '<PROCNAME'
                  AND routine_type   = 'PROCEDURE' )
    BEGIN
        DROP PROCEDURE <PROCNAME>
    END
    GO
    
    
    CREATE PROCEDURE <PROCNAME>
    AS
    BEGIN
    END
    GO
    
    GRANT EXECUTE ON <PROCNAME> TO <ROLE>
    GO