惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
I
InfoQ
The Register - Security
The Register - Security
L
LangChain Blog
H
Help Net Security
The GitHub Blog
The GitHub Blog
S
Schneier on Security
博客园 - 【当耐特】
W
WeLiveSecurity
Attack and Defense Labs
Attack and Defense Labs
IT之家
IT之家
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
The Cloudflare Blog
H
Heimdal Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Y
Y Combinator Blog
雷峰网
雷峰网
N
Netflix TechBlog - Medium
Security Archives - TechRepublic
Security Archives - TechRepublic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
L
Lohrmann on Cybersecurity
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Exploit Database - CXSecurity.com
P
Privacy & Cybersecurity Law Blog
G
GRAHAM CLULEY
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
V
Visual Studio Blog
博客园 - 聂微东
PCI Perspectives
PCI Perspectives
Last Week in AI
Last Week in AI
A
Arctic Wolf
宝玉的分享
宝玉的分享
T
The Blog of Author Tim Ferriss
S
Secure Thoughts
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
云风的 BLOG
云风的 BLOG
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
SegmentFault 最新的问题
SecWiki News
SecWiki News
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
Schneier on Security
Schneier on Security
P
Proofpoint News Feed
博客园 - Franky
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
AI
AI
Engineering at Meta
Engineering at Meta

博客园 - Vincent Yang

Cannot load macro project error SQL Express - "Failed generate a user instance..." SQL Express 2008 x64 Integration with Visual Studio 2008 SP1 PowerShell Operators Crystal Reports .NET Error - "Access to report file denied. Another program may be using it." - Vincent Yang (转:)SharePoint Database Naming Standards List Types & List Internal ID available within MOSS 2007 Telerik: IIS7 & IIS 7.5 and ‘Telerik.Web.UI.WebResource.axd’ is missing in web config 64bit SQL Server issues : Connections to SQL Server files (*.mdf) require SQL Server Express 2005 to function properly 正式入住Windows 7 + XPM A Generic Singleton Form Provider for C# Extreme Programming: Do these 12 practices make perfect? Pick up the pace with extreme programming Testing an ASP.NET Web Service using PowerShell Parsing XML Files with PowerShell Testing SQL Stored Procedures using PowerShell Working with Collections of Objects using PowerShell Generating iCalender file using ASP.NET Six Quick Crystal Reports Design Tips
SQL Server Precision And Scale Problems (SQL Server 精度问题)
Vincent Yang · 2009-01-23 · via 博客园 - Vincent Yang

Ref: http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/sql-server-precision-and-scale-problems

Many people are confused about SQL Server's precision and scale. This is unfortunate because choosing the correct values for precision and scale is critically important when you perform math operations using the decimal/numeric data type. The point of this blog is to explain how SQL Server determines the data type for math operations, and the order in which conversions occur.

For example:

  1. SELECT 10 / 3           UNION All
  2. SELECT 10 / 3.0         UNION All
  3. SELECT 10 / 3.00        UNION All
  4. SELECT 10 / 3.000       UNION All
  5. SELECT 10 / 3.0000      UNION All
  6. SELECT 10 / 3.00000     UNION All
  7. SELECT 10 / 3.000000    UNION All
  8. SELECT 10 / 3.0000000   UNION All
  9. SELECT 10 / 3.00000000

Let's take a close look at the above query so that we can predict the output. Of course, it will help if we know the data types that SQL Server uses. There is a relatively obscure function that you can use to determine the data types. SQL_VARIANT_PROPERTY

For the first calculation, we have 10 / 3. We all know the answer is 3 1/3, but how is this expressed in the output?

Well, using the SQL_VARIANT_PROPERTY function, we can determine the data type that SQL Server will use.

  1. SELECT SQL_VARIANT_PROPERTY(3, 'BaseType') AS [Base Type],
  2.        SQL_VARIANT_PROPERTY(3, 'Precision') AS [PRECISION],
  3.        SQL_VARIANT_PROPERTY(3, 'Scale') AS [Scale],
  4.  
  5.        SQL_VARIANT_PROPERTY(10, 'BaseType') AS [Base Type],
  6.        SQL_VARIANT_PROPERTY(10, 'Precision') AS [PRECISION],
  7.        SQL_VARIANT_PROPERTY(10, 'Scale') AS [Scale]

