[MS-SQL] 프로시저 자동 백업.
프로시저를 수정하다보면 간혹 실수를 하거나 이전 구문으로 복원을 해야할 때 가있다.
데이터베이스에 트리거를 등록해두고
프로시저에 CREATE나 ALTER등이 될 때 마다 소스를 지정한 테이블에 백업하는 방법이다.
CREATE TABLE dbo.SPLOG( idx bigint IDENTITY(1,1) NOT NULL, sp_name varchar(100) NULL, division varchar(20) NULL, SQLCMD varchar(max) NULL, author varchar(20) NULL, modified_date datetime NULL, CONSTRAINT XPKSPLOG PRIMARY KEY NONCLUSTERED ( idx ASC )) GO CREATE TRIGGER TRG_SPLOG ON DATABASE FOR CREATE_PROCEDURE, ALTER_PROCEDURE, DROP_PROCEDURE, CREATE_VIEW, ALTER_VIEW, DROP_VIEW, CREATE_FUNCTION, ALTER_FUNCTION, DROP_FUNCTION, CREATE_TRIGGER, ALTER_TRIGGER, DROP_TRIGGER AS DECLARE @DATA XML SET @DATA = EVENTDATA() INSERT INTO DBO.SPLOG (sp_name, division, SQLCMD, author, modified_date) VALUES (@DATA.value('(/EVENT_INSTANCE/ObjectName)[1]', 'VARCHAR(100)'), @DATA.value('(/EVENT_INSTANCE/EventType)[1]', 'VARCHAR(100)'), @DATA.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'VARCHAR(MAX)'), HOST_NAME(), GETDATE())
이제 수정이 이루어질때마다 SPLOG 테이블에 이력이 남게될 것이다.
- 추가
프로시저의 문장 길이가 varchar(max)가 허용하는 길이를 넘어서는 경우가 있다.
그럴 경우엔 한도 길이만큼 잘라서 분할해서 저장하면 온전히 보관할 수 있다.
프로시저 로그 저장용 테이블 생성
USE [DB] GO /****** Object: Table [dbo].[SPLOG] Script Date: 2021-06-03 오전 11:04:17 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[SPLOG]( [idx] [bigint] IDENTITY(1,1) NOT NULL, [sp_name] [varchar](100) NULL, [division] [varchar](20) NULL, [SQLCMD] [nvarchar](max) NULL, [author] [varchar](20) NULL, [modified_date] [datetime] NULL, [page] [int] NULL, [max_page] [int] NULL, CONSTRAINT [XPKSPLOG] PRIMARY KEY NONCLUSTERED ( [idx] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO SET ANSI_PADDING OFF GO
트리거 생성
USE [DB] GO /****** Object: DdlTrigger [TRG_SPLOG] Script Date: 2021-06-03 오전 11:00:37 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TRIGGER [TRG_SPLOG] ON DATABASE FOR CREATE_PROCEDURE, ALTER_PROCEDURE, DROP_PROCEDURE, CREATE_VIEW, ALTER_VIEW, DROP_VIEW, CREATE_FUNCTION, ALTER_FUNCTION, DROP_FUNCTION, CREATE_TRIGGER, ALTER_TRIGGER, DROP_TRIGGER AS DECLARE @DATA XML DECLARE @NUM INT, @MAX INT,@INTERVAL INT, @INDEX INT, @TMPTEXT VARCHAR(MAX), @MERGETEXT VARCHAR(MAX), @SP_NAME VARCHAR(100), @LOG_COUNT INT SET @DATA = EVENTDATA() SET @SP_NAME = @DATA.value('(/EVENT_INSTANCE/ObjectName)[1]', 'VARCHAR(100)') SET @NUM = 1 --해당 프로시저의 최대 페이지를 가져온다 SET @MAX = (SELECT max(colid) FROM syscomments a, sysobjects b where B.xtype in ('P','FN') AND A.ID = B.ID and b.name = @SP_NAME) SET @INTERVAL = 1 SET @INDEX = 1 SET @TMPTEXT = '' SET @MERGETEXT = '' IF @MAX > 9 --페이지수가 9페이지를 넘는다면 분할해서 저장하자 BEGIN WHILE @NUM<=@MAX BEGIN SET @TMPTEXT = (SELECT A.TEXT FROM syscomments a, sysobjects b where B.xtype in ('P','FN') AND A.ID = B.ID and b.name = @SP_NAME and colid = @NUM) IF @NUM = 1 BEGIN SET @TMPTEXT = REPLACE(@TMPTEXT, 'CREATE', 'ALTER') END SET @MERGETEXT = @MERGETEXT + @TMPTEXT SET @NUM = @NUM + 1 SET @INTERVAL = @INTERVAL + 1 IF @INTERVAL = 9 OR @NUM>@MAX BEGIN --SELECT @MERGETEXT, @INDEX INSERT INTO DBO.SPLOG (sp_name, division, SQLCMD, author, modified_date, page, max_page) VALUES (@DATA.value('(/EVENT_INSTANCE/ObjectName)[1]', 'VARCHAR(100)'), @DATA.value('(/EVENT_INSTANCE/EventType)[1]', 'VARCHAR(100)'), @MERGETEXT, HOST_NAME(), GETDATE(), @INDEX, @MAX/9 + 1) SET @INTERVAL = 1 SET @INDEX = @INDEX + 1 SET @MERGETEXT = '' END END; END ELSE BEGIN INSERT INTO DBO.SPLOG (sp_name, division, SQLCMD, author, modified_date, page, max_page) VALUES (@DATA.value('(/EVENT_INSTANCE/ObjectName)[1]', 'VARCHAR(100)'), @DATA.value('(/EVENT_INSTANCE/EventType)[1]', 'VARCHAR(100)'), @DATA.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'VARCHAR(MAX)'), HOST_NAME(), GETDATE(), @INDEX, @INDEX) END --저장된로그가 200개가 넘으면 이전걸 지워주자 SET @LOG_COUNT = (select count(*) from SPLOG where sp_name = @SP_NAME) IF @LOG_COUNT > 200 BEGIN delete from SPLOG where sp_name = @SP_NAME and idx not in (select top 200 idx from SPLOG where sp_name = @SP_NAME order by modified_date desc) END GO SET ANSI_NULLS OFF GO SET QUOTED_IDENTIFIER OFF GO ENABLE TRIGGER [TRG_SPLOG] ON DATABASE GO