SQLServer:从数据类型 varchar 转换为 numeric 时出错。

1.工作要求

计算某两个经纬度距离

在这里插入图片描述

2.遇到问题

从数据类型 varchar 转换为 numeric 时出错。

3.解决问题

项目版本较老,使用SQLServer 2012
计算距离需执行视图,如下:

SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
ALTER  view
vi_ordensilingtranslist
as
SELECT a.csendlongitude,csendlatitud,ilongitude,ilatitude,cmclat,cmclng,a.cgroupcontractname ,a.censilingcode ,a.ccorpname ,a.ccustomername ,a.dfhtime ,a.cmassifname ,a.cjhname ,a.izttime ,a.cinvname ,a.imweight ,a.ipweight ,a.iweight ,a.istarchvalue ,a.iqualityper  ,b.iklfracture,a.ccarcode,a.carcode 
,CASE WHEN a.cmassifname='无地块' OR ISNULL(a.csendlongitude,'')=''  OR ISNULL(c.ilatitude,'') = ''  THEN '无地块或无发货坐标无法计算' ELSE CAST( ROUND(dbo.fnGetDistance(a.csendlongitude,a.csendlatitud,c.ilatitude,c.ilongitude)/1000,2,0) AS VARCHAR(250)) END AS cfhdis 

,CASE WHEN a.cmassifname='无地块' OR ISNULL(d.cmclat,'')=''OR ISNULL(c.ilongitude,'') = '' OR ISNULL(a.cmassifname,'') = ''  THEN '无地块或牧场未设置坐标无法计算' ELSE CAST( ROUND(dbo.fnGetDistance(c.ilongitude,c.ilatitude,d.cmclat,d.cmclng)/1000,2,0) AS VARCHAR(250)) END AS cdkmcdis

,CASE WHEN  ISNULL(a.csendlongitude,'')=''OR ISNULL(d.cmclat,'')='' THEN '无发货位置或无牧场坐标无法计算' ELSE CAST( ROUND(dbo.fnGetDistance(a.csendlongitude,a.csendlatitud,d.cmclat,d.cmclng)/1000,2,0) AS VARCHAR(250)) END AS cfhmcdis
FROM dbo.Op_EnsilingTrans a WITH(NOLOCK)  LEFT JOIN dbo.op_sensorytest b WITH(NOLOCK) ON a.censilingcode=b.clzcode 
LEFT JOIN dbo.op_massif c WITH(NOLOCK) ON a.cmassifcode=c.cmassifcode
LEFT JOIN dbo.Sys_AccountSet d WITH(NOLOCK) ON a.ccorpcode=d.cztcode
WHERE ISNULL(a.iweight,0)>0


GO

根据经纬度计算公里数函数如下

SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE FUNCTION [dbo].[fnGetDistance](@sendlog VARCHAR(50), @sendlat VARCHAR(50), @lat VARCHAR(50), @log VARCHAR(50))
RETURNS FLOAT
AS
BEGIN

    DECLARE @a GEOGRAPHY;
    DECLARE @b GEOGRAPHY;
	DECLARE @distance REAL

    DECLARE @atxt VARCHAR(50)='';
    DECLARE @btxt VARCHAR(50)='';

    SET @atxt ='POINT('+@sendlog+' '+@sendlat+')';
    SET @btxt='POINT('+@log+' '+@lat+')';

    SET @a = geography::STGeomFromText(@atxt, 4326);
    SET @b = geography::STGeomFromText(@btxt, 4326);

    -- 计算距离并将结果存入输出参数
    SET @distance = ROUND(@a.STDistance(@b), 1); -- 将距离转换为公里并进行四舍五入
	RETURN @distance
END
GO

执行视图,报错:

消息 8114,级别 16,状态 5,第 1 行
从数据类型 varchar 转换为 numeric 时出错。

错误原因:isnull的使用问题
错误点:
在视图内,ISNULL(a.csendlongitude,'')='' OR ISNULL(c.ilatitude,'') = '',这里a表,即Op_EnsilingTrans表经纬度字段类型为nvarchar,而c表,即op_massif表经纬度字段为decimal,

在这里插入图片描述

在这里插入图片描述

错就错在decimal,
下面是正确写法:

SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
ALTER  view
vi_ordensilingtranslist
as
SELECT a.csendlongitude,csendlatitud,ilongitude,ilatitude,cmclat,cmclng,a.cgroupcontractname ,a.censilingcode ,a.ccorpname ,a.ccustomername ,a.dfhtime ,a.cmassifname ,a.cjhname ,a.izttime ,a.cinvname ,a.imweight ,a.ipweight ,a.iweight ,a.istarchvalue ,a.iqualityper  ,b.iklfracture,a.ccarcode,a.carcode 
,CASE WHEN a.cmassifname='无地块' OR ISNULL(a.csendlongitude,'')=''  OR ISNULL(c.ilatitude,0) = 0  THEN '无地块或无发货坐标无法计算' ELSE CAST( ROUND(dbo.fnGetDistance(a.csendlongitude,a.csendlatitud,c.ilatitude,c.ilongitude)/1000,2,0) AS VARCHAR(250)) END AS cfhdis 

,CASE WHEN a.cmassifname='无地块' OR ISNULL(d.cmclat,'')=''OR ISNULL(c.ilongitude,0) = 0 OR ISNULL(a.cmassifname,'') = ''  THEN '无地块或牧场未设置坐标无法计算' ELSE CAST( ROUND(dbo.fnGetDistance(c.ilongitude,c.ilatitude,d.cmclat,d.cmclng)/1000,2,0) AS VARCHAR(250)) END AS cdkmcdis

,CASE WHEN  ISNULL(a.csendlongitude,'')=''OR ISNULL(d.cmclat,'')='' THEN '无发货位置或无牧场坐标无法计算' ELSE CAST( ROUND(dbo.fnGetDistance(a.csendlongitude,a.csendlatitud,d.cmclat,d.cmclng)/1000,2,0) AS VARCHAR(250)) END AS cfhmcdis
FROM dbo.Op_EnsilingTrans a WITH(NOLOCK)  LEFT JOIN dbo.op_sensorytest b WITH(NOLOCK) ON a.censilingcode=b.clzcode 
LEFT JOIN dbo.op_massif c WITH(NOLOCK) ON a.cmassifcode=c.cmassifcode
LEFT JOIN dbo.Sys_AccountSet d WITH(NOLOCK) ON a.ccorpcode=d.cztcode
WHERE ISNULL(a.iweight,0)>0


GO

4.结论

建表时注意字段类型统一

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值