'Getting maximum value of float in SQL programmatically
Is there an method for programmatically (in T-SQL) retrieving the maximum (and minimum) value of a datatype? That it would act like float.MaxValue in C#.
I would like to use it in some selection when the parameter does not equal any actual values in the database, so I would use something like
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*/)
Solution 1:[1]
Though there doesn't appear to be any inline way to get the min or max values, 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_float AS CAST('-1.79E+308' AS float)
,max_float AS CAST('1.79E+308' AS float)
,min_real AS CAST('-3.40E+38' AS real)
,max_real AS CAST('3.40E+38' AS real)
,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
After that, you can either copy a maximum value to a local variable or (when using queries) cross join with this table.
Declare @max_int int
Set @max_int=(SELECT max_int FROM datatype_extrema)
IF COALESCE(@FirstInt, @max_int) < COALESCE(@SecondInt, 0)
Solution 2:[2]
Here are the defaults for the float and real type (that's missing in the accepted answer):
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
Unfortunately it is not possible to convert them from a varbinary, but varchar works without any problems.
Solution 3:[3]
For float
and real
the min and max values can be computed using the POWER
function:
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)
And these are the decimal values:
SELECT
max_float = 1.7976931348623158E+308
, min_float = -1.7976931348623158E+308
, max_real = 3.4028234E+38
, min_real = -3.4028234E+38
Solution 4:[4]
1.79769313486231580799909999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
This is the max number of float value
Here's how you can get it:
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
Solution 5:[5]
SELECT ST.name AS Name,
ST.max_length AS MaxLength,
ST.precision AS Precision,
ST.scale AS Scale,
ST.is_nullable AS IsNullable,
IIF(ST.max_length > 0, ST.max_length * 8, 0) AS SizeBits,
CASE
WHEN ST.name in ('tinyint', 'smallint', 'int', 'real', 'money', 'float', 'decimal', 'numeric', 'bigint')
THEN Power(cast(2 as varchar), ST.max_length * 8 -1) * (-1)
ELSE NULL END AS MinValue,
CASE
WHEN ST.name in ('tinyint', 'smallint', 'int', 'real', 'money', 'float', 'decimal', 'numeric', 'bigint')
THEN Power(cast(2 as varchar), ST.max_length * 8 -1) -1
ELSE NULL END AS MaxValue
FROM sys.types ST
WHERE ST.is_user_defined = 0
ORDER BY 1
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Oliver |
Solution 3 | Anthony Faull |
Solution 4 | |
Solution 5 | Cristian Meneses González |