0

我写了一个存储过程。现在我明白了,这是非常糟糕的表现。我认为这是因为 while 循环。

ALTER PROCEDURE [dbo].[DeleteEmptyCatalogNodes] 
@CatalogId UNIQUEIDENTIFIER,
@CatalogNodeType int = null
AS
BEGIN
SET NOCOUNT ON;

DECLARE @CID UNIQUEIDENTIFIER
DECLARE @CNT int

SET @CID = @CatalogId
SET @CNT = @CatalogNodeType

DELETE cn FROM CatalogNodes cn
LEFT JOIN CatalogNodes as cnj on cn.CatalogNodeId = cnj.ParentId
LEFT JOIN CatalogArticles as ca on cn.CatalogNodeId = ca.CatalogNodeId
WHERE cn.CatalogId = @CID
AND cnj.CatalogNodeId IS NULL
AND ca.ArticleId IS NULL
AND (cn.CatalogNodeType = @CNT OR @CNT IS NULL)

WHILE (@@ROWCOUNT  > 0)
BEGIN
    DELETE cn FROM CatalogNodes cn
    LEFT JOIN CatalogNodes as cnj on cn.CatalogNodeId = cnj.ParentId
    LEFT JOIN CatalogArticles as ca on cn.CatalogNodeId = ca.CatalogNodeId
    WHERE cn.CatalogId = @CID
    AND cnj.CatalogNodeId IS NULL
    AND ca.ArticleId IS NULL
    AND (cn.CatalogNodeType = @CNT OR @CNT IS NULL)
END
END

你们中的任何人都可以给我一个关于如何更“设置”的提示吗?

非常感谢!

编辑评论和答案:

这些表是这样构建的:

目录节点:

CatalogNodeId|ParentId|Name
1|NULL|Root
2|1|Node1
3|1|Node2
4|2|Node1.1

目录文章:

CatalogNodeId|Name
3|Article1
3|Article2
3|Article3

调用我的 SP 后,必须删除 Node1 和 Node1.1。在第一个删除语句中,Node1.1 将被删除。在 While 循环中,Node1 将被删除。我希望我的问题现在更容易理解,它是一个树结构。

4

4 回答 4

1

您只是不需要 WHILE 部分,因为所有匹配的行都将从第一个 DELETE 语句中删除

于 2013-11-06T11:37:03.720 回答
1

你的循环没有做任何事情......如果有任何符合你的 where 条件的记录,第一个删除语句将删除一些记录......所以 @@rowcount 将大于 0 但不会有任何记录在循环内的第二个删除语句中删除。还是我错过了什么?

无论如何,我不认为连续两次执行删除对性能有很大影响...如果您查看查询计划,您应该会看到它...

于 2013-11-06T11:41:02.610 回答
0

在我看来,这样做的一种方法是创建一个表变量并将所有必须删除的元素放在那里,并使用 i 和 join 在一个语句中进行删除。

于 2013-11-06T11:34:01.740 回答
0

CatalogNodes 是您要删除的内容。创建一个选择来拉出您想要摆脱的所有 CatalogNode。如果有东西被外键约束绑定,请先删除它们,最后一旦它们都摆脱了删除 CatalogNodes。临时表在这里可能很有用,因为它们保存在内存中。

于 2013-11-06T11:49:13.220 回答