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 루프가 잘 작동했습니다. 사용자가 요청한 행을 모두 반환했습니다. 그러나 동일한 크기의 데이터 세트를 실행하는 데는 거의 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 블록을 치지 않고 실행되는 경우에만 "카운터"가 증가하지만 커서를 블록에 통합하는 방법을 알지 못합니다.
여기에 분명한 사실이 있습니까? (요구 된 바와 같이, SQL INSERT의 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의 제안은, 실제 I SP 삽입 프로세스 비트보고 정했다. 내가 발견 한 문제 중 하나는 많은 중역들이 이메일 주소로 연결하기 위해 도메인을 끌어 오지 않고 있다는 것입니다. 스크립트가 도메인 정보를 찾을 수있는 영역을 확장하면 거의 사용자가 지정한 완료로 프로세스가 향상되었습니다. 아직 완벽하지는 않지만 올바른 방향으로 나아가는 단계입니다.
동적으로 커서를 특정 수의 행을 가져 오도록 강제로 찾는 방법은 WHILE 루프를 사용하는 두 번째 SP에서이 특정 SP를 중첩시킬 수 있습니다. 따라서 기본적으로 목록 크기가 사용자 지정 목록 크기보다 작 으면 삽입 SP가 다시 실행됩니다. 그럴 수도 있습니다. 작동하는 경우이를 다시 편집하여 솔루션으로 게시합니다.
'TowerData_guess_ *'절차의 코드는 무엇입니까? – RBarryYoung
이것은 INSERT의 일부로 제공된 구문 분석 된 값을 사용하는 아주 기본적인 INSERT 문입니다. 우리는 100 % 성공적인 삽입을 기대하지 않습니다. 따라서 Cursor가 사용자 지정 개수의 결과에 도달 할 때까지 계속 실행되는 이유입니다. – RockiesMagicNumber
솔직히 나는 19 초를 받아 들일 수 있다고 생각한다. 8000 개의 행을 삽입하는 초보다 더 빠른 것은 대부분의 환경에서 매우 느린 것으로 간주됩니다. proc의 INSERT 코드를 게시하고 때때로 실패 할 것이라고 예상하는 이유를 설명하면, 우리가 더 잘 수행 할 수 있다고 확신합니다. – RBarryYoung