/*------------------
*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*/