【问题标题】:How to check if a view exists and create if it does not如何检查视图是否存在,如果不存在则创建
【发布时间】:2018-03-07 09:23:58
【问题描述】:

如果 SQL Server 2016 中不存在,我想创建一个视图

IF EXISTS(SELECT 1 FROM sys.views 
     WHERE Name = 'VI_ALL_CITIES_AS_CATEGORY')
BEGIN
CREATE VIEW VI_ALL_CITIES_AS_CATEGORY AS
    SELECT PERSONS.FIRST_NAME AS 'Име', PERSONS.LAST_NAME AS 'Фамилия', CITIES.CITY_NAME AS 'Град'
    FROM CITIES
    LEFT JOIN PERSONS ON CITIES.ID = PERSONS.CITY_ID ;
END

但它给了我错误:

语法错误:'CREATE VIEW' 必须是 批处理。

【问题讨论】:

  • 除非我读错了你的 SQL,否则你的 EXISTS 正在检查是否存在,然后你试图 CREATE 它。如果视图已经存在,CREATE 将失败。
  • 另一种解决方案:set noexeccodereview.stackexchange.com/a/13858/40484

标签: sql sql-server ssms sql-server-2016


【解决方案1】:

你有两个选择:

1) 如果您使用的是 SSMS 或任何可以将您的脚本分成不同批次的客户端:

IF EXISTS(SELECT 'view exists' FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = N'YourViewName'AND TABLE_SCHEMA = 'YourViewSchema')
BEGIN
    DROP VIEW YourViewSchema.YourViewName
END

GO -- This will make the next statement the first in it's batch

CREATE VIEW YourViewSchema.YourViewName AS
SELECT something = 1
FROM YourTable

GO

2) 如果您不能将代码拆分成批次,您将不得不使用动态 SQL 来“欺骗”引擎来创建您的视图:

 IF NOT EXISTS(SELECT 'view exists' FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = N'YourViewName'AND TABLE_SCHEMA = 'YourViewSchema')
    BEGIN
        DECLARE @v_ViewCreateStatement VARCHAR(MAX) = '
            CREATE VIEW YourViewSchema.YourViewName AS
                SELECT something = 1
                FROM YourTable'

        EXEC (@v_ViewCreateStatement)

    END

请注意,1) 是 IF EXISTS,2) 是 IF NOT EXISTS

这样做的原因是大多数 DDL 语句需要在批处理中放在首位,因此很遗憾,您不能将 CREATE 对象语句放在其他语句之后。

【讨论】:

    【解决方案2】:

    试试这个方法

    IF NOT EXISTS
    (
        SELECT 1
        FROM sys.views
        WHERE Name = 'VI_ALL_CITIES_AS_CATEGORY'
    )
    BEGIN
    
        EXEC('CREATE VIEW VI_ALL_CITIES_AS_CATEGORY AS SELECT 1 as Val')
    
    END
    GO
    
    ALTER VIEW VI_ALL_CITIES_AS_CATEGORY
    AS
    SELECT 
        PERSONS.FIRST_NAME AS 'Име',
        PERSONS.LAST_NAME AS 'Фамилия',
        CITIES.CITY_NAME AS 'Град'
        FROM CITIES
           LEFT JOIN PERSONS 
              ON CITIES.ID = PERSONS.CITY_ID
    

    【讨论】:

    • 中间有一个 GO 语句,请记住,如果此代码在存储过程中,这将不起作用。
    【解决方案3】:

    如果您不想删除当前视图,可以使用临时名称创建一个新视图,然后使用 IF 重命名,使用仅在一批中执行的 exec sp_rename,如下所示:

    CREATE VIEW VI_ALL_CITIES_AS_CATEGORY_TEMP AS
    SELECT PERSONS.FIRST_NAME AS 'Име', PERSONS.LAST_NAME AS 'Фамилия', CITIES.CITY_NAME AS 'Град'
    FROM CITIES
    LEFT JOIN PERSONS ON CITIES.ID = PERSONS.CITY_ID ;
    
    GO
    
    IF OBJECT_ID('dbo.VI_ALL_CITIES_AS_CATEGORY', 'V') IS NULL
    exec sp_rename 'dbo.VI_ALL_CITIES_AS_CATEGORY_TEMP', 'VI_ALL_CITIES_AS_CATEGORY'
    
    GO
    
    IF OBJECT_ID('dbo.VI_ALL_CITIES_AS_CATEGORY_TEMP', 'V') IS NOT NULL
    drop view VI_ALL_CITIES_AS_CATEGORY_TEMP
    

    【讨论】:

      猜你喜欢
      • 2014-07-23
      • 2011-05-12
      • 2011-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多