意外的字符串转换为十六进制

时间:2012-12-13 22:43:01

标签: mysql sql string view hex

我有一个公式设置,它采用小数,即基数10 3.6 three hours and point 6 minutes,并将决策位置转换为60 36 minutes的基数。然后使用天花板将分钟向上舍入到最近的15分钟增量,这样它总是向上舍入36 to 45 minutes。然后它将小时部分与分钟部分连接起来,并在它们之间放置一个字符串冒号。这个sql在视图中执行。

现在在视图中它以十六进制值而不是字符串值8:30 turns into 0x383A333020483A4D出现。但在选择查询中,它采用正确的串联字符串格式。发生了什么事?

CONCAT((((CEILING(((60 * ((agent_logins.hours_worked) % 1)) / 15)) * 15) / 60) + ((agent_logins.hours_worked) - ((agent_logins.hours_worked) % 1))) - (((CEILING(((60 * ((agent_logins.hours_worked) % 1)) / 15)) * 15) / 60) + ((agent_logins.hours_worked) - ((agent_logins.hours_worked) % 1))) % 1, ':', (((CEILING(((60 * ((agent_logins.hours_worked) % 1)) / 15)) * 15) / 60) + ((agent_logins.hours_worked) - ((agent_logins.hours_worked) % 1))) % 1 * 60) as hours_worked

3 个答案:

答案 0 :(得分:1)

正如CONCAT()所述:

  

如果参数包含任何二进制字符串,则结果为二进制字符串。数字参数将转换为其等效的字符串形式。这是MySQL 5.5.3中的非二进制字符串。在5.5.3之前,它是一个二进制字符串;要避免这种情况并生成非二进制字符串,可以使用显式类型转换,如下例所示:

SELECT CONCAT(CAST(int_col AS CHAR), char_col);

您必须使用5.5.3之前的MySQL版本,因此CONCAT()的数字参数将转换为二进制字符串(导致整个二进制字符串)。您的客户端以十六进制形式向您显示二进制列,这是一种合理的行为。

正如文档所述(以及@SofianeM's answer中的建议),您可以通过显式转换回CONVERT()CAST()的非二进制字符串来克服此问题。

但是,为什么不简单地使用SEC_TO_TIME()

SELECT SEC_TO_TIME(CEILING(4 * hours_worked) * 900)
FROM   agent_logins

sqlfiddle上查看。

答案 1 :(得分:1)

该十六进制表示的前四个字节似乎表示您期望的字符串值'8:30'的ASCII编码。接下来的四个字节显示为代表' H:M'的ASCII编码。

0x38 = '8'
0x3A = ':'
0x33 = '3'
0x30 = '0'
0x20 = ' '
0x48 = 'H'
0x3A = ':'
0x4D = 'M'

这并没有真正回答你问的问题,但是......

为什么不使用MySQL内置函数来执行此类格式化? (一种可能的解释是,您需要使用的“持续时间”值超出了MySQL TIME数据类型允许的限制,即-838:59:59到838:59:59。)

否则,您可以使用更简单的表达式将时间向上舍入到最近的15分钟边界,并将其格式化为小时:分钟的字符串表示

TIME_FORMAT(SEC_TO_TIME(CEILING( agent_login.hours_worked *4)*900),'%k:%i')

SQL Fiddle Here


当SELECT生成的字符串只有4个字符,或者客户端选择显示十六进制表示的原因时,使用视图作为行源的SELECT语句返回8个字符的原因一点也不清楚。 (八个字节确实恰好是BIGINT的长度。)

答案 2 :(得分:0)

Convert(exp, type)解决了这个问题。 Conversions