Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 2008 r2 使用游标返回指定数量的结果_Sql Server 2008 R2 - Fatal编程技术网

Sql server 2008 r2 使用游标返回指定数量的结果

Sql server 2008 r2 使用游标返回指定数量的结果,sql-server-2008-r2,Sql Server 2008 R2,我的SQL 2008R2数据库中有一个游标。此游标获取数据列表,解析每行数据,然后通过存储过程运行解析后的数据行 DECLARE ExecsDataCursor CURSOR FAST_FORWARD FOR SELECT TOP (@GuessListSize) ExecutiveId, CompanyExecutiveId, Email, CompanyId, @EmailPatternID EmailP

我的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
根据RBarryYoung的建议,我选择稍微看看实际的SP插入过程。我发现的一个问题是,我们的许多执行官没有将一个域连接到一个电子邮件地址。扩展脚本可以查找域信息的区域将过程改进到接近用户指定的完成。虽然还不完美,但这是朝着正确方向迈出的一步


至于如何动态强制光标拖动特定数量的行,我想我可以将这个特定的SP嵌套在使用WHILE循环的第二个SP中。因此,基本上,当列表大小小于用户指定的列表大小时,它将重新执行插入SP。这可能会起作用。如果可行,我将重新编辑并将其作为解决方案发布。

正如文章最后一段所建议的,我最终使用了嵌套SP。最外层的SP运行一个WHILE循环,跟踪请求的exec数量。然后,它使用指定数量的EXEC运行生成SP。如果返回的号码小于请求的号码,它将保留在WHILE循环中


正在记录生成SP中的错误,以便我们的数据团队进行审查。

TowerData_guess.*过程中的代码是什么?这是一个非常基本的INSERT语句,使用作为INSERT一部分提供的解析值。我们不期望100%的成功插入。因此,光标会一直触发,直到达到用户指定的结果数。坦白说,我很惊讶19秒被认为是可以接受的。在大多数环境中,插入8000行所需的时间只要超过几分之一秒,就会被视为非常慢。如果您发布proc的
INSERT
代码,并解释为什么您期望它有时会失败,我相信我们可以让它表现得更好。虽然我欣赏优化SPs的提议,但问题是试图找到一种混合光标和While循环的方法。我相信我们有很多方法可以改进实际插入,但是让用户指定的数据集完整是最重要的。简单地说,如果用户希望插入2000行,WHILE循环将确保插入这2000行。光标仅从2000行开始,然后没有完成到达CATCH块的行。我想要相对提高光标的速度和WHILE循环的完整性。简单地说,从数据库的角度来看,解决这一问题的最佳方法是提前确定哪些行不可插入,然后将它们过滤掉。使用试错法插入和计数是一种关系破裂的方法。但要修复它,我们需要知道这些过程中发生了什么,以及为什么一些插入失败。
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