通過SqlClr制作Sql自動化批量執行腳本


通過SqlClr制作Sql自動化批量執行腳本

     在與同事一起做項目時,看到同事用sqlclr做批量執行腳本,感覺挺新奇的就上網搜集資料自己模仿跟做了個案例,

感覺挺不錯的,現在想和大家分享一下,可能存在些錯誤的地方,大家就做個小參考吧....

1.我們在做數據遷移或是數據庫結構修改時,通常會寫一些腳本文件之后逐個運行。但是如果有數十或數百個腳本文件,

   那么就可以通過SqlClr制作Sql自動化執

2.比如現在ImportDataScript文件夾內有些腳本文件:

   

3.我們想讓這9個腳本文件自動的依次執行,並且輸出最終的執行情況並且生成一個日志寫到ImportDataScript文件夾內的

   LogFile文件夾內的Logg.txt中。

4.我們預期結果:

   執行結果:(執行每個文件的開始時間、結束時間、執行總時間)

   

   輸出日志:(名稱、執行時間)

   

5.思路:首先我們通過sqlclr創建一個表值函數來獲取腳本文件的本地路徑的集合,然后遍歷這個集合並通過sql exec xp_cmdshell命令

   來執行指定路徑下的腳本文件,並通過sqlclr創建一個記錄日志的的標量函數來逐條記錄執行日志。

5.1創建sqlclr項目

5.1.1創建實體類:

 1 public class FilePathModel
 2     {
 3         public FilePathModel()
 4         {
 5 
 6         }
 7         public FilePathModel(string fileName, string filePath)
 8         {
 9             this.FileName = fileName;
10             this.FilePath = FilePath;
11         }
12         private string _FileName;
13 
14         public string FileName
15         {
16             get { return _FileName; }
17             set { _FileName = value; }
18         }
19         private string _FilePath;
20 
21         public string FilePath
22         {
23             get { return _FilePath; }
24             set { _FilePath = value; }
25         }
26     }

5.1.2創建表值函數:

 1 public partial class UserDefinedFunctions
 2 {
 3   [Microsoft.SqlServer.Server.SqlFunction
 4   (DataAccess = DataAccessKind.Read,
 5    TableDefinition = "FileName nvarchar(100),FilePath nvarchar(100)",
 6    FillRowMethodName = "FillTable", IsDeterministic = true)]
 7     public static IEnumerable GetScriptFilePath(SqlString fileRootPath)
 8     {
 9         
10         IList<FilePathModel> list = new List<FilePathModel>();
11         if (Directory.Exists(fileRootPath.Value))
12         {
13             DirectoryInfo di = new DirectoryInfo(fileRootPath.Value);
14             foreach (FileInfo fi in di.GetFiles())
15             {
16                 list.Add(new FilePathModel { FileName=fi.Name,FilePath=fi.FullName});
17             }
18         }
19         return list;
20     }
21   public static void FillTable(object obj, out SqlString fileName, out SqlString filePath)
22     {
23         fileName = "";
24         filePath = "";
25         FilePathModel fpModel = obj as FilePathModel;
26         if (fpModel != null)
27         {
28             fileName = fpModel.FileName;
29             filePath = fpModel.FilePath;
30         }
31     }
32 };

5.1.3創建寫入日志的標量函數:

 1 public partial class UserDefinedFunctions
 2 {
 3     [Microsoft.SqlServer.Server.SqlFunction]
 4     public static SqlString ImportLog(SqlString pathStr, SqlString strName, SqlString Time)
 5     {
 6         // 在此處放置代碼
 7 
 8         if (Directory.Exists(pathStr.Value))
 9         {
10             string filePathNew = Path.Combine(pathStr.Value, "Logg.txt");
11             FileInfo fi = new FileInfo(filePathNew);
12             if (!File.Exists(filePathNew))
13             {
14                 fi.Create();
15             }
16             using (StreamWriter sw = fi.AppendText())
17             {
18                 sw.WriteLine(strName.Value + "||" + Time.Value);
19             }
20             return new SqlString("完成");
21         }
22         else
23         {
24             return new SqlString("失敗");
25         }
26     }
27 };

5.2寫執行腳本:

--開啟sqlclr
sp_configure 'show advanced options', 1; 
GO 
RECONFIGURE; 
GO 
sp_configure 'clr enabled', 1; 
GO 
RECONFIGURE; 
GO
--使用.net framework
ALTER database Test SET TRUSTWORTHY ON
ALTER assembly DataImprot
with permission_set = external_access
go
--
--開啟【xp_cmdshell】權限
exec sp_configure 'xp_cmdshell', @configvalue = 1
reconfigure with override
go

--開啟【opendatasource】權限
exec sp_configure @configname = 'Ad Hoc Distributed Queries', @configvalue = 1
reconfigure with override

--測試
DECLARE @fileRootPath nvarchar(100)
DECLARE @logFilePath nvarchar(100)
DECLARE @serverName nvarchar(100)
DECLARE @dataBaseName nvarchar(100)
DECLARE @loginName nvarchar(100)
DECLARE @passWord nvarchar(100)
--服務器名
SET @ServerName='PACTERA_GZF-PC'
--數據庫名
SET @dataBaseName='Test'
--用戶名
SET @loginName='sa'
--密碼
SET @passWord='sa'
--腳本根路徑
SET @fileRootPath='D:\ImportDataScript'
--日志文件路徑.txt
SET @logFilePath='D:\ImportDataScript\LogFile'
DECLARE @FilePathTable table
(
    [FileName] nvarchar(100),
    FilePath nvarchar(100)
)
create table #CurFilePathTable
(
    Id int identity(1,1) primary key,
    [FileName] nvarchar(100),
    FilePath nvarchar(100),
    BeginTime datetime,
    EndTime datetime,
    ExcuteDate float
)
insert into @FilePathTable select [FileName], [FilePath] from dbo.GetScriptFilePath(@fileRootPath)
declare @FileName nvarchar(100)
declare @FilePath nvarchar(100)
declare @BeginTime datetime
declare @EndTime datetime
declare @sqlStr nvarchar(200)
declare cur_FilePath cursor for select [FileName], [FilePath] from @FilePathTable
open cur_FilePath
  fetch next from cur_FilePath into @FileName, @FilePath
while (@@fetch_status = 0)
begin
    set @BeginTime = getdate()
    set @sqlStr = 'exec xp_cmdshell ''osql -S '+@ServerName+' -U '+@loginName+' -P '+@passWord+' -i ' + @FilePath + ''''
    exec master..sp_executesql @sqlStr 
    set @EndTime = getdate()
    print @FileName
    insert into #CurFilePathTable ([FileName], FilePath, BeginTime,EndTime,ExcuteDate) values (@FileName, @FilePath, @BeginTime,@EndTime,datediff(second, @BeginTime, @EndTime))
    select dbo.ImportLog(@logFilePath,@FileName,convert(varchar(10),datediff(second, @BeginTime, @EndTime)))
    fetch next from cur_FilePath into @FileName, @FilePath
end
close cur_FilePath
deallocate cur_FilePath

select * FROM #CurFilePathTable
DROP TABLE #CurFilePathTable

5.3總結:

     感覺SqlClr就像是插件模型,通過嵌入.dll來實現更多的功能。

     利用SqlClr我們可以做許事情比如我們也可以在sqlserver端實現數據的加密解密等。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM