【问题标题】:Views as Stored Procedures in Schema Change script视图作为模式更改脚本中的存储过程
【发布时间】:2013-09-08 00:09:24
【问题描述】:

我编写了一个更改脚本来更新生产数据库中的架构。我必须删除一个视图并重新创建它们,因为该视图中的一列现在已被删除。

我打算用,

DECLARE @sql NVARCHAR(MAX);
SET @sql = '<View Definition>';

EXEC sp_executesql @sql;

如果有的话,使用这种方法有什么陷阱?您会建议哪些替代方案?

我在一个带有 Try catch 块的事务下拥有整个脚本。因此,当没有错误时,脚本将被提交否则回滚。我尝试使用如下 CREATE VIEW 命令,但在引入 TRASACTION 和 TRY-CATCH BLOCKS 后出现错误。这就是为什么要使用动态 SQL 语句 - EXEC sp_executesql .

错误是“创建视图必须是批处理中的唯一语句”

IF EXISTS ( SELECT * FROM sys.views WHERE name = 'VwViewName')
BEGIN 
DROP VIEW VwViewName
END

IF NOT EXISTS ( SELECT * FROM sys.views WHERE name = 'VwViewName')
BEGIN 
     CREATE VIEW VwViewName
    <VIEW DEFINITION>
END    

【问题讨论】:

  • 为什么要使用dynamic SQL?为什么不使用drop\createalter view?请记住,drop 将放弃对视图的任何授权。
  • 其实,我正在删除并重新创建。请阅读,这是在生产数据库中更改视图的标准。不是吗?
  • 是的,这是非常标准的过程。但不使用dynamic SQL
  • 所以你会建议正常的 drop/create 而不是动态 SQL 执行命令?为什么会这样?
  • 请在下方查看我的回复

标签: sql sql-server tsql database-schema


【解决方案1】:

由于您正在运行架构更新,因此您应该遵守最低限度的规定,例如

  • 使其可重复
  • 在您的版本控制系统中拥有它
  • 并在您的测试环境中对其进行测试,然后再投入生产。

为了使其可重新运行,通常的做法是检查对象是否存在并删除它,然后再次创建它。

动态 SQL 不会添加 IF 子句所具有的任何功能。

例如:

IF EXISTS(SELECT * FROM sys.views WHERE name = 'MyView')
BEGIN
    DROP VIEW [MyView]
END
GO
CREATE VIEW MyView AS 
    SELECT [Columns list ]
    FROM [MyTable]
GO

我知道证明dynamic SQL 的唯一情况是如果您想保留grant / deny,在这种情况下您可以使用以下语法。

IF NOT EXISTS(SELECT * FROM sys.views WHERE name = 'MyView')
BEGIN
    EXEC sp_executesql N'CREATE VIEW MyView AS SELECT 1 AS Dummy'
END
GO
ALTER VIEW MyView AS 
    SELECT [Columns list ]
    FROM [MyTable]

go
GRANT .... 

我不会创建Dynamic SQL 来填充我必须在以下任何脚本中重复名称的几次。恕我直言,部署脚本应该尽可能简单。

【讨论】:

  • True 我将其存储在版本控制中并在我的测试环境中多次测试。但是,我不确定我是否完全理解您所说的可重复的意思?因为,更改脚本应该只在生产数据库中运行一次。 (参考:odetocode.com/blogs/scott/archive/2008/02/02/…)还是我解释错了?
  • 关于第二条评论,您需要在CREATE ...上方添加一个GO
  • 关于您的第一条评论,使用Dynamic SQL 结合事务没有区别。至于repeatable,我的意思是在研发、Staging、QA、Preproduction 或任何其他环境中,这些deployment scripts 通常会运行很多次直到它们稳定,即很多时候SQA 会发现许多需要更改脚本的错误和功能.因此,从头开始恢复/重新生成环境通常用于多次运行这些脚本,直到它们获得基本的稳定性。
  • @Learner,我明白你的逻辑,你的IF NOT EXISTS(..) 变得无关紧要,如果你不能DROP,你周围的TRY`CATCH` 会选择它,如果你设法@987654338 @它不存在;因此你可以只保留CREATE VIEW...
猜你喜欢
  • 2012-02-08
  • 2017-03-16
  • 2015-02-20
  • 2011-04-12
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 2022-11-07
  • 1970-01-01
相关资源
最近更新 更多