2011-08-17 70 views
7

我有一個CSV導入到我們的數據庫。其中一個「列」包含應爲爲INT的數據,但某些行的數字只落在BIGINT範圍內(因爲它們是來自我們的某個合作伙伴的測試數據)。我們在內部存儲INT並且不想改變。SQL - 安全地將BIGINT降爲INT

我想安全地從BIGINT降到INT。安全地說,我的意思是如果發生算術溢出,則不應出現錯誤。如果演員表轉換成功,我希望我的腳本繼續。如果失敗,我想讓它短路。我似乎無法弄清楚正確的語法。這是我有:

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 

我想過@UserIDBigInt爲INT的有效範圍比較(-2^31(2,147,483,648)至2^31-1(2,147,483,647)),但我真的不喜歡這種方法。這是我的後備。我希望能使用一些語言結構或內置函數。如果我絕對必須與有效範圍進行比較,是否至少有一些內置常量(如C#的int.MinValue & int.MaxValue)?

編輯:更正了錯字。

+0

有沒有內置常量。如果你最終希望與常量進行比較,那麼以前已經回答了此問題:http://stackoverflow.com/questions/7092774/max-value-represented-by-bigint/7092844#7092844 –

+0

爲什麼不直接將值分配給存儲過程中的INT變量,將該值直接分配給BIGINT變量,然後將BIGINT與原始值(也是BIGINT)進行比較。如果分配給INT的溢出,這些值將不匹配。 –

+0

@Conspicuous編譯器,我從來沒有說過我正在使用存儲過程。無論如何,這樣做會引發「將算術表達式轉換爲數據類型int的算術溢出錯誤」。正如我原來的問題所暗示的那樣。 –

回答

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

投下你bigintvarbinary,則下半部存儲@UserID和檢查上半部分:

  • 如果上半部分是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