今天要做數據導入的工作的時候,要導入員工表了。
有個字段叫 LoginName
而數據文件里面,沒有這個字段。
詢問一下主管,答復是 用姓名的拼音。 自己去網上去找個DLL來處理。
對於 中文漢字的拼音,這個以前倒是用 C# 調用 Simplified Chinese Pin-Yin Conversion Library 測試過。
不過實在不高興再去寫段程序,把數據從數據庫表里面讀取出來。
然后產生一個拼音的內容,最后在更新回數據庫去。
就考慮着,如果用 C# 寫個SQL Server 里面的 函數。
這樣直接在數據庫里面
UPDATE
表
SET
LoginName = GetNamePinYin(name);
一句話就一了百了啦。
以后又有新增的用戶,也可以這么折騰。
首先上網看看 C# 寫 SQL Server 的例子。
執行的前提
sp_configure 'clr enabled', 1
GO
RECONFIGURE
GO
然后在 VS2010 里面,創建一個 “Visual C# SQL CLR 數據庫項目”
首先創建下面這樣的函數 [代碼是 VS2010 自動產生的]
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString Function1()
{
// 在此處放置代碼
return new SqlString("Hello");
}
};
然后,嘗試添加 Microsoft.International.Converters.PinYinConverter 的引用
發現無法添加額外的引用。只有少數的 類庫允許被引用。
折騰了一段時間以后, 最后發現
首先要在數據庫的 SQL Server Management Studio 中的 [可編程性] 下的 [程序集]中。
先把那個 ChnCharInfo.dll 加進去。
然后回到 Visual Studio 2010 中,就可以添加 ChnCharInfo.dll 這個引用了。
最后的C#代碼如下:
using System;
using System.Data;
using System.Text;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using Microsoft.International.Converters.PinYinConverter;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString GetPinYin(SqlString word)
{
string result = GetPinYn(word.ToString());
// 在此處放置代碼
return new SqlString(result);
}
///
/// 取得詞的拼音.
///
///
///
private static string GetPinYn(string word)
{
StringBuilder buff = new StringBuilder();
for (int i = 0; i < word.Length; i++)
{
// 依次取得每一個字的發音.
string onePinYin = GetOnePinYin(word[i]);
if (!String.IsNullOrEmpty(onePinYin))
{
// 拼音加入結果列表.
// 去掉最后一個聲調的數字.
buff.Append(onePinYin.Substring(0, onePinYin.Length - 1));
}
}
return buff.ToString();
}
///
/// 取得單個漢字的拼音.
///
///
///
private static string GetOnePinYin(char iChar)
{
// 初始化 Simplified Chinese Pin-Yin Conversion Library.
ChineseChar chineseChar = new ChineseChar(iChar);
// 取得拼音列表.
ReadOnlyCollection pinyin = chineseChar.Pinyins;
foreach (string pin in pinyin)
{
if (!String.IsNullOrEmpty(pin))
{
// 對於多音字,不判斷了,直接返回第一個發音.
return pin;
}
}
// 處理不了的情況下,返回空白.
return String.Empty;
}
};
寫完C#函數以后. 編譯通過完畢以后。
回到 SQL Server Management Studio 中的 [可編程性] 下的 [程序集]中。
先把這個編譯好的 SqlServerProject1.dll 加進去。
最后執行下面的 SQL 語句, 定義好存儲過程的函數。
CREATE FUNCTION[dbo].[GetNamePinYin]
(@word NVARCHAR (10))
RETURNS NVARCHAR (100)
AS
EXTERNAL NAME[SqlServerProject1].[UserDefinedFunctions].[GetPinYin]
go
SELECT dbo.GetNamePinYin('張三');
SELECT dbo.GetNamePinYin('李四');
go
ZHANGSAN
(1 行受影響)
LISI
(1 行受影響)
看上去是滿足預期了
不過最后實際使用的時候,還是發生了
在執行用戶定義例程或聚合 "GetNamePinYin" 期間出現 .NET Framework 錯誤:
System.NotSupportedException: The character is not in extended character set of
Simplified Chinese.
的異常。
回頭再去仔細看看,到底誰的名字這么奇怪的,呵呵。
以下是自己驗證過的, 出現以下錯誤時處理方法:
1.引入程序集后 , 右擊屬性,將權限集改為"無限制",否則會報:
請求“System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”類型的權限已失敗。”
2.引入程序集時,出現:
針對程序集 'SqlServerProject' 的 CREATE ASSEMBLY 失敗,因為程序集 'SqlServerProject' 未獲授權,不滿足 PERMISSION_SET = EXTERNAL_ACCESS。滿足以下兩個條件之一時將給程序集授權: 數據庫所有者(DBO)擁有 EXTERNAL ACCESS ASSEMBLY 權限,且數據庫具有 TRUSTWORTHY 數據庫屬性;或者,程序集已使用其對應登錄名具有 EXTERNAL ACCESS ASSEMBLY 權限的證書或非對稱密鑰加以簽名。
可以先執行以下語句:
--use master
--GRANT EXTERNAL ACCESS ASSEMBLY TO loginame
--ALTER DATABASE dbname SET TRUSTWORTHY ON
(dbname 為准備創建的程序集所在的數據庫,loginame 為該數據庫的所有者對應的登陸賬戶)
引入程序集后,新建存儲過程時,如下例:
CREATE PROCEDURE [dbo].[過程名]
@account [nvarchar](50),
@password [nvarchar](50),
@sms int OUTPUT,
@mms int OUTPUT
WITH EXECUTE AS N'dbo'
AS
EXTERNAL NAME [myself_pro].[StoredProcedures].[定義的方法名]
GO