将数据库列从UNSIGNED更改为BINARY而不转换为字符串

时间:2015-05-16 13:05:09

标签: mysql mariadb

我在UNSIGNED INTEGER列中有一个包含IPv4地址的表。我现在将其更改为支持IPv6地址,由INET6_ATON()返回,需要VARBINARY(16)列类型。

https://mariadb.com/kb/en/mariadb/inet6_aton/

如何更改现有列以保留其内容?

ALTER TABLE hitcounts CHANGE ip ip BINARY(16);

上面的命令似乎是将无符号整数值转换为等价的字符串,这不是我想要的。

示范

CREATE TEMPORARY TABLE hitcounts (ip INTEGER UNSIGNED);
INSERT INTO hitcounts VALUES (INET_ATON('78.156.181.3')),(INET_ATON('64.255.180.66')),(INET_ATON('31.126.241.81'));
SELECT * FROM hitcounts;
+------------+
| ip         |
+------------+
| 1318892803 |
| 1090499650 |
|  528413009 |
+------------+
3 rows in set (0.00 sec)

ALTER TABLE hitcounts MODIFY COLUMN ip VARBINARY(16);
SELECT * FROM hitcounts;
+------------+
| ip         |
+------------+
| 1318892803 |
| 1090499650 |
| 528413009  |
+------------+
3 rows in set (0.00 sec)

虽然转换的ip值似乎已被保留,但实际上它们已被转换为ASCII字符串(请注意第三行的左对齐与正确对齐时使用的右对齐)。尝试获取IP地址将失败:

SELECT INET6_NTOA(ip) FROM hitcounts;
+----------------+
| INET6_NTOA(ip) |
+----------------+
| NULL           |
| NULL           |
| NULL           |
+----------------+
3 rows in set (0.01 sec)

2 个答案:

答案 0 :(得分:1)

简单的解决方案是按照描述更改列,然后更新列以转换为由INET6_ATON()生成的二进制字符串:

select f1.name as name1, f2.name as name2, 
   case when b.winner = b.res1 then f1.name else f1.name end as winner
from battle b 
join fighters f1
  on b.res1 = f1.id
join fighters f2
  on b.res2 = f2.id

答案 1 :(得分:0)

由于INET6函数处理IPv4的4字节二进制和IPv6的16字节二进制,我认为这更接近'正确':

ALTER TABLE hitcounts MODIFY COLUMN ip VARBINARY(16) NOT NULL;

VAR是因为INET6_ATON('1.2.3.4')生成了BINARY(4)字符串。

我尚未确认仅将UNSIGNED转换为VARBINARY(16)会正确保留IPv4值。

需要MySQL 5.6.3或MariaDB 10.0.12。 (在某些早期,我认为MariaDB使用了不同的拼写:INET6_NTOP()INET6_PTON())。