我的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 ExecsData_Guess_fnamelname@domain_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 2 BEGIN BEGIN TRY EXEC ExecsData_Guess_fnamedotlname@domain_DataMe @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 3 BEGIN BEGIN TRY EXEC ExecsData_Guess_finitiallname@domain_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 4 BEGIN BEGIN TRY EXEC ExecsData_Guess_finitialdotlname@domain_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 5 BEGIN BEGIN TRY EXEC ExecsData_Guess_finitial_lname@domain_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 6 BEGIN BEGIN TRY EXEC ExecsData_Guess_fname_lname@domain_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 7 BEGIN BEGIN TRY EXEC ExecsData_Guess_fnamelinitial@domain_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 8 BEGIN BEGIN TRY EXEC ExecsData_Guess_lnamefinitial@domain_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 9 BEGIN BEGIN TRY EXEC ExecsData_Guess_fname@domain_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 10 BEGIN BEGIN TRY EXEC ExecsData_Guess_lname_fname@domain_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 11 BEGIN BEGIN TRY EXEC ExecsData_Guess_lname@domain_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 12 BEGIN BEGIN TRY EXEC ExecsData_Guess_finitiallinitial@domain_DataME @ExecutiveID ,@CompanyExecutiveID ,@FirstName,@MiddleName ,@LastName ,@Domain ,@CompanyID END TRY BEGIN CATCH END CATCH END
IF @EmailPatternID = 13 BEGIN BEGIN TRY EXEC ExecsData_Guess_lnamedotfname@domain_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 ExecsData_Guess_fnamelname@domain_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 ExecsData_Guess_fnamedotlname@domain_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 ExecsData_Guess_finitiallname@domain_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 ExecsData_Guess_finitialdotlname@domain_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 ExecsData_Guess_finitial_lname@domain_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 ExecsData_Guess_fname_lname@domain_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 ExecsData_Guess_fnamelinitial@domain_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 ExecsData_Guess_lnamefinitial@domain_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 ExecsData_Guess_fname@domain_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 ExecsData_Guess_lname_fname@domain_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 ExecsData_Guess_lname@domain_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 ExecsData_Guess_finitiallinitial@domain_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 ExecsData_Guess_lnamedotfname@domain_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
因为Cursor旨在咀嚼预定义的数据列表,所以我不确定如何使所述游标“动态”并返回用户指定的结果数,而不管错误。 WHILE循环只有在没有命中CATCH块的情况下执行SP时才会增加“计数器”,但我不知道如何将其集成到Cursor中,或者我是否可以。
这里有什么显而易见的东西吗?
(根据要求,INSERT SQL SP)
ALTER PROCEDURE [dbo].[ExecsData_Guess_fname@domain_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. andy@umphreys.com
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插入过程。我发现的一个问题是我们的许多执行者都没有将域连接到电子邮件地址。扩展脚本可以查找域信息的区域已将过程改进为接近用户指定的完成。虽然它仍然不完美,但它是朝着正确方向迈出的一步。
至于找到动态强制游标拉出特定行数的方法,我想我可能会在使用WHILE循环的第二个SP中嵌套这个特定的SP。所以基本上,当列表大小小于用户指定的列表大小时,它将重新执行插入SP。那可能有用。如果它有效,我将重新编辑并发布此解决方案。
答案 0 :(得分:0)
正如帖子最后一段所述,我最终使用了嵌套的SP。最外面的SP运行一个WHILE循环,跟踪请求的许多高管。然后它使用指定的执行数运行生成SP。如果返回的数字小于请求的数字,它将保留在WHILE循环中。
我们的数据小组正在记录生成SP中的错误。