2010-04-23 4 views
15

Gibt es eine Methode für programmgesteuert (in T-SQL) Abrufen des maximalen (und minimalen) Werts eines Datentypen? Das würde wie float.MaxValue in C# handeln.Maximaler Wert von Fließkomma in SQL programmgesteuert erhalten

Ich möchte es in irgendeiner Auswahl verwenden, wenn der Parameter nicht gleich alle Ist-Werte in der Datenbank, also würde ich so etwas wie

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*/) 

Antwort

21

verwenden Obwohl es keine Inline-Weg zu sein scheint die min oder max-Werte zu erhalten, 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 

Danach können Sie entweder kopieren einen maximalen Wert auf eine lokale Variable oder mit dieser Tabelle Cross-Join (wenn Abfragen verwendet wird).

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

Hier sind die Standardeinstellungen für den Schwimmer und realen Typ (das ist in der akzeptierte Antwort fehlt):

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 

Leider ist es nicht möglich ist, sie von einem varbinary zu konvertieren, aber varchar funktioniert ohne Probleme.

1

Für float und real die min und max Werte berechnet werden kann mit der POWER Funktion:

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) 

Und das sind die Dezimalwerte:

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

Diese ist die maximale Anzahl von float Wert

Hier ist, wie Sie es bekommen können:

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

Dies ist außergewöhnlich! – Tigerjz32

+0

Die Frage des OP war eher eine programmatische Möglichkeit, den Max-Wert des Float-Datentyps zu erhalten. –

+0

Ich fügte eine Brute-Force-Methode hinzu, um zu ermitteln, wann der Float einen Fehler auslöst. – Kyle