为什么程序运行非常非常缓慢?

时间:2020-02-29 14:16:50

标签: sql sql-server

ALTER procedure [dbo].[PSI]
    @`PartNo` nvarchar (50),
    @Customer nvarchar (50),
    @Date1 Date,
    @Date2 Date
AS

Begin
      declare @Qty int,
                  @i int,
                  @max_i int,
                  @b nvarchar(15),
                  @j int,
                  @max_j int

      IF EXISTS (SELECT * FROM tempdb.sys.sysobjects WHERE name like '#Test%')
            DROP TABLE #Test


      create table #Test(
            IDX         int identity(1,1), 
            Item      nvarchar(50)
          )   

      insert into #Test(Item) select distinct Name_Customer from Master_Products where Name like '%' + @PartNo + '%' and Customer like '%' + @Customer + '%'

      set @i=0
      set @max_i=DATEDIFF(day, @Date1, @Date2)

      Set @Qty=2
      DECLARE @SQL NVARCHAR(200)
      DECLARE @SQL1 NVARCHAR(200)
     DECLARE @x int
     DECLARE @y int
     DECLARE @z int
      while @i<=@max_i

      begin
        set @j=1
        set @max_j=(SELECT MAX(IDX) FROM #Test)
     Set @b=Dateadd(day,@i,@Date1)
     Set @SQL='alter table #Test
    add [' + cast(@b AS NVARCHAR(10)) + ']' + + 'int'
    exec [sp_executesql] @sql  WITH RECOMPILE 
    while @j<=@max_j
    Begin
    Set @x=(SELECT SUM(Qty) 
    FROM Planning_Stock_Balance 
    WHERE DateAjust<=@b and (select top 1 name from Master_Products where Name=Planning_Stock_Balance.PartNo) =(select item from #Test where IDX=@j)) 
    Set @y=(SELECT SUM(OKQTY) FROM Injection_Daily_Result WHERE PRODATE<=@b and (select top 1 name from Master_Products where Name=Injection_Daily_Result.PartNo)=(select item from #Test where IDX=@j))
    Set @z=(SELECT SUM(Qty) FROM Sales_PO WHERE DeliDate<=@b and (select top 1 name from Master_Products where Name=Sales_PO.ItemCode)=(select item from #Test where IDX=@j))

    Set @SQL1 ='update #Test 
    set [' + cast(@b AS NVARCHAR(10)) + ']=' + CAST(isnull(@x,0)+isnull(@y,0)-isnull(@z,0)
     AS NVARCHAR(10))
    + ' where idx =' + cast(@j as NVARCHAR(10)) +''

    exec [sp_executesql] @sql1  WITH RECOMPILE 

    SET @j=@j+1          
    end

    SET @i=@i+1          
    end

     Select * from #Test
     OPTION ( OPTIMIZE FOR UNKNOWN )
    -- where Item like '%' + @PartNo + '%' and (select top 1 Customer from Master_Products where Name=Item) like '%' + @Customer +'%'
     IF OBJECT_ID(N'tempdb..#Test', N'U') IS NOT NULL  
     drop table #Test 
End

1 个答案:

答案 0 :(得分:1)

这段代码非常晦涩,不清楚您要实现的目标。

一些提示:

使用有意义的变量名,例如@stock_balance而不是@x@y等变量名。这缺少命名约定不仅使局外人也难以遵循该代码。

通常,在设计合理的关系数据库中,您将使用 ID 或某些唯一键来处理客户,而不像您在此处那样使用名称:

and Customer like '%' + @Customer + '%'

那是不安全:只要想想如果您有多个同名或同名客户,会发生什么情况。

更不用说这样的where子句将无法使用索引,前提是您甚至拥有一个。

如果在运行过​​程时显示执行计划,它应该向您显示花费很长时间的部分(或者您可以在代码中添加一些print getdate())。 / p>

动态SQL不仅危险,而且很少有道理。必须有一个更好的方法。

您在过程中使用了许多表,这些表的结构是未知的。您应该做的是发布这些表的结构,显示一些示例数据,并提供预期结果的示例。

相关问题