存储过程代码自动备份

时间:2022-03-05 05:01:22

  首先在master库下建立表ProcSqlTableBackProcSqlTableProcSqlTable存放存储过程当前版本代码,BackProcSqlTable存放历史版本代码。

USE [master]
GO
CREATE TABLE [dbo].[BackProcSqlTable](
    [id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY ,--编号
    [dbName] [nvarchar](150) NOT NULL,--数据库名
    [ProcSQL] [ntext] NOT NULL,--存储过程的SQL
    [ProcName] [nvarchar](150) NOT NULL,--存储过程名字
    [AlterDate] [datetime] NOT NULL,--修改时间
    [AlterUser] [nvarchar](150) NULL--修改人
)
GO



USE [master]
GO
CREATE TABLE [dbo].[ProcSqlTable](
    [id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,--编号
    [dbName] [nvarchar](150) NOT NULL,--数据名
    [ProcSQL] [ntext] NOT NULL,--存储过程SQL
    [ProcName] [nvarchar](150) NOT NULL--存储过程名字
)
GO

  接下来需要建立两个库级(DDL)触发器:tr_saveProcSql和tr_saveBackProcSql。tr_saveProcSql将新建存储过程代码写入ProcSqlTable,tr_saveBackProcSql将ProcSqlTable表中保存的代码写到BackProcSqlTable中作为历史版本代码,同时将存储过程当前代码更新到ProcSqlTable。

USE [master]
GO
create trigger [tr_saveProcSql]
on all server --作用于SQL Server实例下所有库
for CREATE_PROCEDURE
as 
  --获取事件数据
  DECLARE @data XML
  SET @data = EVENTDATA()

  declare @dbName nvarchar(50)
  declare @ProcName nvarchar(150)
  declare @ProcSQL nvarchar(max)

  --获取新建存储过程的数据库名
  SET @dbName = @data.value('(/EVENT_INSTANCE/DatabaseName)[1]', 'sysname')
  --获取新建存储过程的名字
  set @ProcName= @data.value('(/EVENT_INSTANCE/ObjectName)[1]', 'sysname')
  --获取新建存储过程的内容
  set @ProcSQL = @data.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'sysname')

  --将数据库名、存储过程名以及存储过程内容插入ProcSqlTable表
  insert into [master].[dbo].[ProcSqlTable]([dbName],[ProcName],[ProcSQL]) 
  values(@dbName,@ProcName,@ProcSQL)

GO

ENABLE TRIGGER [tr_saveProcSql] ON ALL SERVER
GO
USE [master]
GO
create trigger [tr_saveBackProcSql]
on all server  --作用于SQL Server实例下所有库
for ALTER_PROCEDURE
as 
  --获取事件数据
  DECLARE @data XML
  SET @data = EVENTDATA()

  declare @dbName nvarchar(50)
  declare @ProcName nvarchar(150)
  declare @LoginName nvarchar(150)
  declare @ProcSQL nvarchar(max) --存储过程内容
  declare @OldProcSQL nvarchar(max)--修改前的存储过程内容

  --获取修改存储过程的数据库名
  SET @dbName = @data.value('(/EVENT_INSTANCE/DatabaseName)[1]', 'sysname')
  --获取修改存储过程的名字
  set @ProcName= @data.value('(/EVENT_INSTANCE/ObjectName)[1]', 'sysname')
  --获取修改存储过程的内容
  set @ProcSQL = @data.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'sysname')
  --获取用户名
  set @LoginName = @data.value('(/EVENT_INSTANCE/LoginName)[1]', 'sysname')

  if exists(select 1 from [master].[dbo].[ProcSqlTable] where [dbName]=@dbName and [ProcName]=@ProcName)
    begin 
        --如果系统里有该存储过程的记录,获取修改前的存储过程内容
        select @OldProcSQL=[ProcSQL]
        from [master].[dbo].[ProcSqlTable]
        where [dbName]=@dbName and [ProcName]=@ProcName
    end
  else
    begin
         --如果没有将数据库名、存储过程名以及存储过程内容插入ProcSqlTable表
         insert into [master].[dbo].[ProcSqlTable]([dbName],[ProcName],[ProcSQL]) 
         values(@dbName,@ProcName,@ProcSQL)

         --退出
         return
    end

  --更新ProcSqlTable表存储过程的内容供下次使用
  update [master].[dbo].[ProcSqlTable]
  set [ProcSQL]=@ProcSQL
  where [dbName]=@dbName and [ProcName]=@ProcName 

  --将数据库名、存储过程名以及修改前的存储过程内容插入BackProcSqlTable表
  insert into [master].[dbo].[BackProcSqlTable]([dbName],[ProcName],[ProcSQL],[AlterDate],[AlterUser]) 
  values(@dbName,@ProcName,@OldProcSQL,GETDATE(),@LoginName)
  
GO

ENABLE TRIGGER [tr_saveBackProcSql] ON ALL SERVER
GO

 

=====================================================================================
本文只代表本人的见解,可能存在错误,仅用于技术交流。如果你喜欢该文,可以扫下面的二维码打赏我(打赏敬请备注“博客园打赏”五字)。

存储过程代码自动备份