臨時接到通知,需要臨時編寫一個SQL Server的腳本,供出差的同事使用一下。
我當時心想這個SQL Server腳本聽都沒聽說過,但是組織說決定就是你了,那我就只能硬着頭皮上了。
腳本實現的功能比較簡單,在數據庫中尋找固定前綴的表,表中都包含[Time]屬性,刪除三個月(或者...天)的數據。
簡單搜索了相關知識,分以下幾步實現:
1.獲取時間節點並轉換為指定格式:
獲取當前日期前指定時間,網上容易百度到,獲取到時間節點需要將其轉換為固定的格式,具體可參考《Sql中把datetime轉換成字符串(CONVERT)》;
代碼如下所示:
1 select @logdeldate = (select convert(varchar(100), dateadd(month, -3, getdate()), 21));
2.獲取數據庫符合要求的指定表:
此處需要注意獲取到的表名需要存儲進入臨時表中,供后續遍歷使用。因為表中數據沒有主鍵,因此需要進行插入Key以便查詢(如果有更好的辦法,請告知):
1 select NULL tmpKey, [name] into #TempTable from [sysobjects] where [type] = 'u' and name like 'T_Status_A%' order by [name];
此處臨時表中的數據記錄tmpKey值均為NULL,使用如下語句可以為更新其中一條記錄的tmpKey值:
1 set rowCount 1 2 update #TempTable set tmpKey = 1 3 set rowCount 0
select rowCount 0的作用為限制接下來執行的SQL語句僅執行一條,比如下一句語句,僅將一條記錄的tmpKey值更新為1。
1 update #TempTable set tmpKey = 1
3.腳本中聲明變量,並進行賦值操作
1 declare 2 @i as int, 3 @deldate as varchar(100), --設備狀態表刪除時間節點 4 @logdeldate as varchar(100), --日志表刪除時間節點
上述代碼中聲明了若干變量,並標注其對應類型。
1 select @logdeldate = (select convert(varchar(100), dateadd(month, -3, getdate()), 21)); 2 set @logsql = 'delete from [****].[dbo].[T_Log] where Time < ' + CHAR(39) + @logdeldate + CHAR(39);
上述代碼中對@logdeldate進行賦值,賦值為搜索后的結果;后續設置sql語句給@logsql變量,注意@sql聲明時為@logsql as nvarchar(MAX),,非varchar(MAX)。
注:CHAR(39)為單引號。
4.遍歷結果集,並執行語句
1 set @i = 0; --初始化計數 2 while @i < @deltablecount 3 Begin 4 set rowCount 0 5 select @tablename = (select [name] from #TempTable where tmpKey = 1) 6 delete from #TempTable where tmpKey = 1 7 8 set rowCount 1 9 update #TempTable set tmpKey = 1 10 set rowCount 0 11 12 set @statussql = 'delete from ' + QUOTENAME(@tablename) + ' where [Time] < ' + CHAR(39) + @deldate + CHAR(39); 13 print @statussql 14 exec(@statussql) 15 Set @i = @i + 1 16 End 17 GO
上述代碼為遍歷結果集,拼接新的SQL語句並執行。
最后附上此次的腳本,因為初次編寫,有諸多不滿意之處,但是也不知道如何改進,如果各位看后有改進方法請告知。
最后附上完整代碼:
--刪除數據庫指定日期數據前,請確認操作不可逆轉 USE [****] GO --------------------------------------------------------------------------------------------------------------------------------------- --選取符合要求的表,存儲進臨時表中供后續遍歷 select NULL tmpKey, [name] into #TempTable from [sysobjects] where [type] = 'u' and name like 'T_Status_A%' order by [name]; GO set rowCount 1 update #TempTable set tmpKey = 1 set rowCount 0 --------------------------------------------------------------------------------------------------------------------------------------- declare @i as int, @deldate as varchar(100), --狀態表刪除時間節點 @logdeldate as varchar(100), --日志表刪除時間節點 @tablename as varchar(100), @deltablecount as int, --需要刪除的數據庫總數 @logsql as nvarchar(MAX), @realsql as nvarchar(MAX), @statussql as nvarchar(MAX); select @deltablecount = COUNT(*) from #TempTable; --------------------------------------------------------------------------------------------------------------------------------------- --設置日志表的刪除時間節點(默認刪除三個月以前的數據) select @logdeldate = (select convert(varchar(100), dateadd(month, -3, getdate()), 21)); set @logsql = 'delete from [****].[dbo].[T_Log] where Time < ' + CHAR(39) + @logdeldate + CHAR(39); print(@logsql) exec(@logsql) --------------------------------------------------------------------------------------------------------------------------------------- --設置設備狀態表刪除時間(默認刪除三個月以前的數據) select @deldate = (select convert(varchar(100), dateadd(month, -3, getdate()), 21)); set @i = 0; --初始化計數 while @i < @deltablecount Begin set rowCount 0 select @tablename = (select [name] from #TempTable where tmpKey = 1) delete from #TempTable where tmpKey = 1 set rowCount 1 update #TempTable set tmpKey = 1 set rowCount 0 set @statussql = 'delete from ' + QUOTENAME(@tablename) + ' where [Time] < ' + CHAR(39) + @deldate + CHAR(39); print @statussql exec(@statussql) Set @i = @i + 1 End GO drop table #TempTable GO
PS:
如果您覺得我的文章對您有幫助,請關注我的微信公眾號,謝謝!