我在我的SQL 2008R2数据库中有一个游标。该游标获取数据列表,解析每行数据,然后通过存储过程运行解析的数据行。使用游标返回指定数量的结果
DECLARE ExecsDataCursor CURSOR FAST_FORWARD FOR
SELECT TOP (@GuessListSize)
ExecutiveId,
CompanyExecutiveId,
Email,
CompanyId,
@EmailPatternID EmailPatternID,
ExecNameForSorting
FROM
CompanyExecutive
WHERE
CurrentlyWithCompany = 1
AND
Email IS NULL
AND
CompanyExecutiveId NOT IN
(
SELECT CompanyExecutiveId
FROM ExecsData_ExecutiveCandidates
WHERE EmailPatternID = @EmailPatternID
)
ORDER BY
CompanyExecutiveId
OPEN ExecsDataCursor
DECLARE
@ExecutiveId INT,
@CompanyExecutiveId INT,
@Email NVARCHAR(255),
@CompanyId INT,
@EmailPatternID_ForCursor TINYINT,
@ExecName NVARCHAR(255)
FETCH NEXT FROM ExecsDataCursor
INTO
@ExecutiveId ,
@CompanyExecutiveId ,
@Email ,
@CompanyId ,
@EmailPatternID_ForCursor,
@ExecName
DECLARE
@FirstName NVARCHAR(50) = '',
@MiddleName NVARCHAR(50) = '',
@LastName NVARCHAR(50) = '',
@ExampleEmail NVARCHAR(255),
@Domain NVARCHAR(50) = ''
WHILE @@FETCH_STATUS = 0
BEGIN
IF (SELECT COUNT(*) FROM dbo.splitString(@ExecName,' ')) = 1
BEGIN
SELECT @FirstName = Data FROM dbo.splitString(@ExecName,' ') WHERE id = 1
END
IF (SELECT COUNT(*) FROM dbo.splitString(@ExecName,' ')) = 2
BEGIN
SELECT @FirstName = Data FROM dbo.splitString(@ExecName,' ') WHERE id = 1
SELECT @LastName = Data FROM dbo.splitString(@ExecName,' ') WHERE id = 2
END
IF (SELECT COUNT(*) FROM dbo.splitString(@ExecName,' ')) >= 3
BEGIN
SELECT @FirstName = Data FROM dbo.splitString(@ExecName,' ') WHERE id = 1
SELECT @MiddleName = Data FROM dbo.splitString(@ExecName,' ') WHERE id = 2
SELECT @LastName = Data FROM dbo.splitString(@ExecName,' ') WHERE id = (SELECT MAX(id) FROM dbo.splitString(@ExecName,' '))
END
SELECT @ExampleEmail = MAX(Email) FROM CompanyExecutive WHERE Email IS NOT NULL AND CompanyId = @CompanyId
SELECT @Domain = SUBSTRING(@ExampleEmail, CHARINDEX('@', @ExampleEmail), LEN(@ExampleEmail))
IF @EmailPatternID = 1 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 2 BEGIN BEGIN TRY EXEC [email protected]_DataMe @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 3 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 4 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 5 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 6 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 7 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 8 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 9 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 10 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 11 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 12 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 13 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
FETCH NEXT FROM ExecsDataCursor
INTO
@ExecutiveId ,
@CompanyExecutiveId ,
@Email ,
@CompanyId ,
@EmailPatternID_ForCursor,
@ExecName
END
CLOSE ExecsDataCursor
DEALLOCATE ExecsDataCursor
这很有效,至少按我的预期。游标在大约19秒内处理8000行。 8000行由用户输入指定,该用户输入提供给@GuessListSize参数。但是,解析的数据并不总是正确处理,这是可以预料的。因此,try-catch代码。我们并不需要游标对失败的存储过程执行任何操作。我们开始在单独的表格中跟踪它们,以便我们能够弄清楚如何在将来更好地处理这些数据点。
问题在于光标现在不会返回完整列表。我们希望得到用户指定的大小列表。因此,游标会根据需要拉取指定大小的列表,但其中一些条目可能无法通过存储过程正确处理,返回的列表小于指定的大小。
所以接下来我尝试的是一个WHILE循环。现在,WHILE循环正常工作。它返回了用户请求的所有行。然而,它花费了近30分钟的时间来运行相同大小的数据集。这显然是不可接受的。
DECLARE
@ExecutiveId INT,
@CompanyExecutiveId INT,
@Email NVARCHAR(255),
@CompanyId INT,
@EmailPatternID_ForCursor TINYINT,
@ExecName NVARCHAR(255)
DECLARE
@FirstName NVARCHAR(50) = '',
@MiddleName NVARCHAR(50) = '',
@LastName NVARCHAR(50) = '',
@ExampleEmail NVARCHAR(255),
@Domain NVARCHAR(50) = '',
@Counter SMALLINT = 0
--WHILE @@FETCH_STATUS = 0
WHILE @Counter < @GuessListSize
BEGIN
SELECT @CompanyExecutiveId =
MIN(CompanyExecutiveID)
FROM CompanyExecutive
WHERE CurrentlyWithCompany = 1 AND Email IS NULL
AND
CompanyExecutiveId NOT IN
(SELECT CompanyExecutiveId FROM ExecsData_ExecutiveCandidates WHERE EmailPatternID = @EmailPatternID)
AND
CompanyExecutiveID NOT IN
(SELECT CompanyExecutiveId FROM ExecsData_Errors)
SELECT
@ExecutiveId = ExecutiveId,
@Email = Email,
@CompanyId = CompanyId,
@EmailPatternID_ForCursor = @EmailPatternID,
@ExecName = ExecNameForSorting
FROM
CompanyExecutive
WHERE
CompanyExecutiveId = @CompanyExecutiveId
IF (SELECT COUNT(*) FROM dbo.splitString(@ExecName,' ')) = 1
BEGIN
SELECT @FirstName = Data FROM dbo.splitString(@ExecName,' ') WHERE id = 1
END
IF (SELECT COUNT(*) FROM dbo.splitString(@ExecName,' ')) = 2
BEGIN
SELECT @FirstName = Data FROM dbo.splitString(@ExecName,' ') WHERE id = 1
SELECT @LastName = Data FROM dbo.splitString(@ExecName,' ') WHERE id = 2
END
IF (SELECT COUNT(*) FROM dbo.splitString(@ExecName,' ')) >= 3
BEGIN
SELECT @FirstName = Data FROM dbo.splitString(@ExecName,' ') WHERE id = 1
SELECT @MiddleName = Data FROM dbo.splitString(@ExecName,' ') WHERE id = 2
SELECT @LastName = Data FROM dbo.splitString(@ExecName,' ') WHERE id = (SELECT MAX(id) FROM dbo.splitString(@ExecName,' '))
END
SELECT @ExampleEmail = MAX(Email) FROM CompanyExecutive WHERE Email IS NOT NULL AND CompanyId = @CompanyId
SELECT @Domain = SUBSTRING(@ExampleEmail, CHARINDEX('@', @ExampleEmail), LEN(@ExampleEmail))
IF @EmailPatternID = 1 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
IF @EmailPatternID = 2 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
IF @EmailPatternID = 3 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
IF @EmailPatternID = 4 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
IF @EmailPatternID = 5 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
IF @EmailPatternID = 6 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
IF @EmailPatternID = 7 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
IF @EmailPatternID = 8 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
IF @EmailPatternID = 9 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
IF @EmailPatternID = 10 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
IF @EmailPatternID = 11 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
IF @EmailPatternID = 12 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
IF @EmailPatternID = 13 BEGIN BEGIN TRY EXEC [email protected]_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID; SET @Counter = @Counter + 1; END TRY BEGIN CATCH INSERT INTO ExecsData_Errors (CompanyExecutiveID,EmailPatternID) VALUES (@CompanyExecutiveId,@EmailPatternID) END CATCH END
END
因为游标被设计为通过数据的预先定义的列表咀嚼,我不知道如何让说无论是错误的光标“动态”,并返回结果的用户指定的号码。 WHILE循环的“计数器”只有在SP不执行CATCH块的情况下执行时才会增加,但我不知道如何将其整合到光标中,或者甚至可以。
有什么明显的我在这里失踪?
(按照要求,INSERT SQL的SP)
ALTER PROCEDURE [dbo].[[email protected]_DataMe]
(
@ExecutiveID int,
@CompanyExecutiveID int,
@FirstName nvarchar(50),
@MiddleName nvarchar(50),
@LastName nvarchar(50),
@DomainName nvarchar(255),
@CompanyID int
)
AS
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
DECLARE @GUESS nvarchar(255)
DECLARE @FirstInitial nvarchar(1)
DECLARE @MiddleInitial nvarchar(1)
DECLARE @LastInitial nvarchar(1)
set @FirstInitial = SUBSTRING(@FirstName, 1, 1)
set @MiddleInitial = SUBSTRING(@MiddleName, 1, 1)
set @LastInitial = SUBSTRING(@LastName, 1, 1)
--*****Example******
--FirstName = Andy,
--Middle Name = Xanadu,
--Last Name = Farag,
--Domain = @umphreys.com
--******************
--ex. [email protected]
set @GUESS = LTRIM(@FirstName)+ @DomainName
EXEC ExecsData_InsertEmailGuessByExec_DataMe
@ExecutiveID,
@CompanyExecutiveID,
@GUESS,
@CompanyID,
9
RETURN (@@ERROR)
ALTER PROCEDURE [dbo].[ExecsData_InsertEmailGuessByExec_DataMe]
(
@ExecutiveID int,
@CompanyExecutiveID int,
@EmailAddress nvarchar(50),
@CompanyID int,
@EmailPatternID tinyint
)
AS
BEGIN
INSERT ExecsData_ExecutiveCandidates
(
ExecutiveID,
CompanyExecutiveID,
EmailAddress,
CompanyID,
EmailPatternID,
GuessTimestamp
)
VALUES
(
@ExecutiveID,
@CompanyExecutiveID,
@EmailAddress,
@CompanyID,
@EmailPatternID,
CURRENT_TIMESTAMP
)
END
每RBarryYoung的建议下,我选择看实际的SP插入处理了一下。我发现的其中一个问题是,我们的许多Execs并未将域名连接成电子邮件地址。扩展脚本可以查找域信息的区域已将该过程改进为接近用户指定的完成。虽然它还不完美,但它朝着正确的方向迈出了一步。
至于寻找动态强制游标拉动特定行数的方法,我想我可能将这个特定的SP嵌套在使用WHILE循环的第二个SP中。所以基本上,当列表大小小于用户指定的列表大小时,它将重新执行插入SP。这可能会起作用。如果有效,我会重新编辑并将其作为解决方案发布。
'TowerData_guess_ *'程序中的代码是什么? – RBarryYoung
这是一个非常基本的INSERT语句,它使用作为INSERT的一部分提供的解析值。我们预计不会100%插入成功。因此光标继续射击直到击中用户指定数量的结果的原因。 – RockiesMagicNumber
然后,坦率地说,我很惊讶,19秒被认为是可以接受的。在大多数环境中,插入8000行的任何事情都会被认为非常缓慢。如果你发布proc的'INSERT'代码并解释你为什么期望它有时会失败,我相信我们可以让它更好地运行。 – RBarryYoung