--建立函數
Create Function F_GetChildren(@id Varchar(10))
Returns @Tree Table (id Varchar(10), pid Varchar(10))
As
Begin
Insert @Tree Select id, pid From 表 Where id = @id
While @@Rowcount > 0
Insert @Tree Select A.id, A.pid From 表 A Inner Join @Tree B On A.pid = B.id And A.id Not In (Select id From @Tree)
Return
End
GO
--測試
Delete From 表 Where ID In (Select id From dbo.F_GetChildren('01'))Select * From 表
Create Function F_GetChildren(@id Varchar(10))
Returns @Tree Table (id Varchar(10), pid Varchar(10))
As
Begin
Insert @Tree Select id, pid From 表 Where id = @id
While @@Rowcount > 0
Insert @Tree Select A.id, A.pid From 表 A Inner Join @Tree B On A.pid = B.id And A.id Not In (Select id From @Tree)
Return
End
GO
--測試
Delete From 表 Where ID In (Select id From dbo.F_GetChildren('01'))Select * From 表
Create Table 表
(id Varchar(10),
name Nvarchar(10),
pid Varchar(10)
)
Insert 表 Select '01', N'张三', '00'
Union All Select '02', N'李四', '00'
Union All Select '03', N'王五', '01'
Union All Select '04', N'牛六', '02'
Union All Select '05', N'马七', '04'
Union All Select '06', N'张八', '03'
GO
--建立函數
Create Function F_GetChildren(@id Varchar(10))
Returns @Tree Table (id Varchar(10), pid Varchar(10))
As
Begin
Insert @Tree Select id, pid From 表 Where id = @id
While @@Rowcount > 0
Insert @Tree Select A.id, A.pid From 表 A Inner Join @Tree B On A.pid = B.id And A.id Not In (Select id From @Tree)
Return
End
GO
--測試
Delete From 表 Where ID In (Select id From dbo.F_GetChildren('01'))Select * From 表
GO
--刪除測試環境
Drop Table 表
Drop Function F_GetChildren
--結果
/*
id name pid
02 李四 00
04 牛六 02
05 马七 04
*/
不创建函数可以么?
----------------
你的子節點的層數是不是固定的,如果是固定的,可以不用函數,如果不是,只能使用函數了路。
触发器可以么?--------可以,但是有限制。SQL Server 2000中触发器嵌套的最大层数为32层。
if exists(select name from sysobjects where name='test'and type='U')
drop table [dbo].[test]
go
create table [dbo].[test](id char(10),name char(20),pid char(10))
go
insert into test
select'00','aaa','00'
union all select'01','aaa','00'
union all select'02','aaa','00'
union all select'03','aaa','01'
union all select'04','aaa','01'
union all select'05','aaa','02'
union all select'06','aaa','02'
union all select'07','aaa','04'
union all select'08','aaa','04'
union all select'09','aaa','05'
union all select'10','aaa','05'
go
if exists(select name from sysobjects where name='tg_test'and type='TR')
drop trigger [dbo].[tg_test]
go
create trigger [dbo].[tg_test]
on [dbo].[test]
after delete
as
begin
if exists(select 1 from test where pid in(select id from deleted ))
delete from test where pid in(select id from deleted )
end
goselect*from [dbo].[test] delete from [dbo].[test] where id='02'select*from [dbo].[test]
/*结果
id name pid
---------- -------------------- ----------
00 aaa 00
01 aaa 00
03 aaa 01
04 aaa 01
07 aaa 04
08 aaa 04
09 aaa 05
10 aaa 05
*/
paoluo(一天到晚游泳的鱼) ( ) 信誉:100 建立一个触发器
CREATE TRIGGER [Ttt] ON [dbo].[表]
INSTEAD OF DELETE
AS
declare
@id int
declare @Tree Table (id Varchar(10), pid Varchar(10))Insert @Tree Select id, pid From 表 where id=(select id from deleted)
While @@Rowcount > 0
Insert @Tree Select A.id, A.pid From 表 A Inner Join @Tree B On A.pid = B.id And A.id Not In (Select id From @Tree)
Delete From 表 Where ID In (select id from @tree)
alter database 你的库名 set RECURSIVE_TRIGGERS ON
RECURSIVE_TRIGGERS ON | OFF
如果指定为 ON,将允许递归激发触发器。RECURSIVE_TRIGGERS OFF(默认值)只禁止直接递归。若要也禁用间接递归,请使用 sp_configure 将 nested triggers 服务器选项设置为 0。
Create Table 表
(id Varchar(10),
name Nvarchar(10),
pid Varchar(10)
)
Insert 表 Select '01', N'张三', '00'
Union All Select '02', N'李四', '00'
Union All Select '03', N'王五', '01'
Union All Select '04', N'牛六', '02'
Union All Select '05', N'马七', '04'
Union All Select '06', N'张八', '03'
GO
--建立觸發器
Create Trigger Delete_Trigger On 表
For Delete
As
If Exists(Select 1 From 表 Where pid in(Select id From Deleted))
Delete From 表 Where pid In (Select id From Deleted)
GO
--測試
Alter Database TEST Set RECURSIVE_TRIGGERS ON
Delete From 表 Where ID = '01'Select * From 表Alter Database TEST Set RECURSIVE_TRIGGERS OFF
GO
--刪除測試環境
Drop Table 表
--結果
/*
id name pid
02 李四 00
04 牛六 02
05 马七 04
*/
楼主,最后一条“06 张八 03”要删除吗?----------"如何写delete语句,删除id=‘01’,同时把‘01’的所有子孙节点完全删除"重點,“所有子孙节点完全删除”
or id in
(select id from 表 where (select name from 表 where id='01') like '%' +convert(char(2),name) +'%')刚才一直发不了回复。郁闷
paoluo(一天到晚游泳的鱼),你试试我的方法能删除吧。
tracyLD() ( ) 信誉:100 2007-08-17 17:44:48 得分: 0
Love001(随风飞),你要的是这个结果吧。
-----------------當然不是,你自己可以測試看看
你说哪里不是?我测试过的。
id name pid
01 张三 00
02 李四 00
04 牛六 02
05 马七 04
06 张八 03
*/和樓主的結果完全不一樣
你现在可能还没明白树是怎么回事吧,比如你把一颗树上的一个树干砍下来了,是不是他后面所带的所有的枝叶都下来了,这是一个递归的问题,当删除父结点O时,相对于它的子结点A,B来说,都要被删除的,那么同理,当A或者B要被删除时,那么它的子结点也要删除,依次类推,直到最后的那个最底层的节点或叶子为止。而你的那个语句,也仅仅只是删除了一层子结点而已。
谢谢大家支持,可是无论函数、触发器都不是我想要的。用select可以实现么?
------------------如果你的子節點的層數是固定的,只用select可以。但是不是固定的,要麼使用函數,要麼使用觸發器。
例如:我删除id=‘01’后,表记录为
表:
idnamepid
02李四00
04牛六02
05马七04
delete from table where id like '01%' or id like '%01'注:如上删除语句只有当id 为char(n) ,即等长 数据 ,希望可以解决问题
谢谢,paoluo,假设层数是固定的,如何写?--------你的層數是固定幾層的?最好不要過多,不然語句會很複雜。
if exists (select * from 临时表)
drop table 临时表
select * into 临时表 from 表 where id='01'2、建一个存储过程或者在查询分析器中执行以下语句
while exists (select * from 表 where pid in (select id from 临时表 ) and id not in ( select id from 临时表 ) )
insert into 临时表 select * from 表 where pid in (select id from 临时表) and id not in (select id from 临时表)3、执行查询语句
select * from 表 where id not in (select id from 临时表)4、删除临时表
drop table 临时表
就如上6条记录--------
可以這麼寫Delete From 表 Where ID In
(Select '01' As id
Union All
Select id From 表 Where pid = '01'
Union All
Select A.id From 表 A Inner Join 表 B On A.pid = B.id Where B.pid = '01'
)
--建立測試環境
Create Table 表
(id Varchar(10),
name Nvarchar(10),
pid Varchar(10)
)
Insert 表 Select '01',N'张三','00'
Union All Select '02',N'李四','00'
Union All Select '03',N'王五','01'
Union All Select '04',N'牛六','02'
Union All Select '05',N'马七','04'
Union All Select '06',N'张八','03'
GO
--測試
Delete From 表 Where ID In
(Select '01' As id
Union All
Select id From 表 Where pid = '01'
Union All
Select A.id From 表 A Inner Join 表 B On A.pid = B.id Where B.pid = '01'
)Select * From 表
GO
--刪除測試環境
Drop Table 表
--結果
/*
id name pid
02 李四 00
04 牛六 02
05 马七 04
*/