如何将一个CTE的输出添加到另一个CTE?
我有一个数据库,该数据库由8个有关员工的记录组成,它既保存了SSN,ssn是每个员工的ID,也可以保存一个引用其经理的Super_SSN。这是用于创建表的代码:
Create Table t_employee
(
Ssn int not null,
Super_ssn int,
FirstName varchar(50),
LastName varchar(50),
NationalCode varchar(50),
_role varchar(50),
Primary key(Ssn),
Foreign Key(Super_ssn) references t_employee(Ssn)
);
我必须编写Procedure
,该过程需要两个员工的ID(例如,@empid1
和@empid2 ),然后执行以下条件的删除操作: 如果第一名员工没有任何次级员工,则将被删除。但是,如果它具有某些次数,则必须首先将它们添加到另一名员工(
@empid2
),然后删除。
这是我的代码:
USE CompanyHierarchy
GO
Create Procedure deleteEmployees (@empId1 int, @empId2 int)
as
Begin
Declare @subCount int;
With CTE1 (Ssn, FirstName, LastName, Super_ssn, NationalCode, _role, _level) as
(
Select emp.Ssn,
emp.FirstName,
emp.LastName,
emp.Super_ssn,
emp.NationalCode,
emp._role,
0 as _level
From t_employee AS emp
Where emp.Ssn = @empId1
Union ALL
Select _emp.Ssn,
_emp.FirstName,
_emp.LastName,
_emp.Super_ssn,
_emp.NationalCode,
_emp._role,
_emp._level + 1
From t_employee _emp
Join CTE1 C1
on _emp.Super_ssn = C1.Ssn
)
Select @subCount = COUNT (*) From CTE1 c1 Where c1.Ssn <> c1.Super_ssn;
IF @subCount = 0
Begin
Delete From t_employee where Ssn = @empId1;
End
ELSE
Begin
With _CTE1 (Ssn, FirstName, LastName, Super_ssn, NationalCode, _role, _level) as
(
Select emp.Ssn,
emp.FirstName,
emp.LastName,
emp.Super_ssn,
emp.NationalCode,
emp._role,
0 as _level
From t_employee AS emp
Where emp.Ssn = @empId1
Union ALL
Select _emp.Ssn,
_emp.FirstName,
_emp.LastName,
_emp.Super_ssn,
_emp.NationalCode,
_emp._role,
_emp._level + 1
From t_employee _emp
Join _CTE1 _C1
on _emp.Super_ssn = _C1.Ssn
)
Update _CTE1 Set Super_ssn = @empId2 Where Super_ssn <> Ssn;
End
End
GO
EXEC deleteEmployees @empId1 = 6, @empId2 = 5;
但是它显示了错误
msg 4421,第16级,状态1,过程删除员工,第37行[批次 启动行3]派生的表'_cte1'无法更新,因为列 派生表的衍生或恒定。
我还尝试实现两个cte
s来选择两位员工的子和使用insert
,但是我不知道如何检查不添加重复的项目。
Create Procedure deleteEmployees (@empId1 int, @empId2 int)
as
Begin
Declare @subCount int;
With CTE1 (Ssn, FirstName, LastName, Super_ssn, NationalCode, _role, _level) as
(
Select emp.Ssn,
emp.FirstName,
emp.LastName,
emp.Super_ssn,
emp.NationalCode,
emp._role,
0 as _level
From t_employee AS emp
Where emp.Ssn = @empId1
Union ALL
Select _emp.Ssn,
_emp.FirstName,
_emp.LastName,
_emp.Super_ssn,
_emp.NationalCode,
_emp._role,
_emp._level + 1
From t_employee _emp
Join CTE1 C1
on _emp.Super_ssn = C1.Ssn
)
Select @subCount = COUNT (*) From CTE1 c1 Where c1.Ssn <> c1.Super_ssn;
IF @subCount = 0
Begin
Delete From t_employee where Ssn = @empId1;
End
ELSE
Begin
With _CTE1 (Ssn, FirstName, LastName, Super_ssn, NationalCode, _role, _level) as
(
Select emp.Ssn,
emp.FirstName,
emp.LastName,
emp.Super_ssn,
emp.NationalCode,
emp._role,
0 as _level
From t_employee AS emp
Where emp.Ssn = @empId1
Union ALL
Select _emp.Ssn,
_emp.FirstName,
_emp.LastName,
_emp.Super_ssn,
_emp.NationalCode,
_emp._role,
_emp._level + 1
From t_employee _emp
Join _CTE1 _C1
on _emp.Super_ssn = _C1.Ssn
)
, _CTE2 (Ssn, FirstName, LastName, Super_ssn, NationalCode, _role, _level) as
(
Select emp.Ssn,
emp.FirstName,
emp.LastName,
emp.Super_ssn,
emp.NationalCode,
emp._role,
0 as _level
From t_employee AS emp
Where emp.Ssn = @empId1
Union ALL
Select _emp.Ssn,
_emp.FirstName,
_emp.LastName,
_emp.Super_ssn,
_emp.NationalCode,
_emp._role,
_emp._level + 1
From t_employee _emp
Join _CTE2 _C2
on _emp.Super_ssn = _C2.Ssn
)
Insert Into _CTE2
Select * From _CTE1;
End
End
我将感谢您的帮助。
I have a database that consists of 8 records about the employees, and it saves both the Ssn which is the id of every employee and a Super_ssn that references their manager. Here is the code for creating the table:
Create Table t_employee
(
Ssn int not null,
Super_ssn int,
FirstName varchar(50),
LastName varchar(50),
NationalCode varchar(50),
_role varchar(50),
Primary key(Ssn),
Foreign Key(Super_ssn) references t_employee(Ssn)
);
I have to write a Procedure
which takes two employees' id, (for example, @empId1
and @empId2
), and then perform the delete operation, with the below condition:
If the first employee did not have any subalterns, it would be deleted. But if it had some subalterns, they must first be added to another employee (@empId2
) and then deleted.
Here is my code:
USE CompanyHierarchy
GO
Create Procedure deleteEmployees (@empId1 int, @empId2 int)
as
Begin
Declare @subCount int;
With CTE1 (Ssn, FirstName, LastName, Super_ssn, NationalCode, _role, _level) as
(
Select emp.Ssn,
emp.FirstName,
emp.LastName,
emp.Super_ssn,
emp.NationalCode,
emp._role,
0 as _level
From t_employee AS emp
Where emp.Ssn = @empId1
Union ALL
Select _emp.Ssn,
_emp.FirstName,
_emp.LastName,
_emp.Super_ssn,
_emp.NationalCode,
_emp._role,
_emp._level + 1
From t_employee _emp
Join CTE1 C1
on _emp.Super_ssn = C1.Ssn
)
Select @subCount = COUNT (*) From CTE1 c1 Where c1.Ssn <> c1.Super_ssn;
IF @subCount = 0
Begin
Delete From t_employee where Ssn = @empId1;
End
ELSE
Begin
With _CTE1 (Ssn, FirstName, LastName, Super_ssn, NationalCode, _role, _level) as
(
Select emp.Ssn,
emp.FirstName,
emp.LastName,
emp.Super_ssn,
emp.NationalCode,
emp._role,
0 as _level
From t_employee AS emp
Where emp.Ssn = @empId1
Union ALL
Select _emp.Ssn,
_emp.FirstName,
_emp.LastName,
_emp.Super_ssn,
_emp.NationalCode,
_emp._role,
_emp._level + 1
From t_employee _emp
Join _CTE1 _C1
on _emp.Super_ssn = _C1.Ssn
)
Update _CTE1 Set Super_ssn = @empId2 Where Super_ssn <> Ssn;
End
End
GO
EXEC deleteEmployees @empId1 = 6, @empId2 = 5;
But it shows the error that
Msg 4421, Level 16, State 1, Procedure deleteEmployees, Line 37 [Batch
Start Line 3] Derived table '_CTE1' is not updatable because a column
of the derived table is derived or constant.
I have also tried to implement two CTE
s to select the subalterns of both employees, and the use INSERT
, but I do not know how to check not to add duplicate items.
Create Procedure deleteEmployees (@empId1 int, @empId2 int)
as
Begin
Declare @subCount int;
With CTE1 (Ssn, FirstName, LastName, Super_ssn, NationalCode, _role, _level) as
(
Select emp.Ssn,
emp.FirstName,
emp.LastName,
emp.Super_ssn,
emp.NationalCode,
emp._role,
0 as _level
From t_employee AS emp
Where emp.Ssn = @empId1
Union ALL
Select _emp.Ssn,
_emp.FirstName,
_emp.LastName,
_emp.Super_ssn,
_emp.NationalCode,
_emp._role,
_emp._level + 1
From t_employee _emp
Join CTE1 C1
on _emp.Super_ssn = C1.Ssn
)
Select @subCount = COUNT (*) From CTE1 c1 Where c1.Ssn <> c1.Super_ssn;
IF @subCount = 0
Begin
Delete From t_employee where Ssn = @empId1;
End
ELSE
Begin
With _CTE1 (Ssn, FirstName, LastName, Super_ssn, NationalCode, _role, _level) as
(
Select emp.Ssn,
emp.FirstName,
emp.LastName,
emp.Super_ssn,
emp.NationalCode,
emp._role,
0 as _level
From t_employee AS emp
Where emp.Ssn = @empId1
Union ALL
Select _emp.Ssn,
_emp.FirstName,
_emp.LastName,
_emp.Super_ssn,
_emp.NationalCode,
_emp._role,
_emp._level + 1
From t_employee _emp
Join _CTE1 _C1
on _emp.Super_ssn = _C1.Ssn
)
, _CTE2 (Ssn, FirstName, LastName, Super_ssn, NationalCode, _role, _level) as
(
Select emp.Ssn,
emp.FirstName,
emp.LastName,
emp.Super_ssn,
emp.NationalCode,
emp._role,
0 as _level
From t_employee AS emp
Where emp.Ssn = @empId1
Union ALL
Select _emp.Ssn,
_emp.FirstName,
_emp.LastName,
_emp.Super_ssn,
_emp.NationalCode,
_emp._role,
_emp._level + 1
From t_employee _emp
Join _CTE2 _C2
on _emp.Super_ssn = _C2.Ssn
)
Insert Into _CTE2
Select * From _CTE1;
End
End
I will be grateful for your help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您是否使您的代码过度复杂化?您为什么根本穿越层次结构?当然,如果您打算在“ b”报告“ A”和“ C”向“ B”报告时删除“ A”,则您不打算对“ C”做任何事情。您只需要将这些报告直接更改为“ A”(在这种情况下)。如果是这样,则不需要CTE即可穿越层次结构。您还学会了不良习惯,并选择了奇怪的命名标准。
只需检查是否存在
@empid1
(一个通用名称,该名称不提供有关其使用方式的任何线索 - 请先作为主管作为主管,而不是“移动”(不是Move”(不是“添加”)将这些行到其他用户参数@Empid2
。简而言之:这就是您在非常基本的层面上需要的所有代码。添加您想要的任何错误处理,也许是对参数值进行的一些理智检查,也许可以在更新之前检查存在。使用两个零件名称(schema.table)是开发的最佳实践。
Have you overcomplicated your code? Why do you traverse the hierarchy at all? Surely if you intend to delete "a" when "b" reports to "a" and "c" reports to "b", you don't intend to do anything to "c". You only need to change those reporting directly to "a" ("b" in this case). If so, you don't need CTEs to traverse the hierarchy. You have also learned bad habits and have chosen strange naming standards.
Just check for the existence of
@empId1
(a generic name that does not provide any clues about how it is used - see what I mean by naming standards?) as a supervisor first and "move" (not "add") those rows to the other user parameter@empId2
. In short:That is all the code you need at a very basic level. Add whatever error handling you wish, perhaps some sanity checking of the parameter values, and perhaps check for existence before the update. Use of two part names (schema.table) is a best practice to develop.