This discussion has been locked. The information referenced herein may be inaccurate due to age, software updates, or external references.
You can no longer post new replies to this discussion. If you have a similar question you can start a new discussion in this forum.

SQL Data Types and Why They Matter

I was building a report for a customer this morning based on a solution that I had implemented for them.  The solution was for calculating volume utilization based on a non-fixed percentage.  It is something that I saw adatole​ use and that zackm​ expanded on when he joined the team at my full-time gig in the summer of 2017.

The premise is pretty simple.  I built a volume custom property where the customer could insert the minimum disk space that the customer wanted before getting and alert and then using a PowerShell script and a SWQL query, I pulled that value, calculated a v_UsageCrit and v_UsageWarn percentage and wrote them into the volume custom properties.  The alerting then uses % used and compares it against the v_UsageCrit and v_UsageWarn custom properties before alerting.

All good, right?

Like any good engineer, I wanted to provide the custom with a report that showed them 1) if they have volumes where they hadn't defined the minimum disk space, and 2) if the script the updates the v_UsageCrit and v_UsageWarn custom properties hadn't done its job.  Easy enough right?  I just write a SWQL query that checks to the two values, but I kept getting back results where I knew the values where the same and SWQL was reporting both the custom property and the calculated value as the same (95.12 = 95.12, right?)

Maybe it was a SWQL thing?  (I know tdanner​ loves when we poke at SWQL!)  So I re-wrote the query in SQL.  (This is a heavily paraphrased version)

SELECT
v.caption
,v_UsageCrit
,(100-(ROUND((v.v_MinimumDiskSpace/(v.VolumeSize/1024/1024))*100,2)) ) AS [Calculated Value}
FROM Volumes v
WHERE
v_UsageCrit <> (100-(ROUND((v.v_MinimumDiskSpace/(v.VolumeSize/1024/1024))*100,2)) )

But I kept getting results back that were the same as the SWQL results.  Why would two values that were the same (heck, the custom property value was inserted by the same calculation that I was comparing it against!) come back as not being equal?  I thought it was a rounding issue.  Nope.  And then I remembered that SQL has different data types!

The custom properties were created as Floating Point Numbers. When I checked the Volumes table in SQL I saw that they were being stored as Real numbers.

pastedImage_11.png

But what about the calculated number?  What data type was it?  The answer is in SQL_VARIANT_PROPERTY

SQL_VARIANT_PROPERTY(v.v_UsageCrit,'basetype') AS [Custom Property Type]
,SQL_VARIANT_PROPERTY( (100-(ROUND((v.v_MinimumDiskSpace/(v.VolumeSize/1024/1024))*100,2)) ), 'basetype' ) AS [Calculated Base Type]

When I stuck that into my query and then ran it I saw this!

pastedImage_19.png

Comparing two different data types in SQL meant that they weren't actually the same!  I quickly CAST the values and the query returned results as expect.  An example of the logic is below.

CAST(v.v_UsageCrit AS decimal(6,2) = CAST( (100-(ROUND((v.v_MinimumDiskSpace/(v.VolumeSize/1024/1024))*100,2)) AS decimal(6,2)

The moral of the story is:  If the data looks right to the human eye, it is probably SQL data types that are making your life miserable emoticons_grin.png

  • Comparing floating point values for equality is a tricky thing. In general, when working with floating point values you should expect a certain amount of error, so it is better to test if the values are close enough rather than exactly equal. So rather than test if A = B, you can test if ABS(A - B) < 0.0001.

  • I feel like I can get away with it in this case because I am comparing a value that was computed and written to a custom property against the same computed value (or expected computed value). If they aren't exactly the same then I would want to know about it and make sure it was investigated.

    Plus, my need to have things exact is sometimes overwhelming emoticons_grin.png