SQL - 安全地将BIGINT转发为INT

Ols*_*dev 10 sql t-sql sql-server

我有一个CSV我正在导入我们的数据库.其中一个"列"包含应该是INT的数据,但有些行的数字只能在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
Run Code Online (Sandbox Code Playgroud)

我想过将@UserIDBigInt与INT的有效范围(-2 ^ 31(-2,147,483,648)到2 ^ 31-1(2,147,483,647))进行比较,但我真的不喜欢这种方法.那是我的后备.我希望能使用一些语言结构或内置函数.如果我必须与有效范围进行比较,是否至少有一些内置常量(如C#的int.MinValue和int.MaxValue)?

编辑:纠正错字.

Cha*_*ins 6

将这些添加到您的脚本:

SET ARITHABORT OFF;
SET ARITHIGNORE ON;
Run Code Online (Sandbox Code Playgroud)

这会将任何溢出值转换为NULL.

更多信息:http://msdn.microsoft.com/en-us/library/ms184341.aspx


And*_*y M 5

将您的投射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
Run Code Online (Sandbox Code Playgroud)