The output indicates SQL Server will use Integer, Precision 10, scale 0. Using integer math, the output will be 3. Since both values are integer, the result is an integer.

Now, let's look at the next one. 10/3.0

  1. SELECT SQL_VARIANT_PROPERTY(3.0, 'BaseType') AS [Base Type],
  2.        SQL_VARIANT_PROPERTY(3.0, 'Precision') AS [PRECISION],
  3.        SQL_VARIANT_PROPERTY(3.0, 'Scale') AS [Scale],
  4.  
  5.        SQL_VARIANT_PROPERTY(10, 'BaseType') AS [Base Type],
  6.        SQL_VARIANT_PROPERTY(10, 'Precision') AS [PRECISION],
  7.        SQL_VARIANT_PROPERTY(10, 'Scale') AS [Scale]

This time, we get Numeric(2,1) (for 3.0) and int for the 10. There are well defined (although obscure) rules for math operations. Full rules here: Precision, Scale, and Length

For division, the rule is:

Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
Scale = max(6, s1 + p2 + 1)

p1 represents the precision of the first number. s1 represents the scale of the first number. P2 and S2 represent the second number.

10 / 3.0
P1 = 10
S1 = 0
P2 = 2
S2 = 1

Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
Precision = 10 - 0 + 1 + max(6, 0 + 2 + 1)
Precision = 11 + Max(6, 3)
Precision = 11 + 6
Precision = 17

Unfortunately, this isn't correct because the SQL_VARIANT_PROPERTY is returning 10 for the integer. When dividing the numbers, SQL Server actually converts the integer to a decimal, using the smallest value possible to represent the value. In this case, 10 is converted to decimal(2,0). Performing the calculations again:

10 / 3.0
P1 = 2
S1 = 0
P2 = 2
S2 = 1

Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
Precision = 2 - 0 + 1 + max(6, 0 + 2 + 1)
Precision = 3 + Max(6, 3)
Precision = 3 + 6
Precision = 9

Scale = max(6, s1 + p2 + 1)
Scale = max(6, 0 + 2 + 1)
Scale = max(6,3)
Scale = 6

So, Select 10 / 3.0 = 3.333333

Now, let's fast forward to the last calculation. Select 10 / 3.00000000

Precision/scale for the 10 (after converting to decimal) = 2,0
Precision/scale for the 3.00000000 = 9,8

10 / 3.00000000
P1 = 2
S1 = 0
P2 = 9
S2 = 8

Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
Precision = 2 - 0 + 8 + max(6, 0 + 9 + 1)
Precision = 10 + Max(6, 10)
Precision = 10 + 10
Precision = 20

Scale = max(6, s1 + p2 + 1)
Scale = max(6, 0 + 9 + 1)
Scale = max(6,10)
Scale = 10

The result is 3.3333333333 Decimal(20,10)

Lastly, since the original example was a UNION ALL query, all results are converted to the same data type. Each result is first calculated, then finally converted to a data type that satisfies all results. In this case, each result is converted to a Decimal(20,10). But remember, this ONLY occurs after each calculation is performed!

Select 10 / 3           3.0000000000 Int
Select 10 / 3.0 3.3333330000 Decimal(9,6)
Select 10 / 3.00 3.3333330000 Decimal(10,6)
Select 10 / 3.000 3.3333330000 Decimal(11,6)
Select 10 / 3.0000 3.3333330000 Decimal(12,6)
Select 10 / 3.00000 3.3333333000 Decimal(14,7)
Select 10 / 3.000000 3.3333333300 Decimal(16,8)
Select 10 / 3.0000000 3.3333333330 Decimal(18,9)
Select 10 / 3.00000000 3.3333333333 Decimal(20,10)