简体   繁体   English

将子字符串数字从 nvarchar 转换为数字

[英]Convert substring numbers from nvarchar to numeric

I know there are a lot of question on here about converting strings to integers in SQL but I have not been able to get anything to work with a value returned by substring.我知道这里有很多关于在 SQL 中将字符串转换为整数的问题,但我无法使用子字符串返回的值进行任何处理。 I am using the substring function to return only the numbers from a string so I can compare the values but I'm getting an error.我使用 substring 函数只返回字符串中的数字,以便我可以比较这些值,但出现错误。

Error converting data type nvarchar to numeric.将数据类型 nvarchar 转换为数字时出错。

I have tried running the below:我试过运行以下:

select 
   sy.ResourceID,
   sy.ResourceType,
   sy.Name0,
   sy.SMS_Unique_Identifier0,
   sy.Resource_Domain_OR_Workgr0,
   sy.Client0,
   Cast(Cast (substring(bio.SMBIOSBIOSVersion0,9,6)as Numeric(4,2)) as Int) as 'BiosVersion'
from v_R_system sy 
   inner join v_GS_FIRMWARE firm on firm.ResourceID = sy.ResourceId 
   inner join v_GS_COMPUTER_SYSTEM CS on cs.ResourceID = sy.ResourceId 
   inner join v_GS_PC_BIOS Bio on bio.ResourceID = sy.ResourceId 
where firm.SecureBoot0 != 1 and cs.Model0 = 'HP EliteBook 840 G3'

Casting as int rounds to 1 , when it should be 01.43 based on what the substring gets.转换为 int 01.431 ,当它应该是01.43基于子字符串的获取。 When I remove the cast as int and just convert as numeric it truncates it 1.42 .当我删除转换为 int 并只转换为数字时,它会截断它1.42 When I try compare it to a value I specify I still get the error stated above.当我尝试将它与我指定的值进行比较时,我仍然收到上述错误。

select 
   sy.ResourceID,
   sy.ResourceType,
   sy.Name0,
   sy.SMS_Unique_Identifier0,
   sy.Resource_Domain_OR_Workgr0,
   sy.Client0,
   Cast(substring(bio.SMBIOSBIOSVersion0,9,6)as Numeric(4,2)) as 'BiosVersion'
from v_R_system sy 
   inner join v_GS_FIRMWARE firm on firm.ResourceID = sy.ResourceId 
   inner join v_GS_COMPUTER_SYSTEM CS on cs.ResourceID = sy.ResourceId 
   inner join v_GS_PC_BIOS Bio on bio.ResourceID = sy.ResourceId 
where firm.SecureBoot0 != 1 and cs.Model0 = 'HP EliteBook 840 G3' 
   and Cast(substring(bio.SMBIOSBIOSVersion0,9,6)as Numeric(4,2)) < 01.42

is this an issue with my comparison actually or an issue with the way I'm formatting?这实际上是我的比较问题还是我的格式问题?

Product:产品:

  • Microsoft SQL Server Standard (64-bit) Microsoft SQL Server 标准版(64 位)
  • Version: 2016 (v13.0.4604.0)版本:2016 (v13.0.4604.0)
  • Language: English (United States)语言:英语(美国)
  • Collation: SQL_Latin1_General_CP1_CI_AS排序规则:SQL_Latin1_General_CP1_CI_AS

简单的修复是try_cast()而不是cast()

try_Cast(try_Cast(substring(bio.SMBIOSBIOSVersion0, 9, 6)as Numeric(4,2)) as Int) as BiosVersion

You are most likely getting a leading space through your substring .您最有可能通过substring获得前导空格。 Try starting at 10 instead of 9. And make use of the where clause to limit you result set to only qualifying records尝试从 10 而不是 9 开始。并利用where子句将结果集限制为仅符合条件的记录

cast(substring(bio.SMBIOSBIOSVersion0,10,6) as numeric(4,2))

As an alternate to cast, you can coerce a 'numeric context' by adding 0.作为强制转换的替代方法,您可以通过添加 0 来强制“数字上下文”。

select ...
0+substring(bio.SMBIOSBIOSVersion0,9,6) as 'BiosVersion'

It may depend on your database flavor and version.这可能取决于您的数据库风格和版本。 Please specify.请明确说明。

It is possible that you have data where the specified substring is not numeric.您可能有数据,其中指定的子字符串不是数字。 In that case, try_cast will work (see other answer).在这种情况下, try_cast 将起作用(请参阅其他答案)。

Casting as int rounds to 1 , when it should be 01.43 based on what the substring gets.转换为 int 01.431 ,当它应该是01.43基于子字符串的获取。 When I remove the cast as int and just convert as numeric it truncates it 1.42 .当我删除转换为 int 并只转换为数字时,它会截断它1.42

First, the rounding problem.第一,四舍五入问题。 If you have more precision than two digits, you need to cast to a numeric type that includes all the possible digits, since any of those digits might turn out to be a tie-breaker for which way to round.如果您的精度超过两位数,则需要转换为包含所有可能数字的数字类型,因为这些数字中的任何一个都可能成为决定舍入方式的决胜局。 Once you complete that cast, use the ROUND() function to get the precision you actually need.完成该转换后,使用ROUND()函数获得您实际需要的精度。

You also seem to care about the leading 0 , at least for the SELECT clause.您似乎也关心前导0 ,至少对于SELECT子句。 I advise against that.我建议不要这样做。 Let client code worry about precise formatting for numbers and dates.让客户端代码担心数字和日期的精确格式。 But if you really need this, you want the FORMAT() function.但是如果你真的需要这个,你需要FORMAT()函数。 Again, use this after casting to numeric, but you can use it to replace ROUND() .同样,转换为数字使用它,但您可以使用它来替换ROUND() The import thing is this produces a string value again, rather than a numeric value, so only use it for the SELECT clause when the client program or report expects string data.重要的是这会再次产生一个字符串值,而不是一个数字值,所以只有当客户端程序或报告需要字符串数据时才将它用于SELECT子句。

Finally, there is a situation in the WHERE clause with some invalid casts.最后, WHERE子句中存在一些无效强制转换的情况。 The problem here is _you cannot force SQL Server to run conditions in the WHERE clause in any specific order.这里的问题是 _you 不能强制 SQL Server 以任何特定顺序运行 WHERE 子句中的条件。 Sql Server will process those filters in the order it believes is most efficient, even if some are needed sooner for logical reasons. Sql Server按照它认为最有效的顺序处理这些过滤器,即使出于逻辑原因需要更快地使用某些过滤器。

With that in mind, you should look at using TRY_CAST() in the WHERE clause.考虑到这一点,您应该考虑在 WHERE 子句中使用TRY_CAST() This will allow you to safely cast these substring to numeric values, even before other necessary filters are complete.这将允许您安全地将这些子字符串转换为数值,甚至在其他必要的过滤器完成之前。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM