資料庫儲存 DateTime.ToFileTime() 產生的 long 值(1601 年起始的 100ns 刻度),T-SQL 原生無 FromFileTime 對應函數,導致在預存程序中難以進行年份、季度等時間維度分析。
編寫 C# 組件,註冊至 SQL Server,再透過預存程序封裝呼叫,實現無縫轉換。
using System;
using System.Runtime.InteropServices;
using Microsoft.SqlServer.Server;
[ComVisible(true)]
[Guid("729BA6AF-3EFF-4B75-B43B-D951A190DBE6")]
public class FileTimeConverter
{
[SqlFunction(IsDeterministic = true, IsPrecise = true)]
public static string ConvertFileTime(long fileTime)
{
if (fileTime <= 0) return string.Empty;
try
{
DateTime dt = DateTime.FromFileTime(fileTime);
return dt.ToString("yyyy-MM-dd HH:mm:ss"); // 統一格式
}
catch
{
return string.Empty;
}
}
}
-- 開啟 CLR 功能
EXEC sp_configure 'clr enabled', 1; RECONFIGURE;
-- 建立組件 (需 TRUSTWORTHY 或簽名)
CREATE ASSEMBLY FileTimeUtils
FROM 'C:\Deploy\FileTimeUtils.dll'
WITH PERMISSION_SET = SAFE;
-- 建立標量函數對應
CREATE FUNCTION dbo.ufn_ConvertFileTime(@fileTime BIGINT)
RETURNS NVARCHAR(30)
AS EXTERNAL NAME FileTimeUtils.[FileTimeConverter].ConvertFileTime;
-- 單筆轉換
SELECT dbo.ufn_ConvertFileTime(133123456789012345);
-- 批次查詢
SELECT CreateTime, dbo.ufn_ConvertFileTime(CreateTime) AS NormalTime
FROM AuditLog
WHERE CreateTime > 0;
| 維度 | sp_OA* (COM) | SQL CLR |
|---|---|---|
| 效能 | 進程外呼叫,高延遲 | 進程內執行,近原生速度 |
| 安全性 | 需啟用 Ole Automation,高風險 | 權限集合精細控制 (SAFE/EXTERNAL_ACCESS/UNSAFE) |
| 部署 | 需 regasm、GAC、DCOM 設定 | 單一 CREATE ASSEMBLY 部署 |
| 除錯 | 極難 | 支援 Visual Studio 遠端除錯 |
| 型別安全 | Variant 型別,易出錯 | 強型別參數與回傳值 |
PERMISSION_SET = SAFE 限制僅純運算、無外部存取TRUSTWORTHY ON 或簽名非對稱金鑰/憑證授權 UNSAFE 組件