如何在不使用临时表的前提下通过SQL Cursor跳过已处理的CompanyId行
实现方案
你的游标已经按CompanyID排序,同一家公司的所有记录会连续返回,仅需新增几个状态变量记录已处理的公司ID和匹配结果即可,完全不需要临时表,实现逻辑如下:
- 新增3个状态变量:
@LastProcessedCoId INT:存储上一个已经完成匹配判断的公司ID,初始值设为-1@HasFirstNameUnderlineLastName BIT:标记当前公司是否匹配到firstName_lastName格式的邮箱,初始值设为0@HasFirstInitialLastName BIT:标记当前公司是否匹配到firstInitial_lastName格式的邮箱,初始值设为0
- 循环入口先判断当前公司ID是否等于已处理的公司ID,相等则直接跳过本次循环,取下一条记录
- 匹配到对应邮箱格式后直接打印结果,全部格式判断完成后将当前公司ID赋值给
@LastProcessedCoId,后续同公司的所有行都会直接跳过
修正后的完整代码
DECLARE @CoId INT ,@Email VARCHAR(255) ,@FName varchar(50) ,@LName varchar(50) -- 新增状态变量 ,@LastProcessedCoId INT = -1 ,@HasFirstNameUnderlineLastName BIT = 0 ,@HasFirstInitialLastName BIT = 0 Declare CoCursor CURSOR For SELECT E.CompanyID, E.Email, P.First_Name, P.Last_Name From Table_Email as E Left Join Table_People as P ON E.EmployeeID = P.EmployeeID Order by CompanyID, Email OPEN CoCursor Fetch NEXT FROM CoCursor INTO @CoId, @Email, @FName, @LName While @@FETCH_STATUS = 0 BEGIN -- 已处理过的公司直接跳过 IF @CoId = @LastProcessedCoId BEGIN Fetch NEXT FROM CoCursor INTO @CoId, @Email, @FName, @LName CONTINUE END -- 重置当前公司的匹配标记 SET @HasFirstNameUnderlineLastName = 0 SET @HasFirstInitialLastName = 0 -- 判断firstName_lastName格式 IF @Email LIKE @FName + '[_]' + @LName + '@%' BEGIN SET @HasFirstNameUnderlineLastName = 1 PRINT CONVERT(VARCHAR(50), @CoId) + ' has firstName_lastName@companyName.domain type email' END -- 判断firstInitial_lastName格式 IF @Email LIKE LEFT(@FName,1) + @LName + '@%' BEGIN SET @HasFirstInitialLastName = 1 PRINT CONVERT(VARCHAR(50), @CoId) + ' has firstInitial_lastName@companyName.domain type email' END -- 标记当前公司已处理 SET @LastProcessedCoId = @CoId Fetch NEXT FROM CoCursor INTO @CoId, @Email, @FName, @LName END CLOSE CoCursor DEALLOCATE CoCursor
注意事项
- 原代码中存在笔误:
Left Table_People缺少Join关键字,Table_Emails表名和定义的Table_Email不一致,以上代码已经修正 - 如果需要确认公司下至少有2个匹配的邮箱才输出结果,可以在匹配逻辑中新增计数判断,无需额外查询整表
- 方案完全基于游标排序的特性实现,仅在内存中存储状态变量,无临时表/表变量使用,适配大表处理场景
内容的提问来源于stack exchange,提问作者morganherg
相关产品推荐
相关产品推荐

