2011-08-17 21 views
7

私は私たちのデータベースにインポートしているCSVがあります。 "列"にはのINTであるデータが含まれていますが、一部の行にはBIGINT範囲内の数値しか含まれていないものがあります(パートナーのテストデータなので)。私たちは内部的にINTを保存し、変更する気はありません。SQL - 安全にダウンキャストBIGINT INTに

私はBIGINTからINTにダウンキャストすることを安全にしたいと思います。安全には、算術オーバーフローが発生した場合にエラーを発生させる必要はありません。キャスト/変換が成功したら、私はスクリプトを実行します。それが失敗すると、私はそれが短絡したい。私は正しい構文を理解できないようです。 、私は(2^31-1(2,147,483,647)に-2^31(-2147483648))INTの有効範囲に@UserIDBigIntを比較することについて考えてきました

DECLARE @UserIDBigInt BIGINT = 9723021913; -- actually provided by query param 
--Setting within the INT range successfully converts 
--SET @UserIDBigInt = 5; 
DECLARE @UserID INT = CONVERT(INT, @UserIDBigInt); 
--DECLARE @UserID INT = CAST(@UserIDBigInt AS INT); 
SELECT @UserIDBigInt 
SELECT @UserID 
IF @UserID IS NOT NULL BEGIN 
    SELECT 'Handle it as reliable data' 
END 

:これは私が持っているものです私はそのアプローチが本当に好きではありません。それは私の後退です。私はいくつかの言語構造や組み込み関数が使えることを期待していました。私が絶対に有効範囲と比較する必要がある場合は、C#のint.MinValue & int.MaxValueのような組み込み定数がいくつかありますか?

EDIT:誤植が修正されました。

+0

組み込みの定数はありません。最終的に定数と比較したい場合は、前にその質問に答えています:http://stackoverflow.com/questions/7092774/max-value-represented-by-bigint/7092844#7092844 –

+0

ストアドプロシージャのINT変数は、その値をBIGINT変数に戻してから、BIGINTを元の値(BIGINT)と比較します。オーバーフローがINTに割り当てられると、値は一致しません。 –

+0

@Conspicuousコンパイラ、私はストアドプロシージャを使用しているとは言いませんでした。それにかかわらず、そうすることで、式をデータ型intに変換する算術オーバーフローエラーが発生します。私の元の質問で言及されたように。 –

答えて

6

のための安全な簡単な方法は、あなたのスクリプトにこれらを追加していない:

SET ARITHABORT OFF; 
SET ARITHIGNORE ON; 

これはNULLにオーバーフロー値を変換します。ここ

さらに詳しい情報:http://msdn.microsoft.com/en-us/library/ms184341.aspx

0

また、値を文字列に変換し、長さをトリムしてintに変換することもできます。最良の方法は、しかし確か

1

私は、これが最良の答えであるかわからないが、それは私が自分でそれ以前を思い付いたものです。例外/エラーをキャッチし、正常に実行を続けることが可能です。

例:

DECLARE @UserIDBigInt BIGINT = 9723021913; 
DECLARE @UserID INT; 
BEGIN TRY 
    SET @UserID = @UserIDBigInt; 
END TRY BEGIN CATCH 
END CATCH 

IF @UserID IS NULL BEGIN 
    SELECT 'Handle it as unreliable data' 
    RETURN 
END 

SELECT 'Handle it as reliable data' 
3

@UserIDに下半分を保存し、上半分を確認した後、あなたのbigintvarbinaryにキャスト:

  • 上半分がすべて0の下半分である場合負でない値を表します。@UserIDには、正しいintの値が含まれています。

  • 上半分がすべて1で、@UserIDが負の場合、それも問題ありません。

  • これ以外の場合、算術オーバーフローが発生します。

ここでの実装です:

DECLARE @UserIDBigInt BIGINT = 9723021913; 
DECLARE @UserID INT, @HighInt INT; 

WITH v AS (SELECT CAST(@UserIDBigInt AS varbinary) AS bin) 
SELECT 
    @HighInt = SUBSTRING(bin, 1, 4), 
    @UserID = SUBSTRING(bin, 5, 4) 
FROM v; 

IF (@HighInt = 0 AND @UserID >= 0 OR @HighInt = -1 AND @UserID < 0) BEGIN 
    SELECT 'Handle it as reliable data' 
END 
関連する問題