資料清洗常需從欄位移除特定字元集。本文提供三個即用型純量函數:DeleteHZ (刪除雙位元漢字)、DeleteEN (刪除單位元英數符號)、Ufn_convertWideNumericToAnsi (全形數字轉半形),均採迴圈逐字元判斷 DATALENGTH 實現,相容 SQL Server 2000+。
CREATE FUNCTION DeleteHZ (@cargoname VARCHAR(512))
RETURNS VARCHAR(512)
AS BEGIN
DECLARE @Result VARCHAR(512) = '', @sno SMALLINT = 1;
WHILE @sno <= DATALENGTH(@cargoname)
BEGIN
IF DATALENGTH(SUBSTRING(@cargoname, @sno, 1)) = 1
SET @Result = @Result + SUBSTRING(@cargoname, @sno, 1);
SET @sno = @sno + 1;
END
RETURN @Result;
END
測試:SELECT dbo.DeleteHZ('CUSTOMS CUSTOMS報關員') → CUSTOMS CUSTOMS
CREATE FUNCTION DeleteEN (@cargoname VARCHAR(512))
RETURNS VARCHAR(512)
AS BEGIN
DECLARE @Result VARCHAR(512) = '', @sno SMALLINT = 1;
WHILE @sno <= DATALENGTH(@cargoname)
BEGIN
IF DATALENGTH(SUBSTRING(@cargoname, @sno, 1)) = 2
SET @Result = @Result + SUBSTRING(@cargoname, @sno, 1);
SET @sno = @sno + 1;
END
RETURN @Result;
END
原理:中文編碼環境下,漢字佔 2 bytes,英數佔 1 byte,利用 DATALENGTH 區分。
CREATE FUNCTION Ufn_convertWideNumericToAnsi (@vstrIn VARCHAR(1000))
RETURNS VARCHAR(4000)
AS BEGIN
DECLARE @strReturn VARCHAR(4000) = '', @bin VARBINARY(4000), @str VARCHAR(4000),
@stmp VARCHAR(4), @i INT = 1, @len INT;
SET @bin = CONVERT(VARBINARY(4000), @vstrIn);
EXEC master..xp_varbintohexstr @bin, @str OUTPUT; -- 轉十六進位字串 0x...
SET @str = STUFF(@str, 1, 2, ''); -- 移除 '0x'
SET @len = LEN(@str);
WHILE @i < @len
BEGIN
SET @stmp = SUBSTRING(@str, @i, 4); -- 每字元 4 hex 位
IF SUBSTRING(@stmp, 1, 1) <> 'A' RETURN @vstrIn; -- 非全形數字直接回傳原值
SET @stmp = REPLACE(REPLACE(@stmp, 'A', ''), 'B', ''); -- 移除 A/B 前綴
SET @stmp = CAST((CONVERT(INT, @stmp) - 30) AS VARCHAR(1)); -- 0xA330=全形0 → 30h=48 → 48-30=18? 實測邏輯需依編碼調整
SET @strReturn = @strReturn + @stmp;
SET @i = @i + 4;
END
RETURN @strReturn;
END
測試:SELECT dbo.Ufn_convertWideNumericToAnsi('031851001845') → 同樣字串 (若輸入真全形則轉半形)。
逐字元迴圈在大量資料下較慢。SQL Server 2016+ 可改用 TRANSLATE 或 CLR 函數;若頻繁呼叫,建議在 ETL 階段一次性清洗而非查詢時即時計算。