2011-08-17 20 views
7

Tengo un archivo CSV que estoy importando en nuestra base de datos. Una de las "columnas" contiene datos que debe ser como INT, pero algunas filas tienen números que solo se incluyen en el rango BIGINT (porque son datos de prueba de uno de nuestros socios). Almacenamos INT internamente y no deseamos cambiar.SQL - downcast con seguridad BIGINT a INT

Quiero descender con seguridad de BIGINT a INT. De forma segura, quiero decir que no se deben generar errores si ocurre un desbordamiento aritmético. Si el cast/conversion tiene éxito, quiero que mi script continúe. Si falla, quiero que se cortocircuite. Parece que no puedo entender la sintaxis adecuada. Esto es lo que tengo:

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 

He pensado en comparación @UserIDBigInt al rango válido de un INT (31^-2 (-2147483648) a 2^31-1 (2147483647)), pero realmente no me gusta ese enfoque. Esa es mi alternativa. Esperaba algunas construcciones de lenguaje o funciones integradas que pudiera usar. Si tengo que comparar absolutamente con el rango válido, ¿hay al menos algunas constantes integradas (como C# int.MinValue & int.MaxValue)?

EDIT: Error corregido.

+0

No hay constantes integradas. Si termina queriendo comparar con constantes, esa pregunta ha sido respondida antes: http://stackoverflow.com/questions/7092774/max-value-represented-by-bigint/7092844#7092844 –

+0

¿Por qué no simplemente asignar el valor a una variable INT en su procedimiento almacenado, asigne ese valor nuevamente a una variable BIGINT, luego compare el BIGINT con el valor original (también un BIGINT).Si hubiera una asignación de desbordamiento a un INT, los valores no coincidirán. –

+0

@Conspicuo compilador, nunca dije que estuviera usando un procedimiento almacenado. De todos modos, al hacerlo, se genera un "Error de desbordamiento aritmético que convierte la expresión a tipo de datos int". como se aludió en mi pregunta original. –

Respuesta

0

También puede convertir el valor en una cadena, recortarla a la longitud y convertir a int. no es la mejor manera, pero de una manera fácil y segura a ciencia cierta

1

no estoy seguro de que esta es la mejor respuesta, pero es uno que se me ocurrió antes en mi propia. Es posible detectar la excepción/error y continuar con gracia la ejecución.

Ejemplo:

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

de emitir su bigint a varbinary, a continuación, almacenar la mitad inferior de @UserID y comprobar la mitad superior:

  • si la mitad superior es todo 0 y la mitad inferior representa un valor no negativo, @UserID contiene el valor correcto de int;

  • si la mitad superior es todos 1 y @UserID es negativo, está bien también;

  • de lo contrario hay un desbordamiento aritmético.

Aquí es una implementación:

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 
Cuestiones relacionadas