SQL Server 合并IP
所给字符串是:用逗号连接起来的无规律的IP(不一定是一个网段),例如:
114.113.112.1,114.113.112.3,114.113.112.10,114.113.112.11,114.113.112.12,114.113.112.13,114.113.112.180
要通过一个函数返回这样的字符串:
114.113.112.1,114.113.112.3,114.113.112.10-13,114.113.112.180
即,连续的IP用“-”把首和尾连接,其它的IP仍以逗号连接,所有IP的趋势是从小大大排列。
代码
--函数一:
--SQL Server Split函数
--Author:zc_0101
--说明:
--支持分割符多字节
--使用方法
--Select * FROM DBO.F_SQLSERVER_SPLIT('1203401230105045','0')
--select * from DBO.F_SQLSERVER_SPLIT('abc1234a12348991234','1234')
CREATE FUNCTION F_SQLSERVER_SPLIT(@Long_str varchar(8000),@split_str varchar(100))
RETURNS @tmp TABLE(
ID inT IDENTITY PRIMARY KEY,
short_str varchar(8000)
)
AS
BEGIN
DECLARE @long_str_Tmp varchar(8000),@short_str varchar(8000),@split_str_length int
SET @split_str_length = LEN(@split_str)
IF CHARINDEX(@split_str,@Long_str)=1
SET @long_str_Tmp=SUBSTRING(@Long_str,@split_str_length+1,LEN(@Long_str)-@split_str_length)
ELSE
SET @long_str_Tmp=@Long_str
IF CHARINDEX(REVERSE(@split_str),REVERSE(@long_str_Tmp))>1
SET @long_str_Tmp=@long_str_Tmp+@split_str
ELSE
SET @long_str_Tmp=@long_str_Tmp
IF CHARINDEX(@split_str,@long_str_Tmp)=0
Insert INTO @tmp select @long_str_Tmp
ELSE
BEGIN
WHILE CHARINDEX(@split_str,@long_str_Tmp)>0
BEGIN
SET @short_str=SUBSTRING(@long_str_Tmp,1,CHARINDEX(@split_str,@long_str_Tmp)-1)
DECLARE @long_str_Tmp_LEN INT,@split_str_Position_END int
SET @long_str_Tmp_LEN = LEN(@long_str_Tmp)
SET @split_str_Position_END = LEN(@short_str)+@split_str_length
SET @long_str_Tmp=REVERSE(SUBSTRING(REVERSE(@long_str_Tmp),1,@long_str_Tmp_LEN-@split_str_Position_END))
IF @short_str<>'' Insert INTO @tmp select @short_str
END
END
RETURN
END
--函数二
IF OBJECT_ID(N'F_IP_Merge','FN') IS NOT NULL DROP FUNCTION F_IP_Merge
GO
CREATE FUNCTION [dbo].[F_IP_Merge](@IP_str VARCHAR(MAX))
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @TEMP TABLE(ID INT IDENTITY PRIMARY KEY,IP VARCHAR(50),NUM BIGINT)
INSERT INTO @TEMP
SELECT SHORT_STR,(CAST(PARSENAME(SHORT_STR,4)+PARSENAME(SHORT_STR,3)+PARSENAME(SHORT_STR,2)+RIGHT(REPLICATE('0',2)+PARSENAME(SHORT_STR,1),3) AS BIGINT)) cnt
FROM DBO.F_SQLSERVER_SPLIT(@IP_str,',')
ORDER BY CAST(PARSENAME(SHORT_STR,4) AS INT),CAST(PARSENAME(SHORT_STR,3) AS INT),CAST(PARSENAME(SHORT_STR,2) AS INT),CAST(PARSENAME(SHORT_STR,1) AS INT)
DECLARE @S VARCHAR(MAX)
SELECT @S=ISNULL(@S,'')+IP+MERGE_STR FROM (
SELECT *,
CASE (SELECT NUM FROM @TEMP B WHERE B.ID=A.ID+1)-NUM
WHEN 1 THEN '-' ELSE ',' END AS MERGE_STR
FROM @TEMP A) T
DECLARE @TEMP2 TABLE(ID INT PRIMARY KEY,SHORT_STR VARCHAR(MAX))
INSERT INTO @TEMP2 SELECT * from DBO.F_SQLSERVER_SPLIT(@S,',')
DECLARE @MIN_ID INT,@MAX_ID INT,@TEM_STR VARCHAR(MAX)
SELECT @MIN_ID=MIN(ID),@MAX_ID=MAX(ID) FROM @TEMP2
WHILE @MIN_ID<=@MAX_ID
BEGIN
SELECT @TEM_STR=SHORT_STR FROM @TEMP2 WHERE ID=@MIN_ID
IF CHARINDEX('-',@TEM_STR)>0
UPDATE @TEMP2 SET SHORT_STR=(
SELECT
LTRIM(MAX(CAST(PARSENAME(SHORT_STR,4) AS INT)))+'.'+
LTRIM(MAX(CAST(PARSENAME(SHORT_STR,3) AS INT)))+'.'+
LTRIM(MAX(CAST(PARSENAME(SHORT_STR,2) AS INT)))+'.'+
LTRIM(MIN(CAST(REPLICATE('0',2)+PARSENAME(SHORT_STR,1)AS INT)))+'~'+
LTRIM(MAX(CAST(REPLICATE('0',2)+PARSENAME(SHORT_STR,1)AS INT)))
FROM DBO.F_SQLSERVER_SPLIT(@TEM_STR,'-')
) WHERE ID=@MIN_ID
SET @MIN_ID=@MIN_ID+1
END
DECLARE @RESULT VARCHAR(MAX)
SELECT @RESULT=ISNULL(@RESULT+'<span style="color:red;">,</span><br />','')+SHORT_STR FROM @TEMP2
RETURN @RESULT
END
--执行
SELECT DBO.F_IP_Merge('114.113.112.1,.113.112.3,.113.112.10,.113.112.11,.113.112.12,.113.112.13,.113.112.180')
/*
114.113.112.1,114.113.112.3,114.113.112.10-114.113.112.13,114.113.112.180
*/
SELECT DBO.F_IP_Merge('1.1.254.253,1.1.255.254,1.1.255.255,1.2.0.0,1.2.0.1,1.2.0.6,114.113.112.1,114.113.112.3,114.113.112.10,114.113.112.11,114.113.112.12,114.113.112.13,114.113.112.180')
/*
1.1.254.253,1.1.255.254-1.1.255.255,1.2.0.0-1.2.0.1,1.2.0.6,114.113.112.1,114.113.112.3,114.113.112.10-114.113.112.13,114.113.112.180
*/
--SQL Server Split函数
--Author:zc_0101
--说明:
--支持分割符多字节
--使用方法
--Select * FROM DBO.F_SQLSERVER_SPLIT('1203401230105045','0')
--select * from DBO.F_SQLSERVER_SPLIT('abc1234a12348991234','1234')
CREATE FUNCTION F_SQLSERVER_SPLIT(@Long_str varchar(8000),@split_str varchar(100))
RETURNS @tmp TABLE(
ID inT IDENTITY PRIMARY KEY,
short_str varchar(8000)
)
AS
BEGIN
DECLARE @long_str_Tmp varchar(8000),@short_str varchar(8000),@split_str_length int
SET @split_str_length = LEN(@split_str)
IF CHARINDEX(@split_str,@Long_str)=1
SET @long_str_Tmp=SUBSTRING(@Long_str,@split_str_length+1,LEN(@Long_str)-@split_str_length)
ELSE
SET @long_str_Tmp=@Long_str
IF CHARINDEX(REVERSE(@split_str),REVERSE(@long_str_Tmp))>1
SET @long_str_Tmp=@long_str_Tmp+@split_str
ELSE
SET @long_str_Tmp=@long_str_Tmp
IF CHARINDEX(@split_str,@long_str_Tmp)=0
Insert INTO @tmp select @long_str_Tmp
ELSE
BEGIN
WHILE CHARINDEX(@split_str,@long_str_Tmp)>0
BEGIN
SET @short_str=SUBSTRING(@long_str_Tmp,1,CHARINDEX(@split_str,@long_str_Tmp)-1)
DECLARE @long_str_Tmp_LEN INT,@split_str_Position_END int
SET @long_str_Tmp_LEN = LEN(@long_str_Tmp)
SET @split_str_Position_END = LEN(@short_str)+@split_str_length
SET @long_str_Tmp=REVERSE(SUBSTRING(REVERSE(@long_str_Tmp),1,@long_str_Tmp_LEN-@split_str_Position_END))
IF @short_str<>'' Insert INTO @tmp select @short_str
END
END
RETURN
END
--函数二
IF OBJECT_ID(N'F_IP_Merge','FN') IS NOT NULL DROP FUNCTION F_IP_Merge
GO
CREATE FUNCTION [dbo].[F_IP_Merge](@IP_str VARCHAR(MAX))
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @TEMP TABLE(ID INT IDENTITY PRIMARY KEY,IP VARCHAR(50),NUM BIGINT)
INSERT INTO @TEMP
SELECT SHORT_STR,(CAST(PARSENAME(SHORT_STR,4)+PARSENAME(SHORT_STR,3)+PARSENAME(SHORT_STR,2)+RIGHT(REPLICATE('0',2)+PARSENAME(SHORT_STR,1),3) AS BIGINT)) cnt
FROM DBO.F_SQLSERVER_SPLIT(@IP_str,',')
ORDER BY CAST(PARSENAME(SHORT_STR,4) AS INT),CAST(PARSENAME(SHORT_STR,3) AS INT),CAST(PARSENAME(SHORT_STR,2) AS INT),CAST(PARSENAME(SHORT_STR,1) AS INT)
DECLARE @S VARCHAR(MAX)
SELECT @S=ISNULL(@S,'')+IP+MERGE_STR FROM (
SELECT *,
CASE (SELECT NUM FROM @TEMP B WHERE B.ID=A.ID+1)-NUM
WHEN 1 THEN '-' ELSE ',' END AS MERGE_STR
FROM @TEMP A) T
DECLARE @TEMP2 TABLE(ID INT PRIMARY KEY,SHORT_STR VARCHAR(MAX))
INSERT INTO @TEMP2 SELECT * from DBO.F_SQLSERVER_SPLIT(@S,',')
DECLARE @MIN_ID INT,@MAX_ID INT,@TEM_STR VARCHAR(MAX)
SELECT @MIN_ID=MIN(ID),@MAX_ID=MAX(ID) FROM @TEMP2
WHILE @MIN_ID<=@MAX_ID
BEGIN
SELECT @TEM_STR=SHORT_STR FROM @TEMP2 WHERE ID=@MIN_ID
IF CHARINDEX('-',@TEM_STR)>0
UPDATE @TEMP2 SET SHORT_STR=(
SELECT
LTRIM(MAX(CAST(PARSENAME(SHORT_STR,4) AS INT)))+'.'+
LTRIM(MAX(CAST(PARSENAME(SHORT_STR,3) AS INT)))+'.'+
LTRIM(MAX(CAST(PARSENAME(SHORT_STR,2) AS INT)))+'.'+
LTRIM(MIN(CAST(REPLICATE('0',2)+PARSENAME(SHORT_STR,1)AS INT)))+'~'+
LTRIM(MAX(CAST(REPLICATE('0',2)+PARSENAME(SHORT_STR,1)AS INT)))
FROM DBO.F_SQLSERVER_SPLIT(@TEM_STR,'-')
) WHERE ID=@MIN_ID
SET @MIN_ID=@MIN_ID+1
END
DECLARE @RESULT VARCHAR(MAX)
SELECT @RESULT=ISNULL(@RESULT+'<span style="color:red;">,</span><br />','')+SHORT_STR FROM @TEMP2
RETURN @RESULT
END
--执行
SELECT DBO.F_IP_Merge('114.113.112.1,.113.112.3,.113.112.10,.113.112.11,.113.112.12,.113.112.13,.113.112.180')
/*
114.113.112.1,114.113.112.3,114.113.112.10-114.113.112.13,114.113.112.180
*/
SELECT DBO.F_IP_Merge('1.1.254.253,1.1.255.254,1.1.255.255,1.2.0.0,1.2.0.1,1.2.0.6,114.113.112.1,114.113.112.3,114.113.112.10,114.113.112.11,114.113.112.12,114.113.112.13,114.113.112.180')
/*
1.1.254.253,1.1.255.254-1.1.255.255,1.2.0.0-1.2.0.1,1.2.0.6,114.113.112.1,114.113.112.3,114.113.112.10-114.113.112.13,114.113.112.180
*/