1

私はC#とSQLServer2008データベースを含むプロジェクトに取り組んでいます。nvarchar(15)テーブルの1つに、IPアドレスを含むフィールド( )があります。

入力値が実際にIPアドレスであることを検証するチェック制約を追加したいと思います。

これを行うために正規表現を使用したかったのですが、この機能はデフォルトではサポートされていないようです。UDFを内部に使用してcustommdllを作成する方法(MSDNチュートリアル)を見ましたが、それがどのように機能するか(つまり、dllをどこに配置すればよいですか?)

そのような制約を追加する「簡単な」方法はありますか?どんな解決策も歓迎します。

前もって感謝します !

4

6 に答える 6

2

これを行うにはいくつかの方法があります。最もパフォーマンスの高い方法は、おそらくデータベース内のCLR関数です。

これは、SQLのテキスト操作ツールがかなり貧弱で、SQLServerにネイティブの正規表現がないためです。

他の人が言っているように、これはDBに挿入する前にアプリケーションによってより適切に処理されます。

于 2010-07-29T13:16:33.850 に答える
1

データベースで処理するのではなく、アプリケーションで何よりもまず処理する必要があります。

その後、データベースにチェックを追加しても害はありませんが、入力をフィルタリングするためにDBに任せるのは非常に大雑把です。

于 2010-07-29T13:12:25.230 に答える
1

私が考えることができる最も簡単な方法は、のような関数を作成し、fnCheckIPこの関数を制約で使用することです。

UDFを使用する必要はありません。

create function fnCheckIP(@ip varchar(15)) returns bit
AS
begin
    if (@ip is null)
        return null

    declare @num1 int
    declare @num varchar(15)    
    declare @pos int
    while (@ip is not null)
    begin
        set @pos = IsNull(NullIf(charindex('.', @ip), 0), Len(@ip) + 1)
        set @num = substring(@ip, 1, @pos - 1)

        if (isnumeric(@num) = 0) or (not cast(@num as int) between 0 and 255)
            return cast(0 as bit)

        if (len(@ip) - @pos <= 0)
            set @ip = null
        else        
            set @ip = NullIf(substring(@ip, @pos + 1, len(@ip) - @pos), '')
    end

    return cast (1 as bit)
end
go

select dbo.fnCheckIP('127.0.0.1')
select dbo.fnCheckIP('127.0.0.300')
于 2010-07-29T13:33:40.290 に答える
1

この解決策はPauloの解決策に似ていますが、isnumericではカンマが許可され、intエラーへのキャストがスローされるため、どちらのアプローチを使用する場合でもコンマ文字を削除する必要があります。

CREATE FUNCTION fn_ValidateIP
(
    @ip varchar(255)
)
RETURNS int
AS
BEGIN
    DECLARE @Result int = 0
        IF
            @ip not like '%,%' and
            len(@ip) <= 15 and
            isnumeric(PARSENAME(@ip,4)) = 1 and
            isnumeric(PARSENAME(@ip,3)) = 1 and
            isnumeric(PARSENAME(@ip,2)) = 1 and
            isnumeric(PARSENAME(@ip,1)) = 1 and
            cast(PARSENAME(@ip,4) as int) between 1 and 255 and
            cast(PARSENAME(@ip,3) as int) between 0 and 255 and
            cast(PARSENAME(@ip,2) as int) between 0 and 255 and
            cast(PARSENAME(@ip,1) as int) between 0 and 255
            set @Result = 1
        ELSE
            set @Result = 0
    RETURN @Result
END

select dbo.fn_ValidateIP('127.0.0.1')
于 2015-06-05T18:11:45.677 に答える
0

これは完全に実用的ではないかもしれませんが、1つの方法は、変換された文字列###-###-###-###をbinary(4)データ型に格納することです。インターフェイスをハイフンで混乱させ、4つの数値を2進数に変換して戻す処理を行います(これはおそらく計算された列によっても実行できます)。少し極端ですが、binary(4)を使用するといつでも実行できます。それをIPアドレスに変換します。

于 2010-07-29T13:44:27.600 に答える
0

Oracleからついに約10年後、sqlserverはネイティブコンパイルを取得しました(制限付き)

    ALTER function fn_ValidateIPv4
(
@ip varchar(255)
)
RETURNS int
--WITH EXECUTE AS OWNER, SCHEMABINDING, NATIVE_COMPILATION  
AS
BEGIN 
--ATOMIC WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english')
/* only sql2016 native Compilation **/
DECLARE @len_ip as int;
SET @len_ip =  len(@ip);
DECLARE @firstBlock varchar(4) = '';
DECLARE @secondBlock varchar(4) = '';
DECLARE @thirdBlock varchar(4) = '';
DECLARE @fourthBlock varchar(4) = '';
DECLARE @countDot as smallint = 0;
DECLARE @l_i as smallint = 0;

DECLARE @l_curChar varchar(1) = 'X';

DECLARE @Result int = 0
    IF (@len_ip <= 15)
    BEGIN
        WHILE (@l_i < @len_ip) 
        BEGIN
            set @l_i += 1;
            set @l_curChar = substring(@ip,@l_i,1);
            if @l_curChar = '.'
                SET @countDot += 1
            ELSE
            BEGIN
                IF @l_curChar IN ( '0','1','2','3','4','5','6','7','8','9' )
                BEGIN
                    IF @countDot = 0 
                        SET @firstBlock = @firstBlock + @l_curChar;
                    IF @countDot = 1
                        SET @secondBlock = @secondBlock + @l_curChar;
                    IF @countDot = 2
                        SET @thirdBlock = @thirdBlock + @l_curChar;
                    IF @countDot = 3
                        SET @fourthBlock = @fourthBlock + @l_curChar;
                    IF  @countDot > 3
                        set @firstBlock = 'AAA'; -- force error 
                END
                ELSE set @firstBlock = 'AAA'; -- force error                

            END;
        END;            

        IF ( @countDot = 3 and
            cast(@fourthBlock as int) between 1 and 255 and
            cast(@thirdBlock as int) between 0 and 255 and
            cast(@secondBlock as int) between 0 and 255 and
            cast(@firstBlock as int) between 0 and 255 
            )           
            set @Result = 1;
    END;

    /*
    select dbo.fn_ValidateIPv4( '127.0.0.258' );        
    */
RETURN @Result
END;

サポートされていないビルド関数isnumericなどを削除する必要がありました...

于 2018-12-14T10:36:33.087 に答える