如何使用十六进制字符串格式的列在 Informix 中处理 bitand 操作
How to process bitand operation in Informix with column in hex string format
在 table 中,我有一个包含十六进制值的字符串列。例如值 '000000000000000a' 表示 10。现在我需要处理 bitand
操作:bitand(tableName.hexColumn, ?)
。当我阅读此函数的 Informix 规范时,它需要 2 个 int。所以我的问题是:处理这个操作更简单的方法是什么?
PS:Informix 中可能没有解决方案,所以我将不得不创建自己的 bitandhexstring
函数,其中输入将是 2 个字符串和十六进制形式,但我不知道从哪里开始。
有多种问题需要处理:
您的十六进制字符串有 16 位数字,因此这些值大概(通常)是 64 位数量。这意味着您需要确保 BITAND 函数具有处理 BIGINT(或者可能是 INT8 — 我不会再次提及 INT8,但在提及 BIGINT 时名义上是一个选项)数据的变体。
您需要将十六进制字符串转换为 BIGINT。
不清楚您是否需要将结果 BIGINT 转换回十六进制字符串。
在 Mac OS X 10.10.4 上使用 Informix 11.70.FC6 进行的一些测试表明 BITAND 对于 64 位数字是安全的。这是个好消息!
HEX 函数,当传递一个 BIGINT 时,returns 一个以 0x
开头并包含数字的十六进制表示的 CHAR(20) 字符串,这样或多或少的地址指向 3 .残差问题是'how to convert 16-byte strings of hex digits to a BIGINT value'。名义上,强制转换操作如:
CAST('0xde3962e8c68a8001' AS BIGINT)
应该可以完成这项工作(但请参阅下文)。可能有比蛮力和无知存储过程更好的方法,但我不能立即确定它是什么。
告诫讲师。
在测试时,我尝试了两个查询:
SELECT bi, HEX(bi) FROM Test_BigInt;
SELECT bi, HEX(bi), SUBSTR(HEX(bi), 3, 16) FROM Test_BigInt;
在 table Test_BigInt
上具有 BIGINT 类型的单个列 bi
(不为空,因为它发生了,但那不是 material)。
第一个查询运行良好。 HEX(bi)
表达式的类型是 CHAR(20),值类似于
0 0x0000000000000000
6898532535585831936 0x5fbc82ca87117c00
-2300268458811555839 0xe013ce0628808001
第二个查询适用于 bi
(0, 1, 2) 的小值,但当值变大时会生成错误 -1215: Value exceeds limit of INTEGER precision
。问题不直接出在 SUBSTR 函数上。这是在 Mac OS X 10.10.4 上使用 Informix 11.70.FC6 进行的测试 — 在 2015-07-08 进行了测试。以下一对查询按预期工作(这是我声称问题不在 SUBSTR 函数本身的理由)。
SELECT bi, HEX(bi) AS hex_bi FROM Test_BigInt INTO TEMP t;
SELECT bi, hex_bi, SUBSTR(hex_bi, 3, 16) FROM t;
在字符串操作上下文中使用HEX结果时,似乎是一个交互问题。我在尝试将空字符串连接到 HEX 的结果时首先遇到问题:HEX(bi) || ''
。事实证明这是不必要的,因为 HEX 的结果报告为 CHAR(20),但也表明 SUBSTR 不是直接的错误。
我也试过 CAST 将十六进制字符串转换为 BIGINT:
SELECT CAST('0xde3962e8c68a8001' AS BIGINT) FROM dual;
BIGINT
-964001791
SELECT HEX(CAST('0xde3962e8c68a8001' AS BIGINT)) FROM dual;
CHAR(18)
0xffffffffc68a8001
哎呀!转换处理不当。这不是新软件(已经超过 2 年了),但很有可能除非其他人发现了这个错误,否则它可能还没有被修复,即使在最新版本中也是如此。
我已经通过后台渠道向 IBM/Informix 报告了此事。
将十六进制字符串转换为 BIGINT 的存储过程
CREATE PROCEDURE hexval(c CHAR(1)) RETURNING INTEGER;
RETURN INSTR("0123456789abcdef", lower(c)) - 1;
END PROCEDURE;
CREATE PROCEDURE hexstr_to_bigint(ival VARCHAR(18)) RETURNING bigint;
DEFINE oval DECIMAL(20,0);
DEFINE i,j,len INTEGER;
LET ival = LOWER(ival);
IF (ival[1,2] = '0x') THEN LET ival = ival[3,18]; END IF;
LET len = LENGTH(ival);
LET oval = 0;
FOR i = 1 TO len
LET j = hexval(SUBSTR(ival, i, 1));
LET oval = oval * 16 + j;
END FOR;
IF (oval > 9223372036854775807) THEN
LET oval = oval - 18446744073709551616;
END IF;
RETURN oval;
END PROCEDURE;
休闲测试:
execute procedure hexstr_to_bigint('000A');
10
execute procedure hexstr_to_bigint('FFff');
65535
execute procedure hexstr_to_bigint('FFFFffffFFFFffff');
-1
execute procedure hexstr_to_bigint('0XFFFFffffFFFFffff');
-1
execute procedure hexstr_to_bigint('000000000000000A');
10
这些值是正确的。
在 table 中,我有一个包含十六进制值的字符串列。例如值 '000000000000000a' 表示 10。现在我需要处理 bitand
操作:bitand(tableName.hexColumn, ?)
。当我阅读此函数的 Informix 规范时,它需要 2 个 int。所以我的问题是:处理这个操作更简单的方法是什么?
PS:Informix 中可能没有解决方案,所以我将不得不创建自己的 bitandhexstring
函数,其中输入将是 2 个字符串和十六进制形式,但我不知道从哪里开始。
有多种问题需要处理:
您的十六进制字符串有 16 位数字,因此这些值大概(通常)是 64 位数量。这意味着您需要确保 BITAND 函数具有处理 BIGINT(或者可能是 INT8 — 我不会再次提及 INT8,但在提及 BIGINT 时名义上是一个选项)数据的变体。
您需要将十六进制字符串转换为 BIGINT。
不清楚您是否需要将结果 BIGINT 转换回十六进制字符串。
在 Mac OS X 10.10.4 上使用 Informix 11.70.FC6 进行的一些测试表明 BITAND 对于 64 位数字是安全的。这是个好消息!
HEX 函数,当传递一个 BIGINT 时,returns 一个以 0x
开头并包含数字的十六进制表示的 CHAR(20) 字符串,这样或多或少的地址指向 3 .残差问题是'how to convert 16-byte strings of hex digits to a BIGINT value'。名义上,强制转换操作如:
CAST('0xde3962e8c68a8001' AS BIGINT)
应该可以完成这项工作(但请参阅下文)。可能有比蛮力和无知存储过程更好的方法,但我不能立即确定它是什么。
告诫讲师。
在测试时,我尝试了两个查询:
SELECT bi, HEX(bi) FROM Test_BigInt;
SELECT bi, HEX(bi), SUBSTR(HEX(bi), 3, 16) FROM Test_BigInt;
在 table Test_BigInt
上具有 BIGINT 类型的单个列 bi
(不为空,因为它发生了,但那不是 material)。
第一个查询运行良好。 HEX(bi)
表达式的类型是 CHAR(20),值类似于
0 0x0000000000000000
6898532535585831936 0x5fbc82ca87117c00
-2300268458811555839 0xe013ce0628808001
第二个查询适用于 bi
(0, 1, 2) 的小值,但当值变大时会生成错误 -1215: Value exceeds limit of INTEGER precision
。问题不直接出在 SUBSTR 函数上。这是在 Mac OS X 10.10.4 上使用 Informix 11.70.FC6 进行的测试 — 在 2015-07-08 进行了测试。以下一对查询按预期工作(这是我声称问题不在 SUBSTR 函数本身的理由)。
SELECT bi, HEX(bi) AS hex_bi FROM Test_BigInt INTO TEMP t;
SELECT bi, hex_bi, SUBSTR(hex_bi, 3, 16) FROM t;
在字符串操作上下文中使用HEX结果时,似乎是一个交互问题。我在尝试将空字符串连接到 HEX 的结果时首先遇到问题:HEX(bi) || ''
。事实证明这是不必要的,因为 HEX 的结果报告为 CHAR(20),但也表明 SUBSTR 不是直接的错误。
我也试过 CAST 将十六进制字符串转换为 BIGINT:
SELECT CAST('0xde3962e8c68a8001' AS BIGINT) FROM dual;
BIGINT
-964001791
SELECT HEX(CAST('0xde3962e8c68a8001' AS BIGINT)) FROM dual;
CHAR(18)
0xffffffffc68a8001
哎呀!转换处理不当。这不是新软件(已经超过 2 年了),但很有可能除非其他人发现了这个错误,否则它可能还没有被修复,即使在最新版本中也是如此。
我已经通过后台渠道向 IBM/Informix 报告了此事。
将十六进制字符串转换为 BIGINT 的存储过程
CREATE PROCEDURE hexval(c CHAR(1)) RETURNING INTEGER;
RETURN INSTR("0123456789abcdef", lower(c)) - 1;
END PROCEDURE;
CREATE PROCEDURE hexstr_to_bigint(ival VARCHAR(18)) RETURNING bigint;
DEFINE oval DECIMAL(20,0);
DEFINE i,j,len INTEGER;
LET ival = LOWER(ival);
IF (ival[1,2] = '0x') THEN LET ival = ival[3,18]; END IF;
LET len = LENGTH(ival);
LET oval = 0;
FOR i = 1 TO len
LET j = hexval(SUBSTR(ival, i, 1));
LET oval = oval * 16 + j;
END FOR;
IF (oval > 9223372036854775807) THEN
LET oval = oval - 18446744073709551616;
END IF;
RETURN oval;
END PROCEDURE;
休闲测试:
execute procedure hexstr_to_bigint('000A');
10
execute procedure hexstr_to_bigint('FFff');
65535
execute procedure hexstr_to_bigint('FFFFffffFFFFffff');
-1
execute procedure hexstr_to_bigint('0XFFFFffffFFFFffff');
-1
execute procedure hexstr_to_bigint('000000000000000A');
10
这些值是正确的。