偶尔会发生:“将数据类型nvarchar转换为float时出错”

时间:2013-07-04 22:21:17

标签: sql sql-server casting

这是我的SQL查询:

SELECT (CAST(CAST([rssi1] AS float) AS INT))*-1, CONVERT(VARCHAR(10), [date], 110)
FROM history
WHERE id IN
(
    SELECT TOP 8 id
    FROM history
    WHERE ([siteName] = 'CAL00022') 
    ORDER BY id DESC
)
ORDER BY date ASC

大多数时候,它运作正常。 有时,我收到此错误:

Server Error in '/' Application.
Error converting data type nvarchar to float.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 
Exception Details: System.Data.SqlClient.SqlException: Error converting data type nvarchar to float.

表格如下:

enter image description here

2 个答案:

答案 0 :(得分:5)

当你不信任你所选择的引擎中的实数的处理以至于你将它们存储在nvarchars中时,真可怕!我已经找回了足够的1.000000000001来表示同情,但也不太喜欢这个解决方案。

根据约翰的回答,识别您的无效记录是必要的,但无论如何您可能无法亲自对此做任何事情。您提供的是SELECT语句,有时会失败,因此,我解决了这个失败。

在尝试投射之前检查rssi1的值是否为数字可以避免您有时得到的错误。您可以排除rssi1不是数字的那些记录:

SELECT
  (CAST(CAST([rssi1] AS float) AS INT))*-1,
  CONVERT(VARCHAR(10), [date], 110)
FROM history
WHERE id IN
(
    SELECT TOP 8 id
    FROM history
    WHERE ([siteName] = 'CAL00022') 
    ORDER BY id DESC
)
AND ISNUMERIC([rssi1]) = 1
ORDER BY date ASC

或按原样呈现(每个都有自己的限制):

SELECT
  CASE WHEN ISNUMERIC([rssi1]) = 1 THEN CAST((CAST(CAST([rssi1] as float) as int))*-1 as nvarchar) ELSE [rssi1] /* Or choose a value to default to */ END, 
  CONVERT(VARCHAR(10), [date], 110)
FROM history
WHERE id IN
(
    SELECT TOP 8 id
    FROM history
    WHERE ([siteName] = 'CAL00022') 
    ORDER BY id DESC
)
ORDER BY date ASC

答案 1 :(得分:2)

我同意Blorgbeard上面的评论;我猜你在哪里显示CAL00022,这实际上是一个参数,所以我建议自己编写一个小程序来解析历史表中不同的sitename值,在rssi1中寻找不能正确转换的值;

这样的事情:(这是一个简单的工作,应该找到存在不良数据的网站名称 - 尽管你需要自己检查网站名称的实际数据,以确定哪些是不正确的。

(注意:这有点乱,我只是快速输入 - 它可能比这更好)

CREATE PROCEDURE ParseHistoryData 
AS BEGIN
  SET NOCOUNT ON;

  declare @site varchar(20);
  select distinct sitename into #tmp from history;
  create table #bad (sitename varchar(20));

  while (select COUNT(*) from #tmp) > 0 begin
    select @site = MIN(sitename) from #tmp;
    delete #tmp where sitename = @site;

    select rssi1 into #num from history where sitename = @site;
    select CAST(CAST(rssi1 AS float) AS INT) as casted into #err from #num;

    if @@ERROR <> 0 
      insert #bad values (@site);

    drop table #num;
    drop table #err;
  end 

  select sitename from #bad order by 1;
END