5

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

来自 URL SQL 的子字符串域名

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

我正在寻找扩展的是上面链接中的解决方案对仅返回地图的 url 没有帮助,例如“www.maps.google.com”。

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

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

更新:更具体地说,我还需要解析二级域等“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
4

5 回答 5

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')
于 2012-12-05T23:16:17.873 回答
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
于 2013-12-27T21:29:59.777 回答
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 之类的网站不适用于我的解决方案。我建议这只是一个起点,您必须为异常值编写代码。

于 2012-12-05T23:15:05.843 回答
3

我在这里所做的是在协议“://”之后对 url 进行子串化。

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

如果您需要它进行查询,您也可以在一行中完成它,或者像我一样将它用作标量函数。

此外,最好添加一些代码来检查空值或一般情况下的错误字符串。如果要将其保留为单行代码,请尝试使用 ISNULL 和 NULLIF 函数。

DECLARE @urlSansProtocol VARCHAR(MAX)
SET @urlSansProtocol = Substring(@url, CharIndex('://', @url)+3 ,LEN(@url))
RETURN Substring(@urlSansProtocol, 0   ,CharIndex('/',  @urlSansProtocol ))
于 2015-03-05T19:43:41.240 回答
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 ) 
于 2012-12-06T23:02:23.447 回答