存储过程执行顺序

时间:2015-08-06 08:44:12

标签: sql sql-server sql-server-2008 function stored-procedures

CREATE PROCEDURE [dbo].[uspGetLogs]
(
    @StartDate  DATETIME,
    @EndDate    DATETIME
)
AS
SELECT
    sl.ID,
    LOG10(sl.Value)
FROM
    dbo.SampleList sl
INNER JOIN
    (
        SELECT
            ID,
            RANK() OVER(PARTITION BY Codec ORDER BY TimeStampUTC DESC, d.ID DESC) ranked
        FROM
            dbo.SampleList 
        WHERE
            ListDate BETWEEN @StartDate AND @EndDate
    ) r
ON
    r.ID        =   sl.ID   AND
    r.ranked    =   1

我用@StartDate = 2014-01-29 @EndDate = 2015-03-14尝试了这个存储过程。

并收到此错误

  

发生了无效的浮点运算

出错的原因"发生了无效的浮点运算"是数学函数的无效用法。

SELECT LOG10(-3);
SELECT LOG10(0);

如果运行上述功能,则会返回错误。

我能够从整个表集中获取值小于1的单个值。但是该值的ListDate是2015-03-14,因此不应该包括它,因为它没有被存储过程中传递的日期范围转换。

因此,在加入和过滤具有日期范围的数据集之前,存储过程似乎首先在整个集合中执行该函数。

这是预期的吗?

2 个答案:

答案 0 :(得分:0)

我不认为有一个保证点可以执行函数,所以我的答案取决于查询计划,取决于优化器决定执行函数的“早期” - 在连接之前或之后。要确保仅对有效值执行该功能,您可以更改为:

CASE WHEN sl.Value < 1 THEN 0 ELSE LOG10(sl.Value) END

答案 1 :(得分:0)

我认为这里可能存在数据问题,因为代码的基本逻辑不会导致问题,请参阅以下示例:

CREATE TABLE #temp1 ( id INT, val INT )
CREATE TABLE #temp2 ( id INT, val INT )

INSERT  INTO #temp1 ( id, val )
VALUES  ( 1, 1 ), ( 2, 10 ), ( 3, -1 ) -- Negative value for id=3 exculded in subquery

INSERT  INTO #temp2 ( id, val )
VALUES  ( 1, 1 ), ( 2, 10 ), ( 3, 20 ) 

SELECT  t1.id ,
        LOG10(t1.val) AS Val
FROM    #temp1 t1
        INNER JOIN ( SELECT * ,
                            RANK() OVER ( PARTITION BY id ORDER BY val ) ranked
                     FROM   #temp2
                     WHERE  id BETWEEN 1 AND 2  -- excludes id 3
                   ) t2 ON t2.id = t1.id
                           AND t2.ranked = 1

DROP TABLE #temp1
DROP TABLE #temp2

<强>产地:

id  val
1   0
2   1

如果您将BETWEEN子句修改为WHERE id BETWEEN 1 AND 3,则会看到错误,因为包含了负值。

所以我会对数据进行三重检查,如果还有问题,请尝试发布一个重新创建问题的小样本。