存储过程是声明性的还是命令式的?

时间:2015-07-11 05:26:32

标签: sql-server tsql stored-procedures

请先阅读以下示例。

我有一个名为Product的数据库表,该表有一个名为Id的列,其数据类型为INT。

我正在编写一个添加新产品的存储过程。数据库的一个规则是在添加新产品时,为其分配的id必须是从1开始的最小整数,当然id是唯一的。

例如,如果现有ID为1,2,3,4,5,6,则新产品的ID为7.但如果现有ID为1,2,3,5,6,8新的id将是4。

这是我的尝试:

DECLARE @newId INT
SET @newId = 1
WHILE EXISTS (SELECT * FROM Product WHERE Product.id = @newId)
    SET @newId = @newId + 1
/*Then use this @newId to insert new item into table Product*/

但我的朋友告诉我这段代码效率不高,因为会在每次迭代时评估while循环条件中的查询。

这是他代码的一部分:

DECLARE @currentId INT, @lastId INT, @newId INT
SET @lastId = 0

DECLARE idCursor CURSOR FOR SELECT Product.id FROM Product ORDER BY Product.id
OPEN idCursor
FETCH NEXT FROM idCursor INTO @currentId

WHILE @@FETCH_STATUS = 0
    BEGIN
        IF @currentId <> @lastId + 1
            BREAK

        SET @lastId = @currentId
        FETCH NEXT FROM idCursor INTO @currentId
    END

SET @newId = @lastId + 1
CLOSE idCursor
DEALLOCATE idCursor
/*Then use this @newId to insert new item into table Product*/

在我看来,SQL是一种声明性语言,无论我们编写什么代码,DBMS都会重新排列它们以实现良好的执行计划,因此我为DBMS提供优化部分并尝试保持简单和可读性。此外,找到新的id只是存储过程的一小部分。

但是在我朋友看来,在编写存储过程时,它变成了一种命令式语言,代码作者负责代码效率。他说我所做的就是让事情变得简单,而不是系统。

所以我的问题是:

  1. 在编写存储过程时,SQL是否仍然是声明性的?或者它在中间的某个地方?

  2. 在编写商店程序时,什么被认为是更好的做法:保持简单或完全照顾他们的效率?

1 个答案:

答案 0 :(得分:2)

我认为每种语言都是你所谓的陈述性和命令性的混合。

一个人可以用任何语言编写错误代码(或优秀代码)。在我看来,如果你想编写优秀的代码,你必须知道你编写代码的语言的优点和缺点。

由于所涉及的循环,您显示的两个代码块都将表现不佳。针对此问题的基于集合的方法看起来像这样:

Declare @NewId Int

Select  Top 1 @NewId = RowId
From    (
        Select  Id, Row_Number() Over (Order By Id) As RowId
        From    Product
        ) As A
Where   Id <> RowId
Order By RowId

Select @NewId

TSQL存在涉及循环的弱点。在99.9%的情况下,你最好避免循环。