2

scodeある範囲のコード番号について列をチェックしようとしているクエリがあります。問題は、scode列にいくつかのnvarchar文字が含まれていることと、それらが見つかったときにエラーが発生することです。

エラーを返さずに次のクエリを実行するにはどうすればよいですか。

SELECT dtExpires, dtFirst
FROM Customers
WHERE (scode BETWEEN 10 AND 100) OR
      (scode BETWEEN 500 AND 600)

私が受け取っているエラー:

nvarchar値をデータ型intに変換するときに変換に失敗しました

4

3 に答える 3

7

本当にすべきことであるデータ型を修正できない場合...

短絡する唯一の確実な方法は、フィルタリングされた結果を #temp テーブルに詰め込むことです。そうしないと、評価の順序を制御できません。サブクエリまたは CTE を使用してISNUMERIC() = 1"最初" の行をフィルター処理しても、SQL Server はBETWEEN最初に条件を評価し、同じエラーで失敗する可能性があります。これは常に発生するとは限りませんが、確実に回避できる唯一の方法は次のとおりです。

SELECT dtExpires, dtFirst, scode
INTO #t
FROM dbo.Customers
WHERE scode NOT LIKE '%[^0-9]%'; -- this assumes no decimals allowed

SELECT dtExpires, dtFirst
FROM #t
WHERE (scode BETWEEN 10  AND 100) 
   OR (scode BETWEEN 500 AND 600);

DROP TABLE #t;
于 2013-02-27T15:45:12.670 に答える
3

ここでの最終的な問題は、これらの数値を として保存していることですnvarchar。これはいくつかの理由で問題があります。まず速度です。これがまさにこのWeb サイトにある多くのケースであることを示す優れたドキュメントと回答がたくさんあります。

整数値は文字列よりも小さいため、1 ページに収まるサイズよりもはるかに多くnvarchar、整数での数学はより簡単に実行できます。SQLFiddleに移動してテーブルに入力し、いくつかの値を指定して、クエリを実行してみてください。次に、その列を整数値に変更して同じクエリを実行すると、実行が速くなるだけでなく、現在のSELECTステートメントが適切に実行されます。この情報と整数に参加する必要がある場合は、私もはるかに速くなります。

天気が悪いのか、これを行う力があるのか​​ どうかは完全にはわかりませんが、問題は確実に解決され、データベースのパフォーマンスも向上します.

于 2013-02-27T15:45:42.600 に答える
1

たぶん次のようなものを使用します

SELECT        dtExpires, dtFirst
FROM            Customers
WHERE        ( cast(fnRemoveNonNumericCharacters(scode) as int) BETWEEN 10 AND 100) OR
                     (cast(fnRemoveNonNumericCharacters(scode) as int)BETWEEN 500 AND 600)

関数は次のとおりです。

CREATE Function [fnRemoveNonNumericCharacters](@strText VARCHAR(1000))
RETURNS VARCHAR(1000)
AS
BEGIN
    WHILE PATINDEX('%[^0-9]%', @strText) > 0
    BEGIN
        SET @strText = STUFF(@strText, PATINDEX('%[^0-9]%', @strText), 1, '')
    END
    RETURN @strText
END

または、scode が数値ではないエントリを除外する場合は、ブール値を返す関数も作成します。この関数は、数値以外の文字が含まれているかどうかを示し、それを where 句に入れます。

また、これを解決する方法は次のとおりです。

SELECT        dtExpires, dtFirst
FROM            Customers
WHERE        (( case when scode LIKE '%[^0-9]%' then 0 else scode end BETWEEN 10 AND 100) OR
                     (case when scode LIKE '%[^0-9]%' then 0 else scode end BETWEEN 500 AND 600))
and scode not like '%[^0-9]%'
于 2013-02-27T15:26:43.103 に答える