【问题标题】:Extract values > 1.00 from database从数据库中提取大于 1.00 的值
【发布时间】:2015-11-03 14:49:18
【问题描述】:

我对 SQL 很陌生;我正在努力从数据库中提取数据。我正在尝试提取所有 Au 值 > 1.00 的记录。 AttributeValue 列是NVARCHAR

这是我尝试过的:

SELECT TOP 1000 [Id]
      ,[DHGeochemistryId]
      ,[AttributeColumn]
      ,[AttributeValue]
      ,[ModifiedDate]
      ,[ModifiedBy]
      ,[MRTDetailId]
  FROM [DRILLHOLES_Export].[dbo].[DHGeochemistryAttr]
      WHERE [AttributeValue] > 1.00 and [AttributeColumn] = 'Au'

软件抛出以下错误:

消息 8115,第 16 级,状态 8,第 2 行 将 nvarchar 转换为数字数据类型时出现算术溢出错误。

我尝试转换为数字:

SELECT TOP 1000 [Id]
      ,[DHGeochemistryId]
      ,[AttributeColumn]
      ,[AttributeValue] 
      ,[ModifiedDate]
      ,[ModifiedBy]
      ,[MRTDetailId]
  FROM [DRILLHOLES_Export].[dbo].[DHGeochemistryAttr]
  SET myValue = CASE WHEN ISNUMERIC(AttributeValue)=1 THEN CAST(AttributeValue AS float)
      ELSE 0 END)
      WHERE [AttributeValue]  > 1.00 and [AttributeColumn] = 'Au'

软件抛出以下错误:

消息 102,级别 15,状态 1,第 10 行 '=' 附近的语法不正确。 (第 10 行是“SET”命令)

我正在使用 SQL Server 2014,希望能得到一些帮助。

【问题讨论】:

  • 你不能在 SELECT 中做 SET
  • SET 语句不在 SELECT 语句中,而是一个单独的语句(我认为是无意的)。与 CASE... 组合会导致错误。解决该错误后,该错误将转到本身不是有效语句的 WHERE 语句。 CONVERT 或 CAST 应该可以进行比较,但可能需要检查数值是否为数字,具体取决于 AttributeValue 的可能值。

标签: sql sql-server sql-server-2014


【解决方案1】:

第一个语句抱怨因为AttributeValue 不是数字列。不过你可以CAST它:

WHERE CAST([AttributeValue] AS FLOAT)  > 1.00

但如果其中的任何值不是数字,则可能会出错。所以你可以在投之前使用ISNUMERIC

WHERE ISNUMERIC([AttributeValue]) = 1
AND CAST([AttributeValue] AS FLOAT)  > 1.00

SQL Server 足够聪明,可以将逻辑短路,因此如果 WHERE 子句的第一部分返回 false,它就不会尝试 CAST

【讨论】:

  • #multi-lingual-problems
  • @Tanner 多语言的危险(这是一个词吗?应该是!)
  • 在我的测试中,如果 nvarchar 是字符串,则强制转换仍然会失败。我不太确定 SQL 是否像您希望的那样聪明。
  • 虽然 Sql Server 足够聪明,可以短路,但这需要优先级列表中的一秒钟来匹配索引和其他性能考虑,这样你会经常发现你的 cast() 在你的 IsNumeric 之前运行() 过滤器。
  • @JoelCoehoorn 有趣的是,有没有办法强制优先级呢?除了子查询?
【解决方案2】:

我仍然相信它会出错,但你可以把它放在 try...catch 中,你应该没问题。这是一个示例:

create table #test (
    attValue nvarchar(100),
    attCol nvarchar(100))

insert into #test (attValue, attCol)
select '.99', 'Au'
union
select '1.1', 'Au'
union
select 'hello', 'Au'
union
select '1.01', 'Au'
union
select '1.2', 'Au'
union
select '1.5', 'Au'

begin try
    ;with atts (AttributeValue, AttributeCol) as
    ( 
    select convert(float, x.attValue) as aVal, x.attCol
      from (
            select attValue, attCol
              from #test
             where IsNumeric(attValue) = 1
           ) x
    )
    select * from atts
    where AttributeValue > cast(1.0 as float)
end try
begin catch
    -- do nothing
end catch

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 2017-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多