【问题标题】:SQL Server equivalent to Oracle's CREATE OR REPLACE VIEWSQL Server 相当于 Oracle 的 CREATE OR REPLACE VIEW
【发布时间】:2010-09-14 20:42:42
【问题描述】:

在 Oracle 中,我可以使用单个语句重新创建视图,如下所示:

CREATE OR REPLACE VIEW MY_VIEW AS
SELECT SOME_FIELD
FROM SOME_TABLE
WHERE SOME_CONDITIONS

正如语法所暗示的,这将删除旧视图并使用我给出的任何定义重新创建它。

在 MSSQL(SQL Server 2005 或更高版本)中是否有类似的功能可以做同样的事情?

【问题讨论】:

    标签: sql-server


    【解决方案1】:

    在 SQL Server 2016(或更高版本)中,您可以使用:

    CREATE OR ALTER VIEW VW_NAMEOFVIEW AS ...
    

    在旧版本的 SQL Server 中,您必须使用类似的东西

    DECLARE @script NVARCHAR(MAX) = N'VIEW [dbo].[VW_NAMEOFVIEW] AS ...';
    
    IF NOT EXISTS(SELECT * FROM sys.views WHERE name = 'VW_NAMEOFVIEW')
    -- IF OBJECT_ID('[dbo].[VW_NAMEOFVIEW]') IS NOT NULL
    BEGIN EXEC('CREATE ' + @script) END
    ELSE
    BEGIN EXEC('ALTER ' + @script) END
    

    或者,如果视图没有依赖关系,您可以直接删除它并重新创建:

    IF EXISTS(SELECT * FROM sys.views WHERE name = 'VW_NAMEOFVIEW')
    -- IF OBJECT_ID('[dbo].[VW_NAMEOFVIEW]') IS NOT NULL
    BEGIN 
       DROP VIEW [VW_NAMEOFVIEW];
    END
    
    CREATE VIEW [VW_NAMEOFVIEW] AS ...
    

    【讨论】:

    • 我使用的是 SQL Server 2016(或更新版本),无法使用 CREATE OR REPLACE VIEW 语法。正确的语法是CREATE OR ALTER VIEW。怎么回事,在我发现的所有其他 SO 线程中,每个人都说它是 CREATE OR REPLACE ?
    • @Wolle, CREATE OR REPLACE 是 Oracle 中的语法(见问题)
    【解决方案2】:

    对于SQL Server 2016 SP1+的参考,您可以使用CREATE OR ALTER VIEW 语法。

    MSDN CREATE VIEW:

    CREATE [ OR ALTER ] VIEW [ schema_name . ] view_name [ (column [ ,...n ] ) ]   
    [ WITH <view_attribute> [ ,...n ] ]   
    AS select_statement   
    [ WITH CHECK OPTION ]   
    [ ; ]
    

    或改变

    仅当视图已经存在时,有条件地更改视图。

    db<>fiddle demo

    【讨论】:

    • 这是一种语法。您不能像在 ORACLE 中那样同时使用 CREATE 和 ALTER 关键字。如果像这样尝试,你会得到以下错误。 - 关键字“OR”附近的语法不正确。 - 'CREATE/ALTER PROCEDURE' 必须是查询批处理中的第一条语句。
    • @DivTiwari,这显然在 SQL 2016 中有效。显然,SQL Server 只用了 11 年就赶上了这个 oracle 功能:)
    • @JosephStyons 确实,你是对的!我不明白他们怎么会错过这么长时间的重要功能。
    • @DivTiwari 这是Developers Choice: CREATE OR ALTER 迟到总比没有好:)
    【解决方案3】:

    我在 SQL Server 2017 上运行良好:

    USE MSSQLTipsDemo 
    GO
    CREATE OR ALTER PROC CreateOrAlterDemo
    AS
    BEGIN
    SELECT TOP 10 * FROM [dbo].[CountryInfoNew]
    END
    GO
    

    https://www.mssqltips.com/sqlservertip/4640/new-create-or-alter-statement-in-

    【讨论】:

    • 谢谢,太好了。我看到这个语法是在 SQL 2016 中引入的。当我写这个问题时,它是在 SQL 2005 中的。
    【解决方案4】:

    从 SQL Server 2016 开始,您拥有

    DROP TABLE IF EXISTS [foo];
    

    MSDN source

    【讨论】:

      【解决方案5】:

      上述解决方案虽然可以完成工作,但这样做的风险是放弃用户权限。我更喜欢按如下方式创建或替换视图或存储过程。

      IF NOT EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vw_myView]'))
          EXEC sp_executesql N'CREATE VIEW [dbo].[vw_myView] AS SELECT ''This is a code stub which will be replaced by an Alter Statement'' as [code_stub]'
      GO
      
      ALTER VIEW [dbo].[vw_myView]
      AS
      SELECT 'This is a code which should be replaced by the real code for your view' as [real_code]
      GO
      

      【讨论】:

      • 我曾经是一个“Drop”然后(重新)“Add”的人。但现在我倾向于这种类型的解决方案(如果没有,则添加,然后更改)。
      • 更改视图比删除并重新创建视图要好得多。如果您有很多现有用户的视图安全设置,那么您将不得不重新创建所有这些。这是我解决这个问题的方法。
      • 您的 CREATE 和 ALTER 做不同的事情....为什么? (一个是动态的,另一个不是,它们有不同的信息。)
      • 我发现您的 CREATE VIEW 语句涉及“由 Alter 语句替换”的方式令人困惑——这是什么意思?我也不清楚这里应该实际替换哪些代码,或者如何替换。我一定是少数对你的回答感到困惑的人之一。
      • 对于 SQL Server 2016 SP1+,请参阅 lad2025 的回答。
      【解决方案6】:

      我用:

      IF OBJECT_ID('[dbo].[myView]') IS NOT NULL
      DROP VIEW [dbo].[myView]
      GO
      CREATE VIEW [dbo].[myView]
      AS
      

      ...

      最近我为这类东西添加了一些实用程序:

      CREATE PROCEDURE dbo.DropView
      @ASchema VARCHAR(100),
      @AView VARCHAR(100)
      AS
      BEGIN
        DECLARE @sql VARCHAR(1000);
        IF OBJECT_ID('[' + @ASchema + '].[' + @AView + ']') IS NOT NULL
        BEGIN
          SET @sql  = 'DROP VIEW ' + '[' + @ASchema + '].[' + @AView + '] ';
          EXEC(@sql);
        END 
      END
      

      所以我现在写

      EXEC dbo.DropView 'mySchema', 'myView'
      GO
      CREATE View myView
      ...
      GO
      

      我认为它使我的变更脚本更具可读性

      【讨论】:

        【解决方案7】:

        您可以使用 'IF EXISTS' 检查视图是否存在,如果存在则删除。

        如果存在(从 INFORMATION_SCHEMA.VIEWS 中选择 TABLE_NAME WHERE TABLE_NAME = '我的视图') 删除视图我的视图 走 创建视图 MyView 作为 …… 走

        【讨论】:

        • 这样做的问题是您失去了已删除对象上可能存在的任何权限。
        【解决方案8】:

        您可以使用 ALTER 来更新视图,但这与 Oracle 命令不同,因为它仅在视图已经存在时才有效。 DaveK 的回答可能会更好,因为这将始终有效。

        【讨论】:

        • 虽然 ALTER 保留现有权限(如果新版本有语法错误等,则保留旧版本)。所以使用 IF NOT EXISTS ... 创建一个 Stub,然后用 ALTER 替换它/original 可能会更好地维护权限和依赖关系。
        【解决方案9】:

        我通常使用这样的东西:

        if exists (select * from dbo.sysobjects
          where id = object_id(N'dbo.MyView') and
          OBJECTPROPERTY(id, N'IsView') = 1)
        drop view dbo.MyView
        go
        create view dbo.MyView [...]
        

        【讨论】:

          猜你喜欢
          • 2011-10-14
          • 2013-09-03
          • 2010-12-30
          • 1970-01-01
          • 2016-03-08
          • 1970-01-01
          • 2011-04-10
          • 1970-01-01
          • 2010-11-30
          相关资源
          最近更新 更多