可重新运行的SQL Server脚本

时间:2009-04-03 14:44:42

标签: sql sql-server tsql

确保SQL可以重复运行而不会在后续运行中收到错误的最佳做法是什么?

e.g。

  • 在创建表之前检查表尚不存在
  • 在创建或重命名之前检查列是否已存在
  • 错误时回滚的交易
  • 如果在重新创建表之前删除存在的表,请先删除它们的依赖项,并且不要忘记在
  • 之后重新创建它们。
  • 如果您的SQL风格支持,则使用CREATE OR ALTER PROCEDURE而不是CREATE PROCEDURE或ALTER PROCEDURE
  • 维护内部版本控制方案,因此相同的SQL首先不会运行两次。通过这种方式,您可以通过查看版本号来了解自己的位置。
  • 将现有数据导出为INSERT语句,并从头开始完全重新创建整个数据库。

  • 在创建它们之前删除表格(不是最安全的事情,但如果你知道自己在做什么的话就会紧张)

编辑: 我在寻找这样的东西:

IF EXISTS ( SELECT  *
            FROM    sys.objects
            WHERE   object_id = OBJECT_ID(N'[dbo].[foo]')
                    AND OBJECTPROPERTY(object_id, N'IsUserTable') = 1 ) 
DROP TABLE foo

其他人是否使用这样或更好的陈述?

编辑: 我喜欢Jhonny的建议:

IF OBJECT_ID('table_name') IS NOT NULL DROP TABLE table_name

我这样做是为了添加列:

IF NOT EXISTS ( SELECT  *
                FROM    SYSCOLUMNS sc
                WHERE   EXISTS ( SELECT id
                                 FROM   [dbo].[sysobjects]
                                 WHERE  NAME LIKE 'TableName'
                                        AND sc.id = id )
                        AND sc.name = 'ColumnName' ) 
    ALTER TABLE [dbo].[TableName] ADD [ColumnName] 

9 个答案:

答案 0 :(得分:5)

我认为确保脚本可重新运行的最重要的做法是...... 在对脚本进行任何更改后多次针对测试数据库运行它们。您遇到的错误应该会影响您的实践。

修改

为了响应您对语法的编辑,我认为最好避免系统表支持系统视图,例如

if exists(Select 1 from information_schema.tables where table_name = 'sometable')
    drop sometable
go
if exists(Select 1 from information_schema.routines where 
specific_name  = 'someproc')
   drop someproc 

答案 1 :(得分:4)

要添加到您的列表中:

  • 如果在重新创建表之前删除存在的表,请先删除它们的依赖项,并且不要忘记在
  • 之后重新创建它们。
  • 如果您的SQL风格支持,请使用CREATE OR ALTER PROCEDURE代替CREATE PROCEDUREALTER PROCEDURE

但最终,我会选择以下其中一项:

  • 维护内部版本控制方案,因此同样的SQL 不会首先运行两次。通过这种方式,您可以通过查看版本号来了解自己的位置。
  • 将现有数据导出到INSERT语句,并从头开始完全重新创建整个数据库。

答案 2 :(得分:4)

为了简化操作,我将management studio配置为脚本对象为可重新运行

  1. 工具
  2. 选项
  3. SQL Server对象资源管理器
  4. 脚本
  5. 对象脚本选项
  6. 包含IF不存在条款 True

答案 3 :(得分:3)

我最近找到了一个我不知道存在的登记入住,我喜欢它,因为它更短

IF OBJECT_ID('table_name') IS NOT NULL DROP TABLE table_name

之前,我曾经使用过

IF EXISTS (SELECT * FROM information_schema.tables WHERE table_name = 'table_name') 
DROP TABLE table_name

我觉得这很有用,因为它更便携(MySql,Postgres等),考虑到差异,当然

答案 4 :(得分:0)

要维护模式,请查看迁移工具。我认为LiquiBase适用于SQL Server。

答案 5 :(得分:0)

您还需要检查可能正在删除/重新创建的任何表上的外键。另外,请考虑您可能进行的任何数据更改 - 在尝试再次插入之前删除行等,等等。

在删除表作为安全措施之前,您可能还需要输入代码来检查数据,这样就不会丢弃已经使用过的表。

答案 6 :(得分:0)

对于SQL批处理语句,您可以发出

这只是一个FYI,我只跑了10次

IF EXISTS ( SELECT  *
            FROM    sys.objects
            WHERE   object_id = OBJECT_ID(N'[dbo].[foo]')
                    AND OBJECTPROPERTY(object_id, N'IsUserTable') = 1 ) 
DROP TABLE foo


GO 10 -- run the batch 10 times

这只是一个FYI,我只跑了10次

  

开始执行循环批处理

     

执行完成了10次。

答案 7 :(得分:0)

“IF OBJECT_ID('table_name','U')IS NOT NULL”语法很好,它也可以用于程序:     如果OBJECT_ID('procname','P')不是NULL        ...

...和触发器,视图等......如果你的命名方法允许程序和方法,可能是指定类型(U表为表,P表示编程等等。不记得所有类型的确切字母)的良好做法。表格有相似的名字......

此外,一个好主意可能是创建自己的更改表的过程,并根据您的环境进行错误处理。例如:

  • prcTableDrop,Proc for droping a 表
  • prcTableColumnAdd,Proc用于向表中添加列
  • prcTableColumnRename,你明白了
  • prcTableIndexCreate

这样的过程使得创建可重复(在相同或其他数据库中)更改脚本变得更加容易。

/ B

答案 8 :(得分:0)

只为将来的搜索者(包括我自己)添加此脚本,这样的脚本就称为等幂(名词是等幂)