2011-08-17 18 views
7

Ho un CSV che sto importando nel nostro database. Una delle "colonne" contiene dati che devono essere essere un INT ma alcune righe hanno numeri che rientrano solo nell'intervallo BIGINT (perché sono dati di test da uno dei nostri partner). Archiviamo INT internamente e non desideriamo cambiare.SQL: downcast in modo sicuro da BIGINT a INT

Voglio downcast sicuro da BIGINT a INT. Con sicurezza, voglio dire che nessun errore dovrebbe essere sollevato se si verifica un overflow aritmetico. Se il cast/conversione ha esito positivo, voglio che il mio script vada avanti. Se fallisce, lo voglio cortocircuitare. Non riesco a capire la sintassi corretta. Questo è quello che ho:

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 

Ci ho pensato a confronto @UserIDBigInt per l'intervallo valido di un INT (-2^31 (-2.147.483.648) a 2^31-1 (2,147,483,647)), ma davvero non mi piace questo approccio. Questa è la mia riserva. Speravo in alcuni costrutti linguistici o funzioni integrate che potrei usare. Se devo assolutamente confrontarmi con l'intervallo valido, ci sono almeno alcune costanti integrate (come int.MinValue di C# & int.MaxValue)?

MODIFICA: errore di battitura corretto.

+0

Non ci sono costanti predefinite. Se dovessi finire per paragonare a costanti, quella domanda ha avuto risposta prima: http://stackoverflow.com/questions/7092774/max-value-represented-by-bigint/7092844#7092844 –

+0

Perché non assegnare il valore a una variabile INT nella stored procedure, assegnare tale valore a una variabile BIGINT, quindi confrontare BIGINT con il valore originale (anche BIGINT).Se ci fosse un overflow che assegna a un INT, i valori non corrisponderanno. –

+0

@Conspicuous Compiler, non ho mai detto che sto usando una stored procedure. Indipendentemente da ciò, facendo ciò solleva un "Errore di overflow aritmetico convertendo espressione in tipo di dati int". come accennato nella mia domanda iniziale. –

risposta

0

È anche possibile convertire il valore in una stringa, tagliarlo in lunghezza e convertirlo in int. non il modo migliore, ma un modo sicuro facile di sicuro

1

io non sono sicuro che questa è la migliore risposta, ma è uno mi è venuta in precedenza per conto mio. È possibile rilevare l'eccezione/errore e con garbo continuare l'esecuzione.

Esempio:

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

lanciare la vostra bigint a varbinary, quindi memorizzare la metà inferiore a @UserID e controllare la metà superiore:

  • se la metà superiore è tutto 0 e la metà inferiore rappresenta un valore non negativo, @UserID quindi contiene il valore corretto int;

  • se la metà superiore è tutto 1 e @UserID è negativo, va bene anche così;

  • altrimenti c'è un overflow aritmetico.

Ecco un'implementazione:

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 
Problemi correlati