从T-SQL中的给定URL解析域

时间:2012-12-05 22:52:55

标签: sql sql-server tsql parsing url

我给出了这个答案,但想扩展这个问题,在堆栈上或通过搜索谷歌找不到任何解决方案。

Substring domainname from URL SQL

基本上,上面的链接通过一个简单的URL解决了我的问题,例如使用google解析“www.google.com”。

我正在寻求扩展的内容是上述链接中的解决方案无法帮助像仅仅返回地图的“www.maps.google.com”网址。

我想要的是让它从网址“www.maps.google.com”返回“google”或从“www.test.example.com”返回“示例”。

如果有人对此有解决方案,我将非常感激。

更新:更具体地说,我还需要在二级域名等解析“www.maps.google.com.au”以返回'google'

这是我的Sql函数。

CREATE FUNCTION [dbo].[parseURL]  (@strURL varchar(1000))
RETURNS varchar(1000)
AS
BEGIN

IF CHARINDEX('.', REPLACE(@strURL, 'www.','')) > 0
SELECT @strURL = LEFT(REPLACE(@strURL, 'www.',''), CHARINDEX('.',REPLACE(@strURL,              'www.',''))-1)
Else
SELECT @strURL = REPLACE(@strURL, 'www.','')

RETURN @strURL
END

5 个答案:

答案 0 :(得分:7)

我建议这个

DECLARE @URL nvarchar(max) = 'www.maps.google.com'

DECLARE @X xml = CONVERT(xml,'<root><part>' + REPLACE(@URL, '.','</part><part>') + '</part></root>')

SELECT [Domain] = T.c.value('.','varchar(20)')
FROM @X.nodes('/root/part[position() = last() - 1]') T(c)

方法是将URL转换为XML,然后使用XPath查找域。

<强>更新

关于二级域名,我认为唯一可靠的方法是将它们全部放在一个表格中(顶级域名也可能在表格中),然后您可以使用此查询:

DECLARE @URL nvarchar(max) = 'www.maps.google.com'

DECLARE @X xml = CONVERT(xml,'<root><part>' + REPLACE(REVERSE(@URL), '.','</part><part>') + '</part></root>')

;WITH SplitCTE AS
(
    SELECT
        (SELECT REVERSE(T.c.value('.', 'nvarchar(256)')) FROM @X.nodes('/root/part[. = ../part[position() = 1]]') T(c)) AS TLD,
        (SELECT REVERSE(T.c.value('.', 'nvarchar(256)')) FROM @X.nodes('/root/part[. = ../part[position() = 2]]') T(c)) AS D2,
        (SELECT REVERSE(T.c.value('.', 'nvarchar(256)')) FROM @X.nodes('/root/part[. = ../part[position() = 3]]') T(c)) AS D3
)
SELECT 
    CASE
        WHEN SLD.Domain IS NULL THEN S.D2 ELSE S.D3
    END AS Domain
FROM
    SplitCTE AS S
    LEFT JOIN TLD ON TLD.Domain = S.TLD
    LEFT JOIN SLD ON SLD.Domain = S.D2

我在本例中使用的TLD / SLD表如下。完整的域名列表在此wiki中。小心使用NVARCHAR,因为有些已本地化。

CREATE TABLE dbo.TLD
(
    Domain nvarchar(10)
)
GO

CREATE TABLE dbo.SLD
(
    Domain nvarchar(10)
)
GO

INSERT TLD VALUES ( 'com')
INSERT TLD VALUES ( 'uk')
INSERT SLD VALUES ( 'co')

答案 1 :(得分:4)

TLD问题确实会降低您的代码速度,并添加维护要求,因此我决定包含子域名。这是我使用的:

ALTER FUNCTION dbo.spExtractDomainFromURL ( @strURL NVARCHAR(1000) )
RETURNS NVARCHAR(100)
AS
BEGIN
    --Strip Protocol
    SELECT  @strURL = SUBSTRING(@strURL, CHARINDEX('://', @strURL) + 3, 999)

    -- Strip www subdomain
    IF LEFT(@strURL, 4) = 'www.'
        SELECT  @strURL = SUBSTRING(@strURL, 5, 999)

    -- Strip Path
    IF CHARINDEX('/', @strURL) > 0
        SELECT  @strURL = LEFT(@strURL, CHARINDEX('/', @strURL) - 1)

    RETURN @strURL
END

答案 2 :(得分:3)

有人可能会有更好的解决方案,但这就是我得到的:

LEFT(RIGHT(@strURL, CHARINDEX('.', REVERSE(@strURL)) +  CHARINDEX('.', SUBSTRING(REVERSE(@strURL), CHARINDEX('.', REVERSE(@strURL)) + 1, LEN(@strURL))) - 1), CHARINDEX('.', SUBSTRING(REVERSE(@strURL), CHARINDEX('.', REVERSE(@strURL)) + 1, LEN(@strURL))) - 1)

我不是最好的字符串操作,所以我相信可以缩短我真正长的代码行。基本上,我会使用REVERSE函数来获取最后一段时间,然后从那里开始。我的代码引入了最后一个和第二个到最后一个逗号之间的字符。

请注意,使用www.test.co.uk等网站无法使用我的解决方案。我建议它只是一个起点,你必须编写异常值。

答案 3 :(得分:2)

PARSENAME将最多分为四个由“。”分隔的项目。标记。 Parsename从右侧算起。如果要解析的object_name有四个以上的部分,则会重新执行NULL。

select PARSENAME ( REPLACE('www.maps.google.com.au', 'www.','')  , 3 ) 
select PARSENAME ( REPLACE('www.maps.google.com', 'www.','')  , 2 ) 

答案 4 :(得分:2)

我在这里做的是在协议'://'之后对URL进行子串。

然后我接受该字符串并将所有文本子串到第一个正斜杠。

如果您需要查询,也可以在一行中执行此操作,或者像我一样将其用作标量函数。

此外,添加一些代码以检查空值或一般只是坏字符串是个好主意。如果要将其保留为单行代码,请尝试使用ISNULL和NULLIF函数。

DECLARE @urlSansProtocol VARCHAR(MAX)
SET @urlSansProtocol = Substring(@url, CharIndex('://', @url)+3 ,LEN(@url))
RETURN Substring(@urlSansProtocol, 0   ,CharIndex('/',  @urlSansProtocol ))