sql server - round - T-sql: determina si el valor es entero
round sql (12)
Vea si la siguiente consulta ayudará
SELECT *
FROM MY_TABLE
WHERE CHARINDEX(''.'',MY_FIELD) = 0 AND CHARINDEX('','',MY_FIELD) = 0
AND ISNUMERIC(MY_FIELD) = 1 AND CONVERT(FLOAT,MY_FIELD) / 2147483647 <= 1
Quiero determinar si un valor es entero (como TryParse
en .NET). Desafortunadamente ISNUMERIC
no me queda porque quiero analizar solo enteros y no cualquier tipo de número. ¿Hay algo como ISINT
o algo así?
Aquí hay un código para aclarar las cosas. Si MY_FIELD
no es int, este código fallará:
SELECT @MY_VAR = CAST(MY_FIELD AS INT)
FROM MY_TABLE
WHERE MY_OTHER_FIELD = ''MY_FILTER''
Gracias
¿Por qué no hacer algo como esto?
CASE
WHEN ROUND(MY_FIELD,0)=MY_FIELD THEN CAST(MY_FIELD AS INT)
ELSE MY_FIELD
END
as MY_FIELD2
A veces no puedes diseñar la base de datos, solo tienes que trabajar con lo que te dan. En mi caso, es una base de datos ubicada en una computadora a la que solo tengo acceso de lectura desde 2008.
Necesito seleccionar de una columna en una base de datos mal diseñada que es una varchar
con los números del 1 al 100 pero a veces una cadena aleatoria. Usé lo siguiente para evitarlo (aunque me gustaría poder haber re diseñado toda la base de datos).
SELECT A from TABLE where isnumeric(A)=1
Aquí hay una publicación de blog que describe la creación de una UDF IsInteger
.
Básicamente, recomienda agregar ''.e0''
al valor y usar IsNumeric
. De esta forma, todo lo que ya tenía un punto decimal ahora tiene dos puntos decimales, lo que hace que IsNumeric
sea falso, y cualquier cosa ya expresada en notación científica es invalidada por e0
.
Con sqlserver 2005 y posterior puede usar clases de caracteres similares a expresiones regulares con el operador LIKE. Mira here .
Para verificar si una cadena es un entero no negativo (es una secuencia de dígitos decimales) puede probar que no contiene otros caracteres.
SELECT numstr
FROM table
WHERE numstr NOT LIKE ''%[^0-9]%''
Nota 1: Esto también devolverá las cadenas vacías.
Nota 2: El uso de LIKE ''%[0-9]%''
devolverá cualquier cadena que contenga al menos un dígito.
Ver fiddle
Creo que hay algo mal con el diseño de su base de datos. Creo que es una mala idea mezclar varchar y números en una columna. ¿Cuál es la razón para eso?
Por supuesto, puede verificar si hay otros caracteres distintos de [0-9], pero imagine que tiene 1m de filas en la tabla y está revisando cada fila. Creo que no funcionará bien.
De todos modos, si realmente quieres hacerlo, te sugiero que lo hagas desde el lado del cliente.
En su artículo ¿Puedo convertir esta cadena en un número entero? , Itzik Ben-Gan proporciona una solución en T-SQL puro y otra que usa el CLR.
¿Qué solución deberías elegir?
¿La solución T-SQL o CLR es mejor? La ventaja de utilizar la solución T-SQL es que no necesita salir del dominio de la programación T-SQL. Sin embargo, la solución CLR tiene dos ventajas importantes: es más simple y más rápida. Cuando probé ambas soluciones en una mesa que tenía 1,000,000 de filas, la solución CLR tardó dos segundos, en lugar de siete segundos (para la solución T-SQL), en ejecutarse en mi computadora portátil. Por lo tanto, la próxima vez que necesite verificar si una cadena dada se puede convertir a un número entero, puede incluir la solución T-SQL o CLR que proporcioné en este artículo.
Si solo desea mantener T-SQL, utilice la solución pura de T-SQL. Si el rendimiento es más importante que la comodidad, entonces use la solución CLR.
La solución T-SQL pura es engañosa. Combina la función ISNUMERIC incorporada con coincidencia de patrón y fundición para comprobar si la cadena representa un int.
SELECT keycol, string, ISNUMERIC(string) AS is_numeric,
CASE
WHEN ISNUMERIC(string) = 0 THEN 0
WHEN string LIKE ''%[^-+ 0-9]%'' THEN 0
WHEN CAST(string AS NUMERIC(38, 0))
NOT BETWEEN -2147483648. AND 2147483647. THEN 0
ELSE 1
END AS is_int
FROM dbo.T1;
La parte T-SQL de la solución CLR es más simple. Llama a la función fn_IsInt tal como lo llamaría ISNUMERIC.
SELECT keycol, string, ISNUMERIC(string) AS is_numeric,
dbo.fn_IsInt(string) AS is_int
FROM dbo.T1;
La parte C # es simplemente un contenedor para la función de análisis de .NET Int32.TryParse. Esto funciona porque SQL Server int y .NET Int32 son enteros de 32 bits con signo.
using System;
using System.Data.SqlTypes;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlBoolean fn_IsInt(SqlString s)
{
if (s.IsNull)
return SqlBoolean.False;
else
{
Int32 i = 0;
return Int32.TryParse(s.Value, out i);
}
}
};
Por favor, lea el artículo de Itzik para una explicación completa de estos ejemplos de código.
Este trabajo con la función IsNumeric funcionará:
seleccione * de A donde ISNUMÉRICO (x) = 1 y X no como ''%.%''
o usar
seleccione * de A donde x no sea como ''% [^ 0-9]%''
Lo siguiente es correcto para una cláusula WHERE
; para hacer una función envuélvala en CASE WHEN
.
ISNUMERIC(table.field) > 0 AND PATINDEX(''%[^0123456789]%'', table.field) = 0
Tengo la sensación de que hacerlo de esta manera es obra de Satanás, pero como alternativa:
¿Qué tal un TRY - CATCH?
DECLARE @Converted as INT
DECLARE @IsNumeric BIT
BEGIN TRY
SET @Converted = cast(@ValueToCheck as int)
SET @IsNumeric=1
END TRY
BEGIN CATCH
SET @IsNumeric=0
END CATCH
select IIF(@IsNumeric=1,''Integer'',''Not integer'') as IsInteger
Esto funciona, aunque solo en SQL Server 2008 en adelante.
declare @i numeric(28,5) = 12.0001 if (@i/cast(@i as int) > 1) begin select ''this is not int'' end else begin select ''this is int'' end
WHERE IsNumeric(MY_FIELD) = 1 AND CAST(MY_FIELD as VARCHAR(5)) NOT LIKE ''%.%''
Esa es probablemente la solución más simple. A menos que su MY_FIELD
contenga .00 o algo por el estilo. En ese caso, colóquelo en un flotador para eliminar cualquier .00s posterior