简体   繁体   English

使用IF ELSE语句重构存储过程

[英]Refactoring a stored procedure with IF ELSE statements

In a webapp I'm working on there's a table which holds, so called, ProjectItems . 在一个Webapp中,我正在处理一个表,该表包含所谓的ProjectItems The thing is that different types of project items reside in the same table; 问题是,不同类型的项目项驻留在同一张表中。 you could create a project, a question, an idea and a reaction. 您可以创建一个项目,一个问题,一个想法和一个反应。 With a bitwise column the type is set in the [Type] column. 对于按位列,在[Type]列中设置[Type] And each project item could have a parent (defined by a column named fk_Parent ) in this same table. 每个项目项在同一表中都可以有一个父项(由名为fk_Parent的列定义)。

The hierarchy is this: 层次结构是这样的:

Project (32) > Question (1) > Idea (2) > Reaction (4) Project (32)> Question (1)> Idea (2)> Reaction (4)

(I don't have any influence over the DB setup.) (我对数据库设置没有任何影响。)

I'm now creating a Stored Procedure for getting the root project item (of type Project) for any item with the ID passed as a parameter, but what I've got so far feels a little clunky: 我现在正在创建一个存储过程,以获取ID作为参数传递的任何项目的根项目(项目类型),但是到目前为止,我感觉有些笨拙:

CREATE PROC [dbo].[spProjectItemGetTopParentId]     
@ID INT

AS
    DECLARE @parentId INT
    SELECT @parentId =  fk_Parent FROM tblProjectItem WHERE ID = @ID
IF ((SELECT [Type] FROM tblProjectItem WHERE ID = @parentId) = 32)
    RETURN @parentId
ELSE
    SELECT @parentId =  fk_Parent FROM tblProjectItem WHERE ID = @parentId
IF ((SELECT [Type] FROM tblProjectItem WHERE ID = @parentId) = 32)
    RETURN @parentId
ELSE
    SELECT @parentId =  fk_Parent FROM tblProjectItem WHERE ID = @parentId
IF ((SELECT [Type] FROM tblProjectItem WHERE ID = @parentId) = 32)
    RETURN @parentId
ELSE
    SELECT @parentId =  fk_Parent FROM tblProjectItem WHERE ID = @parentId
IF ((SELECT [Type] FROM tblProjectItem WHERE ID = @parentId) = 32)
    RETURN @parentId
ELSE
RETURN 0
GO

I was wondering if there was any way to do this recursively in SQL? 我想知道是否有任何方法可以在SQL中递归执行此操作? Or some other way to make this a little more neat? 还是通过其他方法使它更整洁?

EDIT: This is the SP including the a CTE: 编辑:这是SP,包括CTE:

CREATE PROC [dbo].[spTest]  
@ID INT

AS
DECLARE @parentId INT;
WITH Parents as (
    select ID,Type,fk_Parent from tblProjectItem where ID = @ID
    union all
    select pi.ID,pi.Type,pi.fk_Parent
    from
        Parents p
            inner join
        tblProjectItem pi
            on
                p.fk_Parent = pi.ID
)
select @parentId = ID from Parents where Type = 32

GO

Yes, a recursive CTE can find this for you: 是的, 递归CTE可以为您找到这个:

;WITH Parents as (
    select ID,Type,parent_id from tblProjectItem where ID = @ID
    union all
    select pi.ID,pi.Type,pi.parent_id
    from
        Parents p
            inner join
        tblProjectItem pi
            on
                p.parent_id = pi.ID
)
select @parentId = ID from Parents where Type = 32

As a side note, I'd recommend against using prefixes for naming your database objects - with the exception of views and tables (that you should generally want to be indistinguishable) all object types can be clearly discerned by their usage - it's always clear from the position of a name in any particular query whether that name refers to a stored procedure, a (table|view), or a column, etc. 附带说明一下,我建议您不要使用前缀来命名数据库对象-除了视图和表(您通常希望不区分它们)之外,所有对象类型都可以通过它们的用法来清楚地区分-从名称在任何特定查询中的位置,无论该名称是指存储过程,(表)还是列等。

CREATE VIEW HierarchyExpanded AS 
BEGIN
    SELECT LVL1.ID      AS [LVL1ID]
          ,LVL1.[Type]  AS [LVL1Type]
          ,LVL2.ID      AS [LVL2ID]
          ,LVL2.[Type]  AS [LVL2Type]
          ,LVL3.ID      AS [LVL3ID]
          ,LVL3.[Type]  AS [LVL3Type]
          ,LVL4.ID      AS [LVL4ID]
          ,LVL4.[Type]  AS [LVL4Type]
    FROM   tblProjectItem LVL1
       INNER JOIN tblProjectItem LVL2
            ON  LVL2.fk_Parent = LVL1.ID
       INNER JOIN tblProjectItem LVL3
            ON  LVL3.fk_Parent = LVL2.ID
       INNER JOIN tblProjectItem LVL4
            ON  LVL4.fk_Parent = LVL3.ID
END



CREATE PROC [dbo].[spProjectItemGetTopParentId]     
@ID INT
AS
BEGIN
    DECLARE @parentId INT
    SELECT [LVL1ID]
    FROM   HierarchyExpanded
    WHERE  ([LVL1ID] =@ID 
    OR [LVL2ID] =@ID 
    OR [LVL3ID] =@ID 
    OR [LVL4ID] =@ID)
       AND [LVL1Type] = 32
END

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM