66

在 SQL Server 中存储 IPv4 地址时最推荐的数据类型应该是什么?

或者也许有人已经为它创建了一个用户 SQL 数据类型(.Net 程序集)?

我不需要排序。

4

13 回答 13

62

将 IPv4 地址存储为binary(4) 最符合其所代表的内容,并且可以轻松进行子网掩码式查询。但是,如果您实际上是在文本表示之后,它需要转换输入和输出。在这种情况下,您可能更喜欢字符串格式。

顺便说一句,如果您将存储为字符串,一个很少使用的 SQL Server 函数可能会有所帮助PARSENAME。不是为 IP 地址设计的,但非常适合它们。下面的调用将返回“14”:

SELECT PARSENAME('123.234.23.14', 1)

(编号从右到左)。

于 2009-06-24T15:10:29.590 回答
27

我通常只对 IPv4 地址使用 varchar(15) - 但是对它们进行排序很痛苦,除非你填充零。

我过去也将它们存储为 INT。 System.Net.IPAddress有一个GetAddressBytes方法将 IP 地址作为代表 IP 地址的 4 个字节的数组返回。您可以使用以下 C# 代码将 an 转换IPAddressint...

var ipAsInt = BitConverter.ToInt32(ip.GetAddressBytes(), 0);

我之所以使用它,是因为我必须做大量的重复地址搜索,并且希望索引尽可能小和快。然后将地址从 int 中拉回IPAddress.net 中的对象中,使用GetByteson 方法BitConverter将 int 作为字节数组获取。将该字节数组传递给构造函数,因为IPAddress它需要一个字节数组,最后IPAddress你会得到你开始的那个。

var myIp = new IPAddress(BitConverter.GetBytes(ipAsInt));
于 2009-06-24T15:07:15.837 回答
19

关于已接受答案中的此评论

除非您填充零,否则对它们进行排序很痛苦。

这是 SQL Server 2008 的一个技巧(来自本书中的 Itzik Ben-Gan )

with ip_addresses as
(
SELECT '131.33.2.201' AS ip_address UNION ALL
SELECT '2.12.4.4' AS ip_address UNION ALL
SELECT '131.33.2.202' AS ip_address UNION ALL
SELECT '2.12.4.169' AS ip_address UNION ALL
SELECT '131.107.2.201' AS ip_address 
)
select ip_address
from ip_addresses
ORDER  BY CAST('/' + ip_address + '/' AS hierarchyid)

退货

ip_address
-------------
2.12.4.4
2.12.4.169
131.33.2.201
131.33.2.202
131.107.2.201
于 2010-08-09T15:42:37.433 回答
8

对于节省空间的存储以及要处理值(匹配或与范围比较)时,我使用int. IP 地址实际上只是一个 32 位值。

对于您只想存储值以查看它的简单解决方案,我使用 avarchar(15)来存储 IP 地址的字符串表示形式。

于 2009-06-24T15:18:27.170 回答
3

不要忘记 IPv6——如果你需要存储它们,你需要更多的空间——与 IPv4 的 32 位相比,128 位。

我会选择 bigint,尽管您需要一些帮助代码来翻译成人类友好的版本。

于 2009-06-24T15:16:40.777 回答
3

我最喜欢的一篇文章谈到了为什么不应该使用正则表达式来解析 IP 地址。他们谈论的大部分内容实际上是在解释为什么您应该非常小心 IP 地址的文本表示。我建议您在决定在数据库中使用什么数据类型之前阅读它,并且可能还考虑您的应用程序将要执行的任何处理(即使这篇文章是关于 Perl 的,它对任何语言都很有用)。

我认为最终 32 位数据类型(或四个 8 位数据类型)将是最佳选择。

于 2009-06-24T15:18:41.163 回答
3

我在这里阅读了很多类似的问题,并且没有一个回复提到其他人的第一答案:“对于 IPv4 地址,您可能希望将它们存储为 int unsigned 并使用 INET_ATON() 和INET_NTOA() 函数从其数值返回 IP 地址,反之亦然。” 我认为这就是我要在我的数据库中使用的内容,除非我决定使用上面提到的 php 函数。

于 2010-08-13T03:01:18.930 回答
2

IPV4?诠释?还是 tinyint x 4?

这实际上取决于它是否只是存储和检索,或者它是否将成为一个范围搜索条件。

于 2009-06-24T15:07:30.250 回答
2

这取决于你的目的。如果您想要最好的存储和可能的性能,并且在大多数情况下,将其存储为 int,将其存储为 varchar 等将比简单的无辜 int 花费更多的性能。
您也可以通过将搜索参数设置为所需的 int 来按 IP 进行搜索。

有一个属性IPAddress.Address,但它已经过时了,我不知道为什么,因为如果您不需要对 IP 类进行排序或控制,最好的方法是将其存储为无符号整数(其最大值0xffffffff等于255.255.255.255以十进制表示。
使用 EF Core,您可以使用转换器将其自动转换为IPAddress.

IPAddress 类也有一个接受长参数的构造函数。

根据 VS 调试器可视化工具,IPAddress 类本身将其内部变量存储为一个数字(不是字节数组)。

阅读有关在 MS SQL Server 中存储单元的解决方法的更多信息:

于 2010-08-09T23:47:44.347 回答
0

由于IP地址中有32位,您可以只使用LONG来存储数值吗?
它不会像使用 VARCHAR 那样浪费空间,但是每次使用它之前,您都必须将其解码回 IP,而且延迟和开销可能不值得。

于 2009-06-24T15:11:36.983 回答
0

我在制作四个 smallint(或您喜欢的任何小的整数数据类型)列方面取得了一些成功——每个八位字节一个。然后,您可以创建一个视图,将它们组合成一个字符字符串(用于显示),或者您可以编写简单的运算符来确定谁在哪个子网中等等。

它非常快(前提是您进行了正确的索引),并且还允许非常简单的查询(没有字符串操作!)。

于 2009-06-24T15:15:56.990 回答
-5

引用这个

将 IP 地址存储在 CHAR(15) 列中。根据您存储的数据量,这可能会非常浪费(为什么我们需要存储点?)。一世

于 2009-06-24T15:06:48.317 回答
-5

我是新手@ php,sql ,但我认为在 sql db 中存储某些内容的最快方法是将其转换为 int 值并另存为 int。

我在php中使用了函数-

function ip_convert() {
    $ip = $_SERVER['REMOTE_ADDR'];
    $intip = str_replace(".","0",$ip);
    return $intip;
}

然后我只是用零替换所有点。然后,如果我需要使用 sql 中的这个 ip .. if($ip == ip_convert())

但这仅在您使用 PHP 的情况下。

于 2014-06-15T17:35:26.833 回答