0

我发现以下代码用零填充 IP 地址,以使其在字典上具有可比性。该代码可以正常工作,但我需要它作为 SQL 中的标量函数。你可以在代码中转换它来创建一个同样的标量函数吗?我们目前使用 SQL Server 2008 R2。

DECLARE @a as NVARCHAR(15)
SET @a = '2.18.4.14'

SELECT 
    @a = CASE 
        WHEN CHARINDEX('.',@a) < 4 
            THEN STUFF(@a,1,0,REPLICATE('0',4-CHARINDEX('.',@a,1))) 
        ELSE @a 
    END
, 
    @a = CASE 
        WHEN CHARINDEX('.',@a) < 8 
            THEN STUFF(@a,5,0,REPLICATE('0',8-CHARINDEX('.',@a, 5))) 
        ELSE @a 
    END
, 
    @a = CASE 
        WHEN CHARINDEX('.',@a) < 12 
            THEN STUFF(@a,9,0,REPLICATE('0',12-CHARINDEX('.',@a, 9))) 
        ELSE @a 
    END
, 
    @a = CASE 
        WHEN LEN(@a) < 15 
            THEN STUFF(@a,13,0,REPLICATE('0',15-LEN(@a))) 
        ELSE @a 
    END

SELECT @a

你能解释一下这段代码是如何工作的吗?我了解 CHARINDEX、STUFF 和 REPLICATE 的作用,但我不了解 CASE 步骤如何修改 IP 地址 @a 的步骤。ist 是标量值还是表?

4

1 回答 1

1

就个人而言,我会使用表值函数,而不是标量函数。表值函数远不执行标量函数,如果您要针对数据集执行操作,那么您会注意到速度大幅提升。

首先,这利用了 Jeff Moden 的DelmitedSplit8k。但是,如果您使用的是 SQL Server 2016,那么您可以使用STRING_SPLIT(我不知道您使用的是什么版本)。那么函数就很简单了:

CREATE FUNCTION Lexicon_IP_fn (@IPAddress VARCHAR(15))
RETURNS TABLE AS
RETURN 
(
    SELECT CONVERT(varchar(15),STUFF((SELECT '.' + RIGHT('000' + DS.Item,3)
                                      FROM DelimitedSplit8K(@IPAddress, '.') DS
                                      FOR XML PATH('')),1,1,'')) AS Lexicon_IP
);

您可以使用 调用该函数CROSS APPLY。例如:

WITH VTE AS (
    SELECT *
    FROM (VALUES ('1.1.1.1'),('123.123.1.42'),('127.0.0.1')) V([IP]))
SELECT [IP], LIP.Lexicon_IP
FROM VTE
     CROSS APPLY Lexicon_IP_fn([IP]) LIP;

返回:

IP           Lexicon_IP
------------ ---------------
1.1.1.1      001.001.001.001
123.123.1.42 123.123.001.042
127.0.0.1    127.000.000.001
于 2018-01-22T10:31:59.257 回答