我将EMOJI符号从Web应用程序保存到Oracle数据库。在html中,此符号由&#128514编码。 即我写
<html>😂</html>
,我将在浏览器中看到它。 但是在数据库中查询
select ascii(sym) from ..
返回值4036991106。 问题是为什么这些代码不同(128514和4036991106),以及如何将它们转换为另一种? 查询
select value from nls_database_parameters where parameter='NLS_CHARACTERSET'
返回值“ AL32UTF8”。 查询
select sym...
返回”,这是我保存的符号。
答案 0 :(得分:1)
阅读文档:ASCII
ASCII
返回数据库字符集中的十进制表示形式 char的第一个字符。
另请参阅Face with Tears of Joy U+1F602
转换不是那么简单,您可以使用此块。
DECLARE
codepoint INTEGER := 128514;
sg1 CHAR(2);
sg2 CHAR(2);
sg3 CHAR(2);
sg4 CHAR(2);
res VARCHAR2(20);
BEGIN
--128 = x80 = 10000000 -> 10xxxxxx
--192 = xC0 = 11000000 -> 110xxxxx
--224 = eE0 = 11100000 -> 1110xxxx
--240 = xF0 = 11110000 -> 11110xxx
IF codepoint <= 127 THEN
res := LPAD(TO_CHAR(codepoint, 'fmXX'), 2, '0');
ELSIF codepoint <= 2047 THEN
sg1 := TO_CHAR(192 + TRUNC(codepoint / 2**6), 'fmXX');
sg2 := TO_CHAR(128 + codepoint MOD 2**6, 'fmXX');
res := LPAD(sg1, 2, '0')||LPAD(sg2, 2, '0');
ELSIF codepoint <= 65535 THEN
sg1 := TO_CHAR(224 + TRUNC(codepoint / 2**12), 'fmXX');
sg2 := TO_CHAR(128 + TRUNC(codepoint / 2**6) MOD 2**6, 'fmXX');
sg3 := TO_CHAR(128 + codepoint MOD 2**6, 'fmXX');
res := LPAD(sg1, 2, '0')||LPAD(sg2, 2, '0')||LPAD(sg3, 2, '0');
ELSE
sg1 := TO_CHAR(240 + TRUNC(codepoint / 2**18), 'fmXX');
sg2 := TO_CHAR(128 + TRUNC(codepoint / 2**12) MOD 2**12, 'fmXX');
sg3 := TO_CHAR(128 + TRUNC(codepoint / 2**6) MOD 2**6, 'fmXX');
sg4 := TO_CHAR(codepoint MOD 2**6 + 128, 'fmXX');
res := LPAD(sg1, 2, '0')||LPAD(sg2, 2, '0')||LPAD(sg3, 2, '0')||LPAD(sg4, 2, '0');
END IF;
DBMS_OUTPUT.PUT_LINE( 'Hex:'||res );
DBMS_OUTPUT.PUT_LINE( 'Decimal: '||TO_NUMBER(res, 'XXXXXXXX') );
END;
结果:
Hex: F09F9882
Decimal: 4036991106
要在另一个方向进行转换,可以使用此功能:
CREATE OR REPLACE FUNCTION UNICODECHAR(uchar VARCHAR2)
RETURN VARCHAR2 DETERMINISTIC IS
utf16 VARCHAR2(10) := ASCIISTR(uchar);
sg1 VARCHAR2(4);
sg2 VARCHAR2(4);
codepoint INTEGER;
BEGIN
IF REGEXP_LIKE(utf16, '^\\') THEN
IF LENGTH(utf16) = 5 THEN
RETURN REGEXP_REPLACE(utf16, '^\\');
ELSE
sg1 := REGEXP_SUBSTR(utf16, '[[:xdigit:]]{4}');
sg2 := REGEXP_SUBSTR(utf16, '[[:xdigit:]]{4}', 5);
codepoint := 2**10 * (TO_NUMBER(sg1, 'XXXX') - TO_NUMBER('D800', 'XXXX')) + TO_NUMBER(sg2, 'XXXX') - TO_NUMBER('DC00', 'XXXX') + 2**16;
RETURN TO_CHAR(codepoint, 'fmXXXXXX');
END IF;
ELSE
RETURN TO_CHAR(ASCII(uchar), 'fmXX');
END IF;
END UNICODECHAR;
然后运行
select TO_NUMBER(UNICODECHAR(sym), 'XXXXXXXX') from ..