与EXEC相比,使用exec sp_executesql执行存储过程的结果不同

时间:2013-08-16 14:03:51

标签: sql sql-server entity-framework stored-procedures

我在数据库中有一个表,其中包含一些具有纬度和经度的邮政编码,例如:

Id  PostCode    Latitude         Longitude
1   ll29 8ht    53.2973289489746    -3.72970223426819

该表由MVC代码优先应用程序生成, 纬度和经度数据类型是真实的

我有一个存储过程,它将searchLatitude和searchLongitude作为输入,然后计算距离:

CREATE PROCEDURE [dbo].[StockistSearch] 
    @searchLat float = 0,
    @searchLng float = 0
AS
BEGIN
    SET NOCOUNT ON;
SELECT top 40 
s.Id as Id,
a.Company as Company,
a.FirstName as FirstName,
a.LastName as LastName,
a.Address1 as Address1,
a.Address2 as Address2,
a.City as City,
a.ZipPostalCode as ZipPostalCode,
a.PhoneNumber as PhoneNumber,
a.FaxNumber as FaxNumber,
a.Email as Email,
s.latitude as Latitude,
s.longitude as Longitude,
( 3959 * acos( cos( radians(@searchLat) )
* cos( radians( s.latitude ) )
* cos( radians( s.longitude )
- radians(@searchLng) )
+ sin( radians(@searchLat) )
* sin( radians( s.latitude ) ) ) )
AS Distance
FROM Stockist s, Customer c, Address a
where s.CustomerId = c.Id
and c.ShippingAddress_Id = a.Id     
ORDER BY distance
END

如果我通过SQL Server管理工作室执行此操作,它将执行以下操作:

DECLARE @return_value int

EXEC    @return_value = [dbo].[StockistSearch]
    @searchLat = 53.29,
    @searchLng = -3.72

SELECT  'Return Value' = @return_value

GO

正确返回距离(0.645英里)

但是,通过应用程序执行时使用:

var result = this.Database.SqlQuery<TEntity>(commandText, parameters).ToList();

根据跟踪,执行:

exec sp_executesql N'StockistSearch',N'@searchLat float,@searchLng float',@searchLat=53.29,@searchLng=-3.72

导致计算距离的结果完全不同(和错误),(返回距离3688.96英里!)

我在调试中逐步完成了代码并正确输入了参数,并确认exec sp_executesql在SQL服务器管理工​​作室中直接运行EXEC时给出了不同的结果

我完全不知道为什么会发生这种情况,虽然存储过程似乎运行正常,但通过应用程序显示的结果完全错误。

请允许有人在我发疯之前给我一些建议!!

由于

更新

感谢所有评论到目前为止,感谢@McKay,我已经将其缩小到忽略输入参数时从exec sp_executesql调用并使用默认值0表示纬度和经度。如果我删除默认值,我收到错误:

Procedure or function 'StockistSearch' expects parameter '@searchLat', which was not supplied.

SQL查询

exec sp_executesql N'StockistSearch', N'@searchLat real, @searchLng real',@searchLat=53.29,@searchLng=-3.72

这个sql是由实体框架自动生成的(代码优先的MVC EF目前不支持存储过程但应该能够使用DbContext中的以下内容查询存储过程:)

var result = this.Database.SqlQuery<TEntity>(commandText, parameters).ToList();

非常感谢任何进一步的帮助

固定: - )

致电:

var result = this.Database.SqlQuery<TEntity>(commandText, parameters).ToList();

命令文本必须附加参数

commandText = "StockistSearch @searchLat,@searchLng"

所以生成的sql是;

exec sp_executesql N'StockistSearch @searchLat,@searchLng', N'@searchLat real, @searchLng real',@searchLat=53.29,@searchLng=-3.72

它现在接受输入参数并计算正确的距离

4 个答案:

答案 0 :(得分:1)

这种不同的数字让我觉得它可能是使用默认值的东西?你有没有取出默认值?

也许您也可以将参数添加到选择中,以确保获得您期望的结果。

SELECT top 40 
    @searchLatitude,
    @searchLongitude,
    l.Id as Id,
    l.Postcode as Postcode,
    l.latitude as Latitude,
    l.longitude as Longitude,

这可能有助于您的调试过程。

答案 1 :(得分:0)

您是否有两个存储过程,一个名为DistanceSearch,一个名为StockistSearch?它看起来就像你的代码。你确定正在调用正确的程序吗?

答案 2 :(得分:0)

你的过程中出错。

( 3959 * acos( cos( radians(@searchLatitude) )
* cos( radians( l.latitude ) )
* cos( radians( l.longitude )
- radians(@searchLongitude) )
+ sin( radians(@searchLat) )
* sin( radians( l.latitude ) ) ) )

一个使用@searchLat,一个使用@searchLatitude

等等,proc似乎选择了表,并没有返回值,但是你的执行期望输出参数?

答案 3 :(得分:0)

不同之处在于它的名称。

您的SSMS调用返回返回值。

您的sp_executesql调用会返回数据集。我猜第40个最近的库存商是3688.96英里远