以下是我用于从单个列搜索技能的过程。我需要传递给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
拆分为其组件参数的函数
答案 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在答案中所提到的,在这种情况下你可以避免使用光标。