使用游标时从游标中删除一行

Delete a row from cursor while using the cursor

我有一个游标遍历我的临时 table。在迭代时,我想检查一个条件并根据条件删除一些行(我将删除迭代器尚未到达的行)。

我尝试从游标迭代的 table 中删除行(因此临时 table),但没有成功,我可以在 Messages panel 中看到它们(我打印它姓名)。

是否可以从 table 游标在 SQL-Server 中迭代的行中删除行?如果不是,我有什么选择?

基本上,temp table 包含树状数据,并且根据列的值,如果它不符合条件,我需要删除它的子项(和孙子等) .

DECLARE cursor_name CURSOR
FOR (SELECT * FROM #test) ORDER BY Path


DECLARE
    @Id AS INTEGER,
    @Name AS VARCHAR(MAX),
    @Path AS VARCHAR(MAX)

OPEN cursor_name;
FETCH NEXT FROM cursor_name INTO @Id, @Name, @Path;
PRINT @Name

DELETE FROM #test 
WHERE
    Path LIKE '%76939%'

    WHILE @@FETCH_STATUS = 0  
    BEGIN
        FETCH NEXT FROM cursor_name INTO @Id, @Name, @Path;
        PRINT @Name
    END;

CLOSE cursor_name;
DEALLOCATE cursor_name;

#编辑

这里是关于这个问题的更多细节。我们的数据结构类似于树列表。每个项目都有多个列,这些列指定行的某些特征。这些特征可以遗传也可以不遗传(如果InheritanceFlag为1则为遗传,为0则为不遗传)。

因此,当用户进行更改时,我们需要根据上述标志将更改传播给其子项。如果其子项之一将 InheritanceFlag 设置为 0,则它不会更改其值,其子项也不会。我想使用路径删除带有光标的那些行。

这是我的数据。 ParentID 是其父级的 ID。在这种情况下,假设我们正在编辑项目 76938,因此我们正在查看它的子项。 ToEdit 列是我要创建的;有了它,我可以过滤行,直接把特征列改成新值

+-------+----------+-------+-------------------------+-----------------+--------+
| ID    | ParentID |  Name |           Path          | InheritanceFlag | ToEdit |
+-------+----------+-------+-------------------------+-----------------+--------+
| 76938 | NULL     |   1   |         (76938)         | 1               | X      |
+-------+----------+-------+-------------------------+-----------------+--------+
| 76942 | 76938    |  1.1  |     (76938)\(76942)     | 1               | 1      |
+-------+----------+-------+-------------------------+-----------------+--------+
| 76952 | 76942    | 1.1.1 | (76938)\(76942)\(76952) | 0               | 0      |
+-------+----------+-------+-------------------------+-----------------+--------+
| 76961 | 76942    | 1.1.2 | (76938)\(76942)\(76961) | 1               | 1      |
+-------+----------+-------+-------------------------+-----------------+--------+
| 76943 | 76938    |  1.2  |     (76938)\(76943)     | 1               | 1      |
+-------+----------+-------+-------------------------+-----------------+--------+
| 76944 | 76938    |  1.3  |     (76938)\(76944)     | 0               | 0      |
+-------+----------+-------+-------------------------+-----------------+--------+
| 76946 | 76944    | 1.3.1 | (76938)\(76944)\(76946) | 1               | 0      |
+-------+----------+-------+-------------------------+-----------------+--------+
| 76947 | 76944    | 1.3.2 | (76938)\(76944)\(76947) | 0               | 0      |
+-------+----------+-------+-------------------------+-----------------+--------+
| 76948 | 76944    | 1.3.3 | (76938)\(76944)\(76948) | 1               | 0      |
+-------+----------+-------+-------------------------+-----------------+--------+
| 76945 | 76938    | 1.4   | (76938)\(76945)         | 1               | 1      |
+-------+----------+-------+-------------------------+-----------------+--------+

如果游标是动态的,您可以从底层 table 中删除并从未来的 FETCH 中删除行,并且定义游标的查询不需要假脱机,有效地将其变成静态的光标.

在您的代码中,按未索引的 VARCHAR(MAX) 排序可防止游标看到基础 table.

中的任何更改

EG这个

drop table if exists #test
go
create table #test(id integer, name varchar(max), path varchar(1000), index ix_path (path))
insert into #test(id,name,path) values (1,'a','0000000'),(2,'b', '0769391'),(3,'c', '1768391')

DECLARE cursor_name CURSOR DYNAMIC
FOR SELECT * FROM #test ORDER BY path


DECLARE
    @Id AS INTEGER,
    @Name AS VARCHAR(MAX),
    @Path AS VARCHAR(MAX)

OPEN cursor_name;
FETCH NEXT FROM cursor_name INTO @Id, @Name, @Path;
PRINT @Name

print 'deleting'
DELETE FROM #test 
WHERE
    Path LIKE '%76939%'

WHILE 1=1
BEGIN
    FETCH NEXT FROM cursor_name INTO @Id, @Name, @Path;
    if @@FETCH_STATUS <> 0  break
    PRINT @Name
END;

CLOSE cursor_name;
DEALLOCATE cursor_name;

产出

(3 rows affected)
a
deleting

(1 row affected)
c