¿Hay alguna forma en T-SQL de convertir un nvarchar a int y devolver un valor predeterminado o NULL si la conversión falla?
116
Utilice la función TRY_CONVERT .
Cree una función definida por el usuario. Esto evitará los problemas que mencionó Fedor Hajdu con respecto a la moneda, números fraccionarios, etc.
CREATE FUNCTION dbo.TryConvertInt(@Value varchar(18))
RETURNS int
AS
BEGIN
SET @Value = REPLACE(@Value, ',', '')
IF ISNUMERIC(@Value + 'e0') = 0 RETURN NULL
IF ( CHARINDEX('.', @Value) > 0 AND CONVERT(bigint, PARSENAME(@Value, 1)) <> 0 ) RETURN NULL
DECLARE @I bigint =
CASE
WHEN CHARINDEX('.', @Value) > 0 THEN CONVERT(bigint, PARSENAME(@Value, 2))
ELSE CONVERT(bigint, @Value)
END
IF ABS(@I) > 2147483647 RETURN NULL
RETURN @I
END
GO
-- Testing
DECLARE @Test TABLE(Value nvarchar(50)) -- Result
INSERT INTO @Test SELECT '1234' -- 1234
INSERT INTO @Test SELECT '1,234' -- 1234
INSERT INTO @Test SELECT '1234.0' -- 1234
INSERT INTO @Test SELECT '-1234' -- -1234
INSERT INTO @Test SELECT '$1234' -- NULL
INSERT INTO @Test SELECT '1234e10' -- NULL
INSERT INTO @Test SELECT '1234 5678' -- NULL
INSERT INTO @Test SELECT '123-456' -- NULL
INSERT INTO @Test SELECT '1234.5' -- NULL
INSERT INTO @Test SELECT '123456789000000' -- NULL
INSERT INTO @Test SELECT 'N/A' -- NULL
SELECT Value, dbo.TryConvertInt(Value) FROM @Test
Referencia: utilicé esta página ampliamente al crear mi solución.
Si :). Prueba esto:
ISNUMERIC()
tiene algunos problemas señalados por Fedor Hajdu .Devuelve verdadero para cadenas como
$
(es moneda),
o.
(ambos son separadores)+
y-
.fuente
ISNUMERIC
para que esta respuesta sea de alguna utilidad en datos no validados (y no necesitaría laISNUMERIC
verificación en primer lugar para datos validados correctamente). El autor reconoce la existencia de estos problemas pero no los aborda.TRY_CONVERT
/TRY_CAST
, que están destinados explícitamente a resolver la pregunta del OP. Esta respuesta se escribió antes de que se lanzara SQL 2012.Prefiero crear una función como TryParse o usar el
TRY-CATCH
bloque T-SQL para obtener lo que desea.ISNUMERIC no siempre funciona según lo previsto. El código dado antes fallará si lo hace:
SET @text = '$'
El signo $ se puede convertir al tipo de datos dinero, por lo que
ISNUMERIC()
devuelve verdadero en ese caso. Hará lo mismo para '-' (menos), ',' (coma) y '.' caracteres.fuente
ISNUMERIC()
regresa1
para,
y.
.Como se ha mencionado, puede tener varios problemas si usa
ISNUMERIC
:Si desea una conversión confiable, deberá codificar una usted mismo.
Actualización : Mi nueva recomendación sería utilizar una conversión de prueba intermedia
FLOAT
para validar el número. Este enfoque se basa en el comentario de Adrianm . La lógica se puede definir como una función con valores de tabla en línea:Algunas pruebas:
Los resultados son similares a la respuesta de Joseph Sturtevant , con las siguientes diferencias principales:
.
o,
para imitar el comportamiento de lasINT
conversiones nativas .'1,234'
y'1234.0'
volverNULL
.'00000000000000001234'
evalúa a12
. El aumento de la longitud del parámetro daría lugar a errores en los números que se desbordanBIGINT
, como los BBAN (números básicos de cuentas bancarias)'212110090000000235698741'
.Retirado : el enfoque a continuación ya no se recomienda, ya que se deja solo como referencia.
El siguiente fragmento funciona con números enteros no negativos. Verifica que su cadena no contenga caracteres que no sean dígitos, que no esté vacía y que no se desborde (al exceder el valor máximo para el
int
tipo). Sin embargo, también proporcionaNULL
números enteros válidos cuya longitud excede los 10 caracteres debido a ceros a la izquierda.Si desea admitir cualquier número de ceros a la izquierda, utilice lo siguiente. Las
CASE
declaraciones anidadas , aunque difíciles de manejar, son necesarias para promover la evaluación de cortocircuitos y reducir la probabilidad de errores (que surgen, por ejemplo, de pasar una longitud negativa aLEFT
).Si desea admitir números enteros positivos y negativos con cualquier número de ceros iniciales:
fuente
Saludos.
Escribí una función escalar útil para simular la función TRY_CAST de SQL SERVER 2012 en SQL Server 2008.
Puedes verlo en el siguiente enlace a continuación y nos ayudamos mutuamente a mejorarlo. Función TRY_CAST para SQL Server 2008 https://gist.github.com/jotapardo/800881eba8c5072eb8d99ce6eb74c8bb
Ejemplo:
Por ahora solo admite los tipos de datos INT, DATE, NUMERIC, BIT y FLOAT
Espero que le sea útil.
CÓDIGO:
fuente
La respuesta de Joseph señaló que ISNUMERIC también maneja notación científica como '1.3e + 3' pero su respuesta no maneja este formato de número.
Lanzar dinero o flotar primero maneja tanto la moneda como las cuestiones científicas:
La función fallará si el número es mayor que un bigint.
Si desea devolver un valor predeterminado diferente, deje esta función para que sea genérica y luego reemplace el nulo:
fuente
Sé que no es bonito, pero es sencillo. Prueba esto:
fuente
Mi solución a este problema fue crear la función que se muestra a continuación. Mis requisitos incluían que el número tenía que ser un número entero estándar, no un BIGINT, y necesitaba permitir números negativos y números positivos. No he encontrado ninguna circunstancia en la que esto falle.
fuente