使用检查约束验证URL

时间:2014-05-02 15:52:57

标签: sql-server tsql

我想创建一个验证网址的CHECK CONSTRAINT

这是我的第一种方法,但它也需要标签。

CHECK ([ServiceURL] LIKE 'https://[a-z0-9]%.[a-z0-9]%')

另一个想法是这个

CHECK ([ServiceURL] LIKE 'https://[a-z0-9].[a-z0-9]')

但这不起作用。任何想法?

3 个答案:

答案 0 :(得分:3)

进一步采用Gary的例子,下面的版本显示了我们如何在不使用游标的情况下编写函数以及如何将check约束添加到表中。你可能想要扩展它来处理http和https,以及可能的其他修改(比如允许/字符)

CREATE FUNCTION dbo.IsValidURL (@Url VARCHAR(200))
RETURNS INT
AS
BEGIN
    IF CHARINDEX('https://', @url) <> 1
    BEGIN
        RETURN 0;   -- Not a valid URL
    END

    -- Get rid of the http:// stuff
    SET @Url = REPLACE(@URL, 'https://', '');

    -- Now we need to check that we only have digits or numbers
    IF (@Url LIKE '%[^a-zA-Z0-9]%')
    BEGIN
        RETURN 0;
    END

    -- It is a valid URL
    RETURN 1;
END

-- Create the table
CREATE TABLE dbo.MyTableOnlyLettersAndDigits 
(
    id int identity(1,1) primary key clustered,
    ServiceURL varchar(200) not null
);

GO

-- Add the check constraint
ALTER TABLE dbo.MyTableOnlyLettersAndDigits 
    ADD CONSTRAINT chkValidURLs CHECK (dbo.IsValidURL(ServiceURL) = 1);


-- Some tests to show it works
insert into dbo.MyTableOnlyLettersAndDigits(ServiceURL)
values ('Missing prefix.Invalid');

insert into dbo.MyTableOnlyLettersAndDigits(ServiceURL)
values ('https://IamAValidURL123');

insert into dbo.MyTableOnlyLettersAndDigits(ServiceURL)
values ('https://Invalid#Char');

答案 1 :(得分:1)

like子句的模式匹配非常有限,如您所发现的那样。无法使用类似子句重现您想要的行为。

您可以将自己的模式匹配功能作为CLR过程进行滚动。您也可以在TSQL中执行此等效逻辑,因为逻辑不像UDF那么复杂。然后在检查约束(或触发器等)中使用UDF

这是article for UDF for URL validation,其功能如下。我没有亲自测试过。

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[IsValidUrl]
(
    @Url varchar(100)
)

RETURNS int

AS

BEGIN

    -- CREATE THE VARIABLES
    DECLARE @TldExtension VARCHAR(10)

    -- CLEAN THE URL
    SET @Url = (SELECT REPLACE(@Url,'http://',''))
    IF (CHARINDEX('/', @Url) !=0)
        SET @Url = SUBSTRING(@Url, 0, CHARINDEX('/', @Url))

    -- DECLARE THE CURSOR
    DECLARE Tld_Cursor CURSOR FOR
        SELECT [Tld] FROM [kogd].[dbo].[TLD]
        ORDER BY [Length] DESC

    -- OPEN THE CURSOR
    OPEN Tld_Cursor
    -- SET THE VARIABLE TO THE NEXT TLD
    FETCH NEXT FROM Tld_Cursor INTO @TldExtension

    -- LOOP
    WHILE @@FETCH_STATUS = 0
        BEGIN
            -- IF FOUND RETURN 1
            IF (CHARINDEX(@TldExtension, @Url) != 0) RETURN 1
            -- ELSE GET NEXT
            FETCH NEXT FROM Tld_Cursor INTO @TldExtension
        END

    -- IF NOT FOUND RETURN 0
    RETURN 0

END

GO

原始文章已失效,a similar article 可能有用

答案 2 :(得分:0)

这是对不需要外部函数的函数的更新。另外,如果你想调试它,它也可以转换成一个程序。

DROP FUNCTION IF EXISTS IsValidURL
GO

CREATE FUNCTION [dbo].[IsValidUrl]
(
    @Url varchar(100)
)
RETURNS BIT
AS
BEGIN
    --PRINT('Original URL: '+@Url)
    -- CLEAN THE URL
    SET @Url = (SELECT REPLACE(@Url,'http://',''))
    SET @Url = (SELECT REPLACE(@Url,'https://',''))
    IF (CHARINDEX('/', @Url) !=0)
        SET @Url = SUBSTRING(@Url, 0, CHARINDEX('/', @Url))

    --PRINT('Cleaned URL: '+@Url)

    IF (@Url LIKE '%[^a-zA-Z0-9.]%') -- check that the URL contains letters or the dot
    BEGIN
        RETURN 0;
        --PRINT('0 -> Contains bad characters');
    END

    IF (CHARINDEX('.', @Url) = 0)
    BEGIN
        RETURN 0;
        --PRINT('0 -> Doesn''t contain the dot character');
    END

    DECLARE @predot varchar(100) 
    DECLARE @postdot varchar(100)
    WHILE ( CHARINDEX('.', @Url) != 0)
    BEGIN
        SET @predot = SUBSTRING(@Url, 0, CHARINDEX('.', @Url))
        SET @postdot = SUBSTRING(@Url, CHARINDEX('.', @Url)+1, LEN(@Url))

        --PRINT 'Pre dot:  '+@predot
        --PRINT 'Post dot: '+@postdot

        IF (LEN(@predot) < 1)
        BEGIN
            RETURN 0;
            --PRINT('0 -> Pre dot can''t be empty');
        END
        IF (LEN(@postdot) < 1)
        BEGIN
            RETURN 0;
            --PRINT('0 -> Post dot can''t be empty');
        END

        SET @Url = @postdot
    END  

    RETURN 1
    --PRINT('1 -> Final return');
    
END
GO