包含循环的存储过程的更改花费的时间太长

时间:2016-02-02 14:49:41

标签: sql-server performance stored-procedures

我没有为我的问题找到任何合适的解决方案,所以我想在这里询问是否有人可以帮助我。

我有一个名为spImportWord的存储过程,它将word文件从另一台服务器上的文件位置下载到本地文件夹,并将每个word文件的值保存到数据库中的表中。对于每个文件,我正在调用一个将文件保存到本地文件夹的控制台应用程序。为了下载我正在使用while循环。在我使用cursor之前,据我所知,你应该远离cursors

自从我从cursor更改为while后,我甚至无法更改我的存储过程。完成需要永恒。有没有办法改善我的存储过程? (注意:使用cursor可以更改SP,但执行显示子查询返回的值超过1等。)

到目前为止我的代码:

ALTER PROCEDURE spImportWord
@fileId INT
AS
DECLARE @cmd VARCHAR(200)
DECLARE @filename VARCHAR(200)
DECLARE @foldername VARCHAR(200)
DECLARE @year VARCHAR(200)
DECLARE @remotePath VARCHAR(MAX)
DECLARE @localPath VARCHAR(MAX)
DECLARE @organisationId INT
DECLARE @folderId INT
DECLARE @import TABLE(ImportId INT)
DECLARE @counter INT

SELECT @filename = Files.FileName
    , @foldername = Files.FolderName
FROM Files WHERE Files.FileId = @fileId

CREATE TABLE #organisation ([OrganisationId] INT, [FolderId] INT, [Year] VARCHAR(4) NULL)
INSERT INTO #organisation
SELECT [tabInstitution].[OrganisationId]
    , [tabInstitution].[FolderId]
    , [tabInstitution].[UploadDate] AS [Year]
FROM [tabInstitution]

SET @organisationId = 0
SET @counter = 0
WHILE (@counter <= (SELECT COUNT(*) FROM #organisation))
BEGIN
    SELECT @organisationId = MIN([#organisation].[OrganisationId])
        , @folderId = [#organisation].[FolderId]
        , @year = [#organisation].[Year]
    FROM [#organisation]
    WHERE [#organisation].[OrganisationId] > @organisationId
    GROUP BY [FolderId], [Year]
    SET @remotePath = '\\somepath.path.com\somefolder\' + @organisationId + '\' + @folderId + '\' + @filename + '.docx'
    SET @localPath = 'C:\Files\' + @year + '\' + @foldername + '\' + @organisationId + '.docx'

    SET @cmd = 'C:\App\ImportWordFiles.exe --SourcePath ' + @remotePath + ' --TargetPath ' + @localPath
    EXEC xp_cmdshell @cmd, no_output

    -- Log into database
    INSERT INTO WordImport
    OUTPUT Inserted.ImportId INTO @import
    VALUES(GETDATE())

    INSERT INTO WordImportItem
    VALUES((SELECT ImportId FROM @import), @organisationId, @folderId, @localPath)

    SET @counter = @counter + 1
END

而不是之前的while循环:

DECLARE MY_CURSOR CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT [#organisation].[OrganisationId]
    , [#organisation].[FolderId]
    , [#organisation].[Year]
FROM [#organisation]
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO @organisationId, @folderId, @year
WHILE @@FETCH_STATUS = 0
BEGIN
    [...]
    FETCH NEXT FROM MY_CURSOR INTO @organisationId, @folderId, @year
END

我希望我解释我的问题是可以理解的。

1 个答案:

答案 0 :(得分:0)

你知道,你应该真正理解游标被认为是坏的原因。在您的情况下,没有理由使用游标,事实上,无论如何,您的while解决方案更加丑陋。

至于你的&#34;子查询问题&#34;,(SELECT ImportId FROM @import)应该责备 - 你不断向@import添加行,子查询返回所有ImportId s,而不仅仅是最后一个(或其他)。一旦@import包含多行,这将失败。很难说出你究竟想要做什么 - 我假设你只是想尝试获取最后一个插入的ID,并且没有必要维护一个完整的表格。导入ID。只需在阅读后删除@import中的所有数据。