重工电子论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 7042|回复: 0
打印 上一主题 下一主题

[数据库] sql加浮点数的问题及其解决方法!

[复制链接]

299

主题

684

帖子

7009

积分

学生管理组

Rank: 8Rank: 8

积分
7009
跳转到指定楼层
楼主
发表于 2016-10-25 00:50:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 李维强-15级 于 2016-10-25 01:12 编辑

由于在服务器windows事件查看器里面,发现.net应用程序池老是不定时报错,报错位置就是SQL执行的地方,

问题很简单 例子就拿现成的来说

以下是我执行的SQL语句:
[SQL] syntaxhighlighter_viewsource syntaxhighlighter_copycode
begin 
select * into #myTempTable FROM (select '687216083021602' AS GPSIMEI,108.234048 as lng,22.844226 as lat,0 as speed,'2016-10-24 01:31:14' as serverTime,'20161024013114000' as GPSinformationID,'设备不正常 device_info=3' as log union all select '687216083021560' AS GPSIMEI,108.487501 as lng,22.823695 as lat,69 as speed,'2016-10-24 01:31:14' as serverTime,'20161024013114001' as GPSinformationID,'正常' as log ) a;

UPDATE a SET a.Latitude=b.lat ,a.Longitude=b.lng,a.UpdateTime=b.serverTime,a.Log='state='+b.log+'&speed='+CONVERT(VARCHAR(20),CONVERT(DECIMAL(20,7),b.speed)) FROM T_M_GPSInformationTemp a INNER JOIN #myTempTable as b ON a.gpsimei=b.gpsimei;

drop table #myTempTable;

end

在上面这个语句执行update的时候,会引发触发器,以下是触发器代码
[SQL] syntaxhighlighter_viewsource syntaxhighlighter_copycode
BEGIN

INSERT INTO T_M_GPSInformation (GPSInformationID,GPSIMEI,Longitude,Latitude,UpdateTime,speed,Log) 
SELECT 
m.GPSinformationID,i.GPSIMEI,i.Longitude,i.Latitude,m.serverTime,m.speed,i.log
from deleted d INNER JOIN inserted i ON d.GPSIMEI=i.GPSIMEI
INNER JOIN #myTempTable m ON m.GPSIMEI=d.GPSIMEI
where
ABS(6378137*ACOS(cos(i.Latitude/57.2958)*cos(d.Latitude/57.2958)*cos((d.Longitude-i.Longitude)/57.2958) + sin(d.Latitude/57.2958)*sin(i.Latitude/57.2958)))>30 

END

那么执行上面的SQL语句就会报错,错误显示“[SQL Server]出现无效的浮点操作。”
问题的关键就是出在这个ACOS(cos(i.Latitude/57.2958)*cos(d.Latitude/57.2958)*cos((d.Longitude-i.Longitude)/57.2958) + sin(d.Latitude/57.2958)*sin(i.Latitude/57.2958))里面,
这里还是多谢周老师提醒,不然我仅到都试不出来哈。
==============================================================================
下面是原因分析
我调试过后,跟踪发现 执行上面的SQL,发现 但是这一段cos(i.Latitude/57.2958)*cos(d.Latitude/57.2958)*cos((d.Longitude-i.Longitude)/57.2958) 算出来是0.849536178179997,而另一段sin(d.Latitude/57.2958)*sin(i.Latitude/57.2958)算出来是0.150463821820003 按理说 这两个数相加 就是1,那么最后取acos(1)=0;这个是正常的,但是在SQL SERVER里面,两个这种长度的带小数的数据相加,加起来不是1,可能是1.00000几而acos(x)的定义域范围是[-1,1],所以就超过了该定义域范围,导致报错。
但是如果我们只是执行算着两个值相加,SQL也会正常显示出1,如下面的语句
[SQL] syntaxhighlighter_viewsource syntaxhighlighter_copycode
select  cos(i.Latitude/57.2958)*cos(d.Latitude/57.2958)*cos((d.Longitude-i.Longitude)/57.2958) + sin(d.Latitude/57.2958)*sin(i.Latitude/57.2958) 
from deleted d INNER JOIN inserted i ON d.GPSIMEI=i.GPSIMEI
--这种正常输出1

但是 在前面加个acos的话,就直接报错了,肯定就是超出范围了
[SQL] syntaxhighlighter_viewsource syntaxhighlighter_copycode
select  acos(cos(i.Latitude/57.2958)*cos(d.Latitude/57.2958)*cos((d.Longitude-i.Longitude)/57.2958) + sin(d.Latitude/57.2958)*sin(i.Latitude/57.2958)) 
from deleted d INNER JOIN inserted i ON d.GPSIMEI=i.GPSIMEI
--这种就报浮点数错误



好了 只要找到原因,问题就好解决。在触发器里面来个case when 即可
[SQL] syntaxhighlighter_viewsource syntaxhighlighter_copycode
INSERT INTO T_M_GPSInformation (GPSInformationID,GPSIMEI,Longitude,Latitude,UpdateTime,speed,Log) 
SELECT 
m.GPSinformationID,i.GPSIMEI,i.Longitude,i.Latitude,m.serverTime,m.speed,i.log
from deleted d INNER JOIN inserted i ON d.GPSIMEI=i.GPSIMEI
INNER JOIN #myTempTable m ON m.GPSIMEI=d.GPSIMEI
where
ABS(6378137*ACOS(
case when (cos(i.Latitude/57.2958)*cos(d.Latitude/57.2958)*cos((d.Longitude-i.Longitude)/57.2958) + sin(d.Latitude/57.2958)*sin(i.Latitude/57.2958))>=1 then 1  ELSE (cos(i.Latitude/57.2958)*cos(d.Latitude/57.2958)*cos((d.Longitude-i.Longitude)/57.2958) + sin(d.Latitude/57.2958)*sin(i.Latitude/57.2958)) END
))>30 


在以上代码中 那个>=1是关键,因为 前面说了 如果单独这么算,是正常的,但是套在acos里面就不正常了
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|cqutlab ( 渝ICP备15004556号

GMT+8, 2024-12-22 16:54 , Processed in 0.176702 second(s), 29 queries .

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表