2010-04-23 17 views
15

¿Hay un método para programáticamente (en T-SQL) recuperando el valor máximo (y mínimo) de un tipo de datos? Que actuaría como float.MaxValue en C#.Obteniendo el valor máximo de float en SQL programáticamente

me gustaría utilizarlo en alguna selección cuando el parámetro no es igual a cualquiera de los valores reales en la base de datos, por lo que me gustaría utilizar algo así como

declare @min float 
declare @max float 
--fill @min and @max, can be null if undefined 
select * from foo 
    where bar between isnull(@min,0) and isnull(@max,max(float)/*magic*/) 

Respuesta

21

Aunque no parece haber ninguna manera inline para obtener el min o max valores, there's a solution somebody put together:

CREATE TABLE datatype_extrema 
    (min_bit bit NOT NULL DEFAULT (0) CHECK (min_Bit=0) 
    ,max_bit   AS CAST(0x1 AS bit) 
    ,min_tinyint  AS CAST(0x00 AS tinyint) 
    ,max_tinyint  AS CAST(0xFF AS tinyint) 
    ,min_smallint  AS CAST(0x8000 AS smallint) 
    ,max_smallint  AS CAST(0x7FFF AS smallint) 
    ,min_int   AS CAST(0x80000000 AS int) 
    ,max_int   AS CAST(0x7FFFFFFF AS int) 
    ,min_bigint  AS CAST(0x8000000000000000 AS bigint) 
    ,max_bigint  AS CAST(0x7FFFFFFFFFFFFFFF AS bigint) 
    ,min_smalldatetime AS CAST('19000101 00:00' AS smalldatetime) 
    ,max_smalldatetime AS CAST('20790606 23:59' AS smalldatetime) 
    ,min_datetime  AS CAST('17530101 00:00:00.000' AS datetime) 
    ,max_datetime  AS CAST('99991231 23:59:59.997' AS datetime) 
) 
    INSERT INTO datatype_extrema DEFAULT VALUES 
    GO 
    CREATE TRIGGER nochange_datatype_extrema 
    ON datatype_extrema INSTEAD OF INSERT, UPDATE, DELETE 
    AS BEGIN 
    RAISERROR ('No changes allowed for table datatype_extrema.', 16, 1) 
    ROLLBACK TRANSACTION 
    END 
    GO 

Después de eso, puede copiar un valor máximo a una variable local o (cuando el uso de consultas) combinación cruzada con esta tabla.

Declare @max_int int 
    Set @max_int=(SELECT max_int FROM datatype_extrema) 
    IF COALESCE(@FirstInt, @max_int) < COALESCE(@SecondInt, 0) 
11

Éstos son los valores por defecto para el flotador y el tipo real (lo que falta en la respuesta aceptada):

select 
    CAST('-1.79E+308' AS float) as MinFloat, 
    CAST('1.79E+308' AS float) as MaxFloat, 
    CAST('-3.40E+38' AS real) as MinReal, 
    CAST('3.40E+38' AS real) as MaxReal 

Por desgracia, no es posible convertirlos de un varbinary, pero varchar funciona sin ningún problemas.

1

Para float y real la min y max valores se pueden calcular utilizando la función de POWER:

SELECT 
    max_float = (1 + (POWER(2e0, 52) - 1)/POWER(2e0, 52)) * POWER(2e0, 1023) 
    , min_float = -(1 + (POWER(2e0, 52) - 1)/POWER(2e0, 52)) * POWER(2e0, 1023) 
    , max_real = CAST((1 + (POWER(2e0,23)-1)/POWER(2e0,23)) * POWER(2e0,127) AS real) 
    , min_real = CAST(-(1 + (POWER(2e0,23)-1)/POWER(2e0,23)) * POWER(2e0,127) AS real) 

Y estos son los valores decimales:

SELECT 
    max_float = 1.7976931348623158E+308 
    , min_float = -1.7976931348623158E+308 
    , max_real = 3.4028234E+38 
    , min_real = -3.4028234E+38 
1
1.79769313486231580799909999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 

Este es el número máximo de flotador valor

Así es como lo puede conseguir:

DECLARE @decimal_length int = 0 
DECLARE @decimal_value varchar(max) = '1.79' 
DECLARE @decimal_value_buffer varchar(max) = @decimal_value 
DECLARE @new_int varchar(10) = '9' 
DECLARE @dummy float 
WHILE @decimal_length < 308 
BEGIN 

    SET @decimal_value = @decimal_value + @new_int 

    BEGIN TRY 
     SET @dummy = CAST(@decimal_value + 'E+308' AS float) 
     SET @decimal_length = @decimal_length + 1 
     SET @decimal_value_buffer = @decimal_value 
     SET @new_int = '9' 
    END TRY 
    BEGIN CATCH 
     SET @decimal_value = @decimal_value_buffer 
     SET @new_int = @new_int - 1 
    END CATCH 
END 

PRINT @decimal_value 
+0

Esta es excepcional! – Tigerjz32

+0

La pregunta del OP era más acerca de una forma programática para obtener el valor máximo del tipo de datos float. –

+0

Agregué un método de fuerza bruta para identificar cuándo el flotador arroja un error. – Kyle

Cuestiones relacionadas