在 SQL 服务器内循环 - IP 迭代
Looping within SQL Server - Iteration of IPs
示例输入
示例输出
我相信这可以使用 WHILE 循环来解决,但无法弄清楚如何将它反透视到一个列中,同时只增加最后一个数字。
编辑:IP 范围由我创建,我随机选择了它们。
我会留下这个答案以防它对任何人有帮助。然而,这是针对 Postgres 的。
不清楚基本类型是什么,但您可以为此使用 inet
函数——通过转换为 int
然后再转换回来:
select ip + '0.0.0.0'::inet, (ip + '0.0.0.0'::inet)::text, host(ip + '0.0.0.0'::inet)
from t cross join lateral
generate_series(ips::inet - '0.0.0.0'::inet, ipe::inet - '0.0.0.0'::inet, 1) ip;
Here 是一个 db<>fiddle.
第一列是值的 inet
表示。第二个是字符串表示,但使用标准 IPV4 表示法。最终看起来像输入数据。
我相信我已经解决了你的问题。通过这种技术,我们也解决了Larnu在评论中提到的问题。
DECLARE @tbl TABLE (IP_start varchar(15), IP_end varchar(15))
DECLARE @i int=1
INSERT INTO @tbl (IP_start, IP_end)
VALUES ('121.11.32.0','121.11.32.5')
,('121.11.33.11','121.11.33.11')
,('121.11.34.0','121.11.34.4')
/*,('121.11.35.0','121.11.36.15')*/
;WITH cte
AS
(SELECT
t.IP_start, t.IP_end
,CAST(CAST(PARSENAME(t.IP_start,4) AS int) AS binary(1))+CAST(CAST(PARSENAME(t.IP_start,3) AS int) AS binary(1))+CAST(CAST(PARSENAME(t.IP_start,2) AS int) AS binary(1))+CAST(CAST(PARSENAME(t.IP_start,1) AS int) AS binary(1)) AS ip_Bin
FROM @tbl t
UNION ALL
SELECT
tt.IP_start, tt.IP_end
,cast((cast(cte.ip_Bin AS int)+@i) AS binary(4))
FROM cte INNER JOIN
@tbl tt ON tt.IP_start=cte.IP_start AND cte.IP_end=tt.IP_end
WHERE cte.ip_Bin<CAST(CAST(PARSENAME(tt.IP_end,4) AS int) AS binary(1))+CAST(CAST(PARSENAME(tt.IP_end,3) AS int) AS binary(1))+CAST(CAST(PARSENAME(tt.IP_end,2) AS int) AS binary(1))+CAST(CAST(PARSENAME(tt.IP_end,1) AS int) AS binary(1))
)
SELECT CAST(CAST(SUBSTRING(cte.ip_Bin,1,1) AS int) AS varchar(3))+'.'+ CAST(CAST(SUBSTRING(cte.ip_Bin,2,1) AS int) AS varchar(3))+'.'+ CAST(CAST(SUBSTRING(cte.ip_Bin,3,1) AS int) AS varchar(3))+'.'+ CAST(CAST(SUBSTRING(cte.ip_Bin,4,1) AS int) AS varchar(3))
FROM cte
ORDER BY cte.IP_start
OPTION(MAXRECURSION 0)
示例输入
示例输出
我相信这可以使用 WHILE 循环来解决,但无法弄清楚如何将它反透视到一个列中,同时只增加最后一个数字。
编辑:IP 范围由我创建,我随机选择了它们。
我会留下这个答案以防它对任何人有帮助。然而,这是针对 Postgres 的。
不清楚基本类型是什么,但您可以为此使用 inet
函数——通过转换为 int
然后再转换回来:
select ip + '0.0.0.0'::inet, (ip + '0.0.0.0'::inet)::text, host(ip + '0.0.0.0'::inet)
from t cross join lateral
generate_series(ips::inet - '0.0.0.0'::inet, ipe::inet - '0.0.0.0'::inet, 1) ip;
Here 是一个 db<>fiddle.
第一列是值的 inet
表示。第二个是字符串表示,但使用标准 IPV4 表示法。最终看起来像输入数据。
我相信我已经解决了你的问题。通过这种技术,我们也解决了Larnu在评论中提到的问题。
DECLARE @tbl TABLE (IP_start varchar(15), IP_end varchar(15))
DECLARE @i int=1
INSERT INTO @tbl (IP_start, IP_end)
VALUES ('121.11.32.0','121.11.32.5')
,('121.11.33.11','121.11.33.11')
,('121.11.34.0','121.11.34.4')
/*,('121.11.35.0','121.11.36.15')*/
;WITH cte
AS
(SELECT
t.IP_start, t.IP_end
,CAST(CAST(PARSENAME(t.IP_start,4) AS int) AS binary(1))+CAST(CAST(PARSENAME(t.IP_start,3) AS int) AS binary(1))+CAST(CAST(PARSENAME(t.IP_start,2) AS int) AS binary(1))+CAST(CAST(PARSENAME(t.IP_start,1) AS int) AS binary(1)) AS ip_Bin
FROM @tbl t
UNION ALL
SELECT
tt.IP_start, tt.IP_end
,cast((cast(cte.ip_Bin AS int)+@i) AS binary(4))
FROM cte INNER JOIN
@tbl tt ON tt.IP_start=cte.IP_start AND cte.IP_end=tt.IP_end
WHERE cte.ip_Bin<CAST(CAST(PARSENAME(tt.IP_end,4) AS int) AS binary(1))+CAST(CAST(PARSENAME(tt.IP_end,3) AS int) AS binary(1))+CAST(CAST(PARSENAME(tt.IP_end,2) AS int) AS binary(1))+CAST(CAST(PARSENAME(tt.IP_end,1) AS int) AS binary(1))
)
SELECT CAST(CAST(SUBSTRING(cte.ip_Bin,1,1) AS int) AS varchar(3))+'.'+ CAST(CAST(SUBSTRING(cte.ip_Bin,2,1) AS int) AS varchar(3))+'.'+ CAST(CAST(SUBSTRING(cte.ip_Bin,3,1) AS int) AS varchar(3))+'.'+ CAST(CAST(SUBSTRING(cte.ip_Bin,4,1) AS int) AS varchar(3))
FROM cte
ORDER BY cte.IP_start
OPTION(MAXRECURSION 0)