我在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)
答案 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()
)。