0

我正在运行 sql server 2008 数据库,我在 Web 应用程序中使用以下查询,但为了调试错误,我直接在管理工作室中运行查询。

我收到以下错误 - 发生了无效的浮点操作。运行此查询时。

select p.Id as Id,  p.CatId as CatId, p.MetaName as MetaName ,p.Active as Active,p.HasChildren as HasChildren ,p.Mlevel as Mlevel ,p.ParentId as ParentId ,p.Type as Type, p.VOrder as VOrder, p.UrlOrder as UrlOrder, Count('*') as VCount 
from MetaDataValues as m 
left join MetaData as p on m.MetaDataId = p.Id
left join Adverts as a on m.AdvertId = a.Id
where a.Status = 1
and a.ExpDate > current_timestamp and 
m.AdvertId in 
(select m2.AdvertId from MetaDataValues as m2 left join MetaData as p2 on m2.MetaDataId = p2.Id where p2.MetaName = 'meta1' 
and m.AdvertId in (select m3.AdvertId from MetaDataValues as m3 left join MetaData as p3 on m3.MetaDataId = p3.Id where p3.MetaName = 'meta2' 
and m.AdvertId in (select m4.AdvertId from MetaDataValues as m4 left join MetaData as p4 on m4.MetaDataId = p4.Id where p4.MetaName = 'meta3' 
and m.AdvertId in (select ad9.Id from Adverts as ad9 where dbo.GetDist(ad9.X,ad9.Y,ad9.Z,52.9131514,-2.9313405) < 969))))
group by p.Id, p.CatId, p.MetaName,p.Active,p.HasChildren,p.Mlevel,p.ParentId,p.Type, p.VOrder, p.UrlOrder

为了解释导致问题的 GetDist 函数,如果我在子查询中将其向上移动到顶层,则查询运行正常?这不是理想的,因为构建此查询的代码是以某种方式编码的,我不想改变它。所以这是有效的查询,完全相同但顺序不同!

select p.Id as Id,  p.CatId as CatId, p.MetaName as MetaName ,p.Active as Active,p.HasChildren as HasChildren ,p.Mlevel as Mlevel ,p.ParentId as ParentId ,p.Type as Type, p.VOrder as VOrder, p.UrlOrder as UrlOrder, Count('*') as VCount 
from MetaDataValues as m 
left join MetaData as p on m.MetaDataId = p.Id
left join Adverts as a on m.AdvertId = a.Id
where a.Status = 1
and a.ExpDate > current_timestamp and 
m.AdvertId in 
(select m2.AdvertId from MetaDataValues as m2 left join MetaData as p2 on m2.MetaDataId = p2.Id where p2.MetaName = 'meta1' 
and m.AdvertId in (select ad9.Id from Adverts as ad9 where dbo.GetDist(ad9.X,ad9.Y,ad9.Z,52.9131514,-2.9313405) < 969)
and m.AdvertId in (select m3.AdvertId from MetaDataValues as m3 left join MetaData as p3 on m3.MetaDataId = p3.Id where p3.MetaName = 'meta2' 
and m.AdvertId in (select m4.AdvertId from MetaDataValues as m4 left join MetaData as p4 on m4.MetaDataId = p4.Id where p4.MetaName = 'meta3' )))
group by p.Id, p.CatId, p.MetaName,p.Active,p.HasChildren,p.Mlevel,p.ParentId,p.Type, p.VOrder, p.UrlOrder



GetDist code

USE [MVC]
GO
/****** Object:  UserDefinedFunction [dbo].[GetDist]    Script Date: 02/20/2013 17:05:00 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER FUNCTION [dbo].[GetDist] 
    (
    @xaxis float,
    @yaxis float,
    @zaxis float,
    @CenterLat float, 
    @CenterLon float
    )
RETURNS float
AS
    BEGIN

declare @CntXAxis float
declare @CntYAxis float
declare @CntZAxis float
declare @EarthRadius float 

set @EarthRadius = 3961
set @CntXAxis = cos(radians(@CenterLat)) * cos(radians(@CenterLon))
set @CntYAxis = cos(radians(@CenterLat)) * sin(radians(@CenterLon))
set @CntZAxis = sin(radians(@CenterLat))

return (@EarthRadius * acos( @XAxis*@CntXAxis + @YAxis*@CntYAxis + @ZAxis*@CntZAxis))


    END
4

2 回答 2

1

看起来 GetDist 可能正在计算一对纬度/经度值之间的距离。我有很多这方面的经验。像这样的大多数 GetDist 函数都使用反余弦函数“ACos”。此函数的参数限制在 -1 到 1 的范围内。如果您尝试传递此范围之外的值,您将在 SQL Server 中收到域错误。如果您的 GetDist 函数使用 CLR 函数,则错误将出现在您的 .net 代码中,并且消息会略有不同。

处理浮点数时,您必须注意奇怪的舍入问题。例如,如果您的计算将返回一个值 1.00000000000001,并且您将其传递给 ACos 函数,您将得到一个错误。

这里有很多猜测,我可能完全没有根据,但请考虑一下并花几分钟时间做一些研究。

根据您上面发布的 GetDist 函数,我建议进行一个相对较小的更改:

ALTER FUNCTION [dbo].[GetDist] 
    (
    @xaxis float,
    @yaxis float,
    @zaxis float,
    @CenterLat float, 
    @CenterLon float
    )
RETURNS float
AS
    BEGIN

declare @CntXAxis float
declare @CntYAxis float
declare @CntZAxis float
declare @EarthRadius float 
declare @Temp float

set @EarthRadius = 3961
set @CntXAxis = cos(radians(@CenterLat)) * cos(radians(@CenterLon))
set @CntYAxis = cos(radians(@CenterLat)) * sin(radians(@CenterLon))
set @CntZAxis = sin(radians(@CenterLat))

Set @Temp = @XAxis*@CntXAxis + @YAxis*@CntYAxis + @ZAxis*@CntZAxis
If @Temp > 1
    Set @Temp = 1
Else If @Temp < -1
    Set @Temp = -1

return (@EarthRadius * acos(@Temp))

    END

即使这不能解决您最初的问题,它至少可以保护您免受奇怪的浮点/精度问题。

于 2013-02-20T16:48:21.683 回答
0

问题是无效操作还是更像“将数据类型 varchar 转换为数字时出错”?当数值数据被存储为字符串时,这是一个相当普遍的问题。当字符串看起来正确时它可以工作,但在其他时候会失败。

的所有参数getDist()都是正确的类型吗?返回值是数字吗?

我猜想更高级别的过滤会过滤掉导致问题的错误值。

于 2013-02-20T15:27:34.207 回答