SQL服务器不返回所有行

时间:2015-06-05 11:39:16

标签: sql sql-server

以下是我用于从单个列搜索技能的过程。我需要传递给SP的3个变量,我需要相应地得到结果。我的理解是,使用分隔符从单个单元格中搜索多个值很容易出错,但是在我尝试将整个内容置于另一个IF ELSE条件之后,此查询无效。

ALTER procedure [dbo].[spFilterThisResume]
@Skill varchar(100),
@Exp INT, @Dt date
AS
DECLARE @NoStart INT
IF (@Exp = '')
    SET @Exp = NULL
IF (@Dt = '')
    SET @NoStart = 1
BEGIN
DECLARE @SkillId varchar(100)
DECLARE MY_CURSOR CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR 
SELECT * FROM dbo.SplitStrings_CTE(@Skill,',')
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO @SkillId
WHILE @@FETCH_STATUS = 0
BEGIN 
    IF (@NoStart = 1)
    BEGIN
        SELECT * FROM tblResume
        (Skills LIKE '%,'+(@SkillId)+',%' OR Skills LIKE (@SkillId)+',%' OR Skills LIKE '%,'+(@SkillId) OR Skills = (@SkillId)
        AND (Experience LIKE @Exp))
    END
    ELSE
    BEGIN
        SELECT * FROM tblResume
        (Skills LIKE '%,'+(@SkillId)+',%' OR Skills LIKE (@SkillId)+',%' OR Skills LIKE '%,'+(@SkillId) OR Skills = (@SkillId)
        AND (Experience LIKE @Exp)
        AND (CreatedDate LIKE @Dt))
    END
END
    PRINT @SkillId
    FETCH NEXT FROM MY_CURSOR INTO @SkillId
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR

我尝试将其放入IF ELSE块之前得到的结果是准确的。它甚至返回了我作为参数传递的单个技能的单个出现。但我不明白查询的哪一部分搞砸了我之前得到的整个结果集。遗憾的是,我没有将工作SP保存到记事本中。所以请帮助我确定我犯了什么错误。

注意:SELECT * FROM dbo.SplitStrings_CTE(@Skill,',')是我用来将输入csv拆分为其组件参数的函数

2 个答案:

答案 0 :(得分:1)

出现问题的是你的开始和结束块都是脱节的,你最终会陷入无限循环。如果我删除了实际的查询,并为每个位添加注释以缩短它,并用一个数字标记每个开头/结尾以便将它们绑定起来:

ALTER procedure [dbo].[spFilterThisResume]
AS
-- DECLARE VARIABLES
BEGIN                                       -- 1 BEGIN 1
    -- DECLARE CURSOR AND OPEN IT
    WHILE @@FETCH_STATUS = 0
    BEGIN                                   -- 2 START WHILE
        IF (@NoStart = 1)
        BEGIN                               -- 3 START IF
            -- QUERY WITH NO DATE CHECK
        END                                 -- 3 END IF
        ELSE
        BEGIN                               -- 3 START IF
            -- QUERY WITH DATE CHECK
        END                                 -- 3 END IF
    END                                     -- 2 END WHILE

    PRINT @SkillId
    FETCH NEXT FROM MY_CURSOR INTO @SkillId
END                                         -- 1 END 1

CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR

因此,您的第二个FETCH NEXT FROM MY_CURSOR INTO @SkillId超出了WHILE。所以你永远不会更新@@FETCH_STATUS,它会在第一次获取后始终为0,并且你永远不会退出循环以获得第二个FETCH,要纠正它你只需要放第二个{{}循环内部{1}}。

但是,这是不必要的光标使用,作为一般规则,您应尽可能避免使用游标。你可以使用:

FETCH

这仍然使用您的原始拆分功能,但在单个查询中,想象一下,从上一个问题开始,您在Resume中有行:

SELECT  *
FROM    tblResume AS r
WHERE   r.Experience LIKE @Exp
AND     EXISTS
        (   SELECT  1
            FROM    dbo.SplitStrings_CTE(@Skill,',') AS s
            WHERE   ',' + r.Skills + ',' LIKE '%,' + s.Value + ',%'
        );

您传递C,C++ P,H,D ASP,.net,C,C#,C++,R+ C++ ,而不是两次运行查询,一次为C++,C#,一次为C++,您可以在检查每个值后运行查询,exists子句基本上会扩展出去:

C#

此外,由于SELECT FROM tblResume WHERE r.Experience = @Exp AND ( ',' + r.Skills + ',' LIKE '%,C++,%' OR ',' + r.Skills + ',' LIKE '%,C#,%' ) @Dt,因此支票DATE确实会检查`@Dt =' 1900-01-01``是否不太可能要求的行为?我怀疑你想要:

@Dt = ''

即。检查日期未通过的位置,而不是1900-01-01。

IF @dt IS NULL
BEGIN

    SELECT  *
    FROM    tblResume AS r
    WHERE   r.Experience LIKE @Exp
    AND     EXISTS
            (   SELECT  1
                FROM    dbo.SplitStrings_CTE(@Skill,',') AS s
                WHERE   ',' + r.Skills + ','  LIKE '%,' + s.Value + ',%'
            );
END
ELSE
BEGIN

    SELECT  *
    FROM    tblResume AS r
    WHERE   r.Experience LIKE @Exp
    AND     r.CreatedDate = @Dt
    AND     EXISTS
            (   SELECT  1
                FROM    dbo.SplitStrings_CTE(@Skill,',') AS s
                WHERE   ',' + r.Skills + ','  LIKE '%,' + s.Value + ',%'
            );

END

<强>附录

关于为什么需要使用谓词如下:

        ----

再次,使用您之前的一些示例数据(一个额外的行):

WHERE ',' + r.Skills + ',' LIKE '%,' + s.Value + ',%'

因此,如果您只是在寻找C&#39;,您可以使用:

1. C
2. ASP,.net,C,C#,C++,R+
3. C++

但正如您在上一个问题中所指出的那样,这也会产生第3行,因为WHERE r.Skills LIKE '%C%'; 就像是&#39;%C%&#39;,这是不正确的,因此有必要寻找C++,即技能完全匹配的地方:

%,C,%

现在这意味着不会返回第一行,因为它上面的WHERE r.Skills LIKE '%,C,%'; C r.Skills`不同,以确保第一行和第一行列表不会从搜索中排除。

如果为%,C,%' - therefore we need to put the delimeter at the start and end of传递NULL,则由于谓词@Exp产生[Anything] = NULL,因此不会返回任何行,因此永远不会为真。这不仅仅是我的答案中的情况,也是你问题中的情况。

答案 1 :(得分:0)

您的sql返回的结果不正确,因为您正在使用SELECT f.AccountLink, f.AccountBalance, f.Age1, f.Age2, f.Age3, f.Age4, f.Age5, f.Age6, f.Age7 FROM Client CROSS APPLY [_efnAgedPostARBalancesSum] ('2014-09-30', Client.DCLink) AS f ()AND包装在一起。

您需要像这样构建查询。

OR

注意: 正如GarethD在答案中所提到的,在这种情况下你可以避免使用光标。