oracle sql 中的 ascii 函数,用于非 ascii 值
ascii function in oracle sql, for non-ascii value
在 Oracle 中 SQL:
当我们将任何非 ascii 字符传递给 ascii 函数时,它会返回一些数字。我们如何解释这个数字。如果我们将字符设置为 AL32UTF8,为什么它不返回给定字符的 Unicode 点
select * from nls_database_parameters where parameter = 'NLS_CHARACTERSET';--AL32UTF8
select ascii('Á') from dual;--50049
这个值50049是什么意思?我期待 193
参见文档:ASCII
ASCII
returns the decimal representation in the database character set of the first character of char.
字符Á
(U+00C1)在UTF-8中的二进制值为xC381
,即十进制50049。
193 是代码点。对于 UTF-8,代码点仅对字符 U+0000 - U+007F (0-127) 等于二进制表示。对于 UTF-16BE,代码点仅对字符 U+0000 - U+FFFF (0-65535),
等于二进制表示
也许您正在寻找
ASCIISTR('Á')
其中return是[=17=]C1
,只需要转成十进制即可
前段时间我开发了这个功能,比ASCIISTR
更高级,它也可以工作多码字符。
CREATE OR REPLACE TYPE VARCHAR_TABLE_TYPE AS TABLE OF VARCHAR2(100);
FUNCTION UNICODECHAR(uchar VARCHAR2) RETURN VARCHAR_TABLE_TYPE IS
UTF16 VARCHAR2(32000) := ASCIISTR(uchar);
UTF16_Table VARCHAR_TABLE_TYPE := VARCHAR_TABLE_TYPE();
sg1 VARCHAR2(4);
sg2 VARCHAR2(4);
codepoint INTEGER;
res VARCHAR_TABLE_TYPE := VARCHAR_TABLE_TYPE();
i INTEGER;
BEGIN
IF uchar IS NULL THEN
RETURN VARCHAR_TABLE_TYPE();
END IF;
SELECT REGEXP_SUBSTR(UTF16, '(\[[:xdigit:]]{4})|.', 1, LEVEL)
BULK COLLECT INTO UTF16_Table
FROM dual
CONNECT BY REGEXP_SUBSTR(UTF16, '\[[:xdigit:]]{4}|.', 1, LEVEL) IS NOT NULL;
i := UTF16_Table.FIRST;
WHILE i IS NOT NULL LOOP
res.EXTEND;
IF REGEXP_LIKE(UTF16_Table(i), '^\') THEN
IF REGEXP_LIKE(UTF16_Table(i), '^\D(8|9|A|B)') THEN
sg1 := REGEXP_SUBSTR(UTF16_Table(i), '[[:xdigit:]]{4}');
i := UTF16_Table.NEXT(i);
sg2 := REGEXP_SUBSTR(UTF16_Table(i), '[[:xdigit:]]{4}');
codepoint := 2**10 * (TO_NUMBER(sg1, 'XXXX') - TO_NUMBER('D800', 'XXXX')) + TO_NUMBER(sg2, 'XXXX') - TO_NUMBER('DC00', 'XXXX') + 2**16;
res(res.LAST) := 'U+'||TO_CHAR(codepoint, 'fmXXXXXX');
ELSE
res(res.LAST) := 'U+'||REGEXP_REPLACE(UTF16_Table(i), '^\');
END IF;
ELSE
res(res.LAST) := 'U+'||LPAD(TO_CHAR(ASCII(UTF16_Table(i)), 'fmXX'), 4, '0');
END IF;
i := UTF16_Table.NEXT(i);
END LOOP;
RETURN res;
END UNICODECHAR;
试试 https://unicode.org/emoji/charts/full-emoji-list.html#1f3f3_fe0f_200d_1f308
中的一些示例
UNICODECHAR('☠️')
应该return
U+1F3F4
U+200D
U+2620
U+FE0F
这里 - 主要是为了我自己的教育 - 是对重音 A 的值 50049 的解释(代码点:Unicode 编码字符集中的 193)。我刚刚通过阅读 https://www.fileformat.info/info/unicode/utf8.htm Another pretty clear explanation and an example for a three-byte encoding on Wikipedia: https://en.wikipedia.org/wiki/UTF-8#Encoding
了解到这是如何工作的
编码的计算源自代码点 193,与与该代码点关联的特定字符无关。
UTF-8 使用相对简单的方案对最大 1,141,111 个代码点进行编码(或者,现在可能更多;现在我们只担心达到该上限的代码点)。
从 1 到 127(十进制)的代码点被编码为一个字节,等于代码点(因此当以二进制表示时,字节总是有一个前导零)。
从 128 到 2047 的代码点被编码为两个字节。在二进制表示中,第一个字节始终以 110 开头,第二个字节始终以 10 开头。以 110 开头的字节始终是 two-byte 编码的第一个字节,而以 10 开头的字节始终是 " multi-byte 编码中的连续”字节(第二个、第三个或第四个)。这些强制性前缀是编码方案的一部分(UTF8 编码的“规则”);它们是规则中的 hard-coded 个值。
因此:对于从 128 到 2047 的代码点,编码为两个字节,二进制表示法的确切格式为 110xxxxx 和 10xxxxxx。第一个字节的最后五位数字(位)加上第二个字节的最后六位数字(总共:11 位)是代码点的二进制表示(必须编码的从 128 到 2047 的值)。
2047 = 2^11 - 1(这就是为什么 2047 与此相关)。代码点可以表示为 11 位二进制数(可能带有前导零)。取前五位(在 left-padding 之后,长度为 0 到 11 位)并将其附加到第一个字节的强制性 110 前缀,并将代码点的后六位附加到强制性第二个字节的前缀 10。这给出了给定代码点的 UTF8 编码(两个字节)。
让我们对代码点 193(十进制)执行此操作。在二进制中,左边用 0 填充,即 00011000001。到目前为止,没什么特别的。
将其分成五位||六位:00011 和 000001.
附加强制性前缀:11000011 和 10000001。
用十六进制重写这些:\xC3 和 \x81。把它们放在一起;这是十六进制 C381,或十进制 50049。
在 Oracle 中 SQL:
当我们将任何非 ascii 字符传递给 ascii 函数时,它会返回一些数字。我们如何解释这个数字。如果我们将字符设置为 AL32UTF8,为什么它不返回给定字符的 Unicode 点
select * from nls_database_parameters where parameter = 'NLS_CHARACTERSET';--AL32UTF8
select ascii('Á') from dual;--50049
这个值50049是什么意思?我期待 193
参见文档:ASCII
ASCII
returns the decimal representation in the database character set of the first character of char.
字符Á
(U+00C1)在UTF-8中的二进制值为xC381
,即十进制50049。
193 是代码点。对于 UTF-8,代码点仅对字符 U+0000 - U+007F (0-127) 等于二进制表示。对于 UTF-16BE,代码点仅对字符 U+0000 - U+FFFF (0-65535),
等于二进制表示也许您正在寻找
ASCIISTR('Á')
其中return是[=17=]C1
,只需要转成十进制即可
前段时间我开发了这个功能,比ASCIISTR
更高级,它也可以工作多码字符。
CREATE OR REPLACE TYPE VARCHAR_TABLE_TYPE AS TABLE OF VARCHAR2(100);
FUNCTION UNICODECHAR(uchar VARCHAR2) RETURN VARCHAR_TABLE_TYPE IS
UTF16 VARCHAR2(32000) := ASCIISTR(uchar);
UTF16_Table VARCHAR_TABLE_TYPE := VARCHAR_TABLE_TYPE();
sg1 VARCHAR2(4);
sg2 VARCHAR2(4);
codepoint INTEGER;
res VARCHAR_TABLE_TYPE := VARCHAR_TABLE_TYPE();
i INTEGER;
BEGIN
IF uchar IS NULL THEN
RETURN VARCHAR_TABLE_TYPE();
END IF;
SELECT REGEXP_SUBSTR(UTF16, '(\[[:xdigit:]]{4})|.', 1, LEVEL)
BULK COLLECT INTO UTF16_Table
FROM dual
CONNECT BY REGEXP_SUBSTR(UTF16, '\[[:xdigit:]]{4}|.', 1, LEVEL) IS NOT NULL;
i := UTF16_Table.FIRST;
WHILE i IS NOT NULL LOOP
res.EXTEND;
IF REGEXP_LIKE(UTF16_Table(i), '^\') THEN
IF REGEXP_LIKE(UTF16_Table(i), '^\D(8|9|A|B)') THEN
sg1 := REGEXP_SUBSTR(UTF16_Table(i), '[[:xdigit:]]{4}');
i := UTF16_Table.NEXT(i);
sg2 := REGEXP_SUBSTR(UTF16_Table(i), '[[:xdigit:]]{4}');
codepoint := 2**10 * (TO_NUMBER(sg1, 'XXXX') - TO_NUMBER('D800', 'XXXX')) + TO_NUMBER(sg2, 'XXXX') - TO_NUMBER('DC00', 'XXXX') + 2**16;
res(res.LAST) := 'U+'||TO_CHAR(codepoint, 'fmXXXXXX');
ELSE
res(res.LAST) := 'U+'||REGEXP_REPLACE(UTF16_Table(i), '^\');
END IF;
ELSE
res(res.LAST) := 'U+'||LPAD(TO_CHAR(ASCII(UTF16_Table(i)), 'fmXX'), 4, '0');
END IF;
i := UTF16_Table.NEXT(i);
END LOOP;
RETURN res;
END UNICODECHAR;
试试 https://unicode.org/emoji/charts/full-emoji-list.html#1f3f3_fe0f_200d_1f308
中的一些示例UNICODECHAR('☠️')
应该return
U+1F3F4
U+200D
U+2620
U+FE0F
这里 - 主要是为了我自己的教育 - 是对重音 A 的值 50049 的解释(代码点:Unicode 编码字符集中的 193)。我刚刚通过阅读 https://www.fileformat.info/info/unicode/utf8.htm Another pretty clear explanation and an example for a three-byte encoding on Wikipedia: https://en.wikipedia.org/wiki/UTF-8#Encoding
了解到这是如何工作的编码的计算源自代码点 193,与与该代码点关联的特定字符无关。
UTF-8 使用相对简单的方案对最大 1,141,111 个代码点进行编码(或者,现在可能更多;现在我们只担心达到该上限的代码点)。
从 1 到 127(十进制)的代码点被编码为一个字节,等于代码点(因此当以二进制表示时,字节总是有一个前导零)。
从 128 到 2047 的代码点被编码为两个字节。在二进制表示中,第一个字节始终以 110 开头,第二个字节始终以 10 开头。以 110 开头的字节始终是 two-byte 编码的第一个字节,而以 10 开头的字节始终是 " multi-byte 编码中的连续”字节(第二个、第三个或第四个)。这些强制性前缀是编码方案的一部分(UTF8 编码的“规则”);它们是规则中的 hard-coded 个值。
因此:对于从 128 到 2047 的代码点,编码为两个字节,二进制表示法的确切格式为 110xxxxx 和 10xxxxxx。第一个字节的最后五位数字(位)加上第二个字节的最后六位数字(总共:11 位)是代码点的二进制表示(必须编码的从 128 到 2047 的值)。
2047 = 2^11 - 1(这就是为什么 2047 与此相关)。代码点可以表示为 11 位二进制数(可能带有前导零)。取前五位(在 left-padding 之后,长度为 0 到 11 位)并将其附加到第一个字节的强制性 110 前缀,并将代码点的后六位附加到强制性第二个字节的前缀 10。这给出了给定代码点的 UTF8 编码(两个字节)。
让我们对代码点 193(十进制)执行此操作。在二进制中,左边用 0 填充,即 00011000001。到目前为止,没什么特别的。
将其分成五位||六位:00011 和 000001.
附加强制性前缀:11000011 和 10000001。
用十六进制重写这些:\xC3 和 \x81。把它们放在一起;这是十六进制 C381,或十进制 50049。