2017-05-05 113 views
3

我有統一的這樣一個順序:T-SQL轉換UNICODE到表情符號

\ U0001F468 \ U0000200D \ U0001F466

如何變換,在T-SQL到相應的表情符號,並插入表情符號在一個nvchar類型的列?

+0

是Unicode編碼的這個實際的Unicode字符,或ASCII表示?什麼版本的SQL Server? – alroc

+0

而且,是否在其他文本中保留了序列,或者是在其自己的專欄中作爲獨立值? – iamdave

+0

最終我選擇在C#中完成,並且工作得很好。 – XIII

回答

2

Hooooookay所以我幾乎不知道這類事情的任何事情,但這是一個有趣的工作分心,我希望能幫助你到達需要的地方。

你可以從你的unicode引用中看到的emoji字符實際上是三個字符,全部被混合在一起。第一個是MAN,第二個是ZERO WIDTH JOINER,第三個是BOY。零寬度連接器的作用是在頁面移動或選擇文本時使其他兩個字符作爲一個字符。您可以在任何不支持的文本編輯器(如SSMS)中看到這種情況,在這種編輯器中,您的光標會在MAN和BOY字符之間「停頓」一個方向按鍵。

所以,爲了回答你的問題,我假定你的所有unicode值都是三個序列,而中間的一個是木匠,或者如果情況並非如此,那麼你將能夠工作從這裏出來你自己。

this very informative Stack Overflow answer開始,您將看到SQL Server對補充字符的處理有一點不完整。因此,您需要更改數據庫排序規則或給予幫助,即讓它知道是否需要將Unicode字符分解爲兩個字符或不是。因爲我假設你的序列都是Emoji-Joiner-Emoji這對我來說不是太大問題,但可能適合你。

首先,我們需要您的字符序列拆分成它的組成部分,爲此,我使用基於Jeff Moden's理貨表字符串劃分功能:

create function [dbo].[StringSplit] 
(
    @str nvarchar(4000) = ' '    -- String to split. 
    ,@delimiter as nvarchar(1) = ','  -- Delimiting value to split on. 
    ,@num as int = null      -- Which value to return. 
) 
returns @results table(ItemNumber int, Item nvarchar(4000)) 
as 
begin 
    declare @return nvarchar(4000); 
    -- Handle null @str values 
    select @str = case when len(isnull(@str,'')) = 0 then '' else @str end; 
        -- Start tally table with 10 rows. 
    with n(n) as (select n from (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n(n)) 
        -- Select the same number of rows as characters in @str as incremental row numbers. 
        -- Cross joins increase exponentially to a max possible 10,000 rows to cover largest @str length. 
     ,t(t) as (select top (select len(@str) a) row_number() over (order by (select null)) from n n1,n n2,n n3,n n4) 
        -- Return the position of every value that follows the specified delimiter. 
     ,s(s) as (select 1 union all select t+1 from t where substring(@str,t,1) = @delimiter) 
        -- Return the start and length of every value, to use in the SUBSTRING function. 
        -- ISNULL/NULLIF combo handles the last value where there is no delimiter at the end of the string. 
     ,l(s,l) as (select s,isnull(nullif(charindex(@delimiter,@str,s),0)-s,4000) from s) 
    insert into @results 
    select rn as ItemNumber 
      ,Item 
    from(select row_number() over(order by s) as rn 
       ,substring(@str,s,l) as item 
     from l 
     ) a 
    where rn = @num 
     or @num is null; 
    return; 
end 

使用此功能,我們可以分割的Unicode序列分成3部分並手動將數據轉換爲3列。繼在SO答案上面鏈接的解釋,這是因爲CodePoint值兩個表情符號(使用下面的腳本convert(int,(convert(varbinary(max),replace('<Your Uxxxxxxxxx unicode value>','U','0x'),1)))部分計算)爲655361114111之間,我們需要找到高代理低代理,但因爲這是沒有必要的零寬連接符,我們只需要二進制表示傳遞給nchar功能(注缺乏轉化爲int):

declare @s nvarchar(50) = '\U0001F468\U0000200D\U0001F466'; 

select nchar(55232+(i1/1024)) + nchar(56320+(i1%1024)) -- MAN emoji 
     +nchar(b2)          -- JOINER 
     +nchar(55232+(i3/1024)) + nchar(56320+(i3%1024)) -- BOY emoji 
     as Emoji 
from(select convert(int,(convert(varbinary(max),replace(s1.Item,'U','0x'),1))) as i1 
      ,convert(varbinary(max),replace(s2.Item,'U','0x'),1) as b2 
      ,convert(int,(convert(varbinary(max),replace(s3.Item,'U','0x'),1))) as i3 
    from stringsplit(@s,'\',2) as s1 
     ,stringsplit(@s,'\',3) as s2 
     ,stringsplit(@s,'\',4) as s3 
    ) as a; 

通過將所有這些nchar值串聯起來,我們結束用正確的字符表示你的表情符號離子:

輸出

Emoji 
----- 
‍