Sql 为什么运行过程非常慢?
这段代码相当晦涩,不清楚您想要实现什么 以下是一些提示: 使用有意义的变量名,例如@stock_balance,而不是像@x、@y等变量名。这种命名惯例的缺乏使得代码不仅对局外人而且对你来说都很难遵循 通常,在正确设计的关系数据库中,您将按ID或某些唯一键(而不是按名称)处理客户,就像您在这里所做的那样:Sql 为什么运行过程非常慢?,sql,sql-server,Sql,Sql Server,这段代码相当晦涩,不清楚您想要实现什么 以下是一些提示: 使用有意义的变量名,例如@stock_balance,而不是像@x、@y等变量名。这种命名惯例的缺乏使得代码不仅对局外人而且对你来说都很难遵循 通常,在正确设计的关系数据库中,您将按ID或某些唯一键(而不是按名称)处理客户,就像您在这里所做的那样: ALTER procedure [dbo].[PSI] @`PartNo` nvarchar (50), @Customer nvarchar (50), @Date1
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
这是非常不安全的:只要想想如果你有多个客户同名或同名会发生什么
更不用说这样的where子句将不能使用索引,假设您甚至有一个索引
如果在运行过程时显示执行计划,它应该会显示花费很长时间的部分,或者您可以在代码中简单地添加一些print-getdate
动态SQL不仅危险,而且很少有正当理由。一定有更好的办法
您在过程中使用了许多表,这些表的结构未知。您应该做的是发布这些表的结构,显示一些示例数据,并提供一个预期结果的示例。首先,我要消除SQL注入带来的巨大安全漏洞。我会暂时摆脱它。你有什么办法让它更快?仅仅向我们发布代码并不是一个问题。我认为问题是空的和while,但我还没有找到解决方案。ThanksISNULL是上述问题中最小的一个。但是,您还没有解释关于上述内容的任何内容,包括it目标。为什么需要动态SQL?为什么要实现一段时间?我希望在一段时间内每天创建一个字段,然后在包含空值的运算符中将数据更新到每个字段中。但是当使用isnull时,程序运行得非常慢。为什么不使用动态Pivot呢?
and Customer like '%' + @Customer + '%'