请先阅读以下示例。
我有一个名为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只是存储过程的一小部分。
但是在我朋友看来,在编写存储过程时,它变成了一种命令式语言,代码作者负责代码效率。他说我所做的就是让事情变得简单,而不是系统。
所以我的问题是:
在编写存储过程时,SQL是否仍然是声明性的?或者它在中间的某个地方?
在编写商店程序时,什么被认为是更好的做法:保持简单或完全照顾他们的效率?
答案 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%的情况下,你最好避免循环。