SQL Idempotence

时间:2012-08-12 01:42:02

标签: sql sql-server-2008-r2 idempotent

我的SQL数据库项目中有一个部署后脚本,它注册应该是数据库一部分的默认值。我希望这个脚本能够在不改变结果的情况下多次运行,所以如果我只需要添加一些修改,我就可以手动运行它。

INSERT INTO [UserRole] ([Name])
SELECT 'Regular'
UNION ALL
SELECT 'Admin'

INSERT INTO [UserRight] ([Name])
SELECT 'CanAccessApplicationLogs'
UNION ALL
SELECT 'CanAccessApplicationJobs'

INSERT INTO [UserRoleRight] ([UserRoleId], [UserRightId])
SELECT  [Ro].[Id], [Ri].[Id] FROM [UserRight] Ri, [UserRole] Ro
 WHERE ([Ro].[Name] = 'Admin' AND
        [Ri].[Name] = 'CanAccessApplicationLogs')
    OR ([Ro].[Name] = 'Admin' AND
        [Ri].[Name] = 'CanAccessApplicationJobs')

我怀疑性能会成为一个问题,因为这个脚本只会插入角色和权限。那么检查每一行是否存在的最干净的方法是什么,并且只插入那些已经不在表中的那些?

2 个答案:

答案 0 :(得分:3)

将每个插入包装在IF语句中都可以。不确定这是否是最干净的方式。

所以你的第一个INSERT会变成:

IF NOT EXISTS(SELECT * FROM UserRole WHERE Name = 'Regular')
BEGIN
  INSERT INTO [UserRole] ([Name])
  SELECT 'Regular'
  UNION ALL
  SELECT 'Admin'
END

答案 1 :(得分:3)

MERGE可以更清晰,并且可以单独检查每一行而不需要每个行周围的IF语句。

http://coding.abel.nu/2012/08/idempotent-db-update-scripts/有一个很好的例子