Sql-Server-2008

儲存過程永遠執行,但內部查詢執行良好

  • May 8, 2020

如果我執行exec pr_BuscaLog -2,它將永遠執行(幾天,沒有盡頭)。

但是,如果我只是複制查詢並自行執行,它會在幾秒鐘內執行。

更新統計數據沒有幫助。

--pr_BuscaLog -1  
CREATE procedure [dbo].[pr_BuscaLog] (@qtdDias int)          
as          
begin          
declare @cmd as nvarchar(4000)          
declare @banco as varchar(100)          
declare @dataLimite as datetime          

更新:當我執行時EXEC PR_BUSCALOG,它開始執行,然後停止。

僅通過檢查程式碼很難判斷它是否由於無限循環或阻塞而永遠執行 - 我的猜測是後者。但這裡有一種稍微不同的方法,可以避免一些可能有問題的事情:

CREATE PROCEDURE dbo.pr_BuscaLog
 @qtdDias INT
AS
BEGIN
 SET NOCOUNT ON;
 DECLARE @cmd NVARCHAR(MAX) = N'', @dataLimite DATETIME = CONVERT(SMALLDATETIME, 
     DATEADD(DAY, @qtdDias, GETDATE()));

 SELECT name INTO #tmp FROM sys.databases WHERE database_id > 4;

 -- delete the ones that don't have that view    
 SELECT @cmd += N'DELETE #tmp WHERE name = N''' + name 
     + ''' AND NOT EXISTS (SELECT 1 FROM ' + QUOTENAME(name) 
     + '.sys.views WHERE name = N''vwLogProjetos'');' FROM #tmp

 EXEC sys.sp_executesql @cmd;
 SET @cmd = N'';

 SELECT @cmd += N'INSERT PainelControle..tblLogProjetos(...columns...)  
   select ...columns... FROM ' + QUOTENAME(name) 
     + N'.dbo.vwLogProjetos as T1 with (nolock)  
         where DtTrabalho >= @dt and not exists
         (
           select 1 from PainelControle.dbo.tblLogProjetos T2 
            Where t2.BancoDados collate SQL_Latin1_General_CP1_CI_AS 
            = t1.BancoDados collate SQL_Latin1_General_CP1_CI_AS 
            and t2.codlog = t1.codlog
         );' FROM #tmp;

 BEGIN TRY
   EXEC sys.sp_executesql @cmd, N'@dt DATETIME', @dataLimite;
 END TRY
 BEGIN CATCH
   insert into dbo.tblLogProjetosErro (rotina, comando,Data) 
     values ('pr_BuscaLog', @cmd + ERROR_MESSAGE(), GETDATE());  
 END CATCH
END

我改變了一些東西(或者你應該改變):

  • 沒有顯式循環。與流行的看法相反,while 循環並不比游標快(參見這篇文章),但這裡也不需要。
  • 當你不需要的時候不要指望 - 看到這個文章
  • 我參數化了日期值,而不是處理混亂的字元串連接(參見這篇文章這篇文章)。使用實體很難避免這種情況,但應始終使用變數來完成。
  • 請停止使用惰性速記;例如使用DATEDIFF(SECOND代替DATEDIFF(s- 見這篇文章
  • 使用架構前綴。總是

while 循環中的 select 語句Select count(1) from #tmp實際上是一個常量值。換句話說,它不會在每次循環中都發生變化。

我猜你真的想每個數據庫循環一次,所以你需要修改你的while循環。

引用自:https://dba.stackexchange.com/questions/88916