/*------------------
*IP 地址分解
------------------------*/
--环境
CREATE TABLE dbo.IPs(ip varchar(15) NOT NULL PRIMARY KEY)
go
--check约束验证IP合法性
ALTER TABLE dbo.IPs ADD CONSTRAINT CHK_IP_valid CHECK
(
ip LIKE '_%._%._%._%'
AND
ip NOT LIKE '%.%.%.%.%'
AND
ip NOT LIKE '%[^0-9.]%'
AND
ip NOT LIKE '%[0-9][0-9][0-9][0-9]%'
AND
ip NOT LIKE '%[3-9][0-9][0-9]%'
AND
ip NOT LIKE '%2[6-9][0-9]%'
AND
ip NOT LIKE '%25[6-9]%'
);
go
INSERT INTO dbo.IPs VALUES('131.107.2.201');
INSERT INTO dbo.IPs VALUES('131.33.2.201');
INSERT INTO dbo.IPs VALUES('131.33.2.202');
INSERT INTO dbo.IPs VALUES('3.107.2.4');
INSERT INTO dbo.IPs VALUES('3.107.3.169');
INSERT INTO dbo.IPs VALUES('3.107.104.172');
INSERT INTO dbo.IPs VALUES('22.107.202.123');
INSERT INTO dbo.IPs VALUES('22.20.2.77');
INSERT INTO dbo.IPs VALUES('22.156.9.91');
INSERT INTO dbo.IPs VALUES('22.156.89.32');
go
--方法:巧用PARSENAME
select IP,COL1=PARSENAME(IP,4),COL2=PARSENAME(ip,3),COL2=PARSENAME(ip,2),COL2=PARSENAME(ip,1)
FROM IPs
go
--方法:模式匹配
--1:建立模式模式匹配表
CREATE VIEW dbo.IPPatterns
AS
SELECT
REPLICATE('_', N1.n) + '.' + REPLICATE('_', N2.n) + '.'
+ REPLICATE('_', N3.n) + '.' + REPLICATE('_', N4.n) AS pattern,
N1.n AS l1, N2.n AS l2, N3.n AS l3, N4.n AS l4,
1 AS s1, N1.n+2 AS s2, N1.n+N2.n+3 AS s3, N1.n+N2.n+N3.n+4 AS s4
FROM dbo.Num AS N1, dbo.Num AS N2, dbo.Num AS N3, dbo.Num AS N4 --这里的NUM表是一张-100W的辅助表,建立方法我上篇说过了
WHERE N1.n <= 3 AND N2.n <= 3 AND N3.n <= 3 AND N4.n <= 3;
GO
--select * from dbo.IPPatterns
--2.连接IP实表
SELECT ip,
CAST(SUBSTRING(ip, s1, l1) AS TINYINT) AS COL1,
CAST(SUBSTRING(ip, s2, l2) AS TINYINT) AS COL2,
CAST(SUBSTRING(ip, s3, l3) AS TINYINT) AS COL3,
CAST(SUBSTRING(ip, s4, l4) AS TINYINT) AS COL4
FROM dbo.IPs
JOIN dbo.IPPatterns
ON ip LIKE pattern
ORDER BY COL1, COL2, COL3, COL4;
GO
/*
ip COL1 COL2 COL3 COL4
--------------- ---- ---- ---- ----
3.107.2.4 3 107 2 4
3.107.3.169 3 107 3 169
3.107.104.172 3 107 104 172
22.20.2.77 22 20 2 77
22.107.202.123 22 107 202 123
22.156.9.91 22 156 9 91
22.156.89.32 22 156 89 32
131.33.2.201 131 33 2 201
131.33.2.202 131 33 2 202
131.107.2.201 131 107 2 201*/