为什么SQL Where子句值是由用户提供还是嵌入在代码中是否重要?

时间:2016-06-10 18:09:26

标签: sql-server tsql stored-procedures reporting-services rdl

我有一份按设计运行的旧SSRS报告 - 返回大量数据。

我创建了一个针对使用特定值的派生。

IOW,在旧版报告中,该值由用户选择,而在派生报告中,它是“烘焙”。

派生的报告经过大量的沙漏和仓鼠笼子的嘎嘎声后,终于举起手来说:“在本地报告处理期间发生了错误。缓冲XML内容所需的大小超过了缓冲区配额。”

相关问题是here

两份报告之间的唯一区别是:

1)我删除了其中一个参数

2)在引用该参数的情况下,我将.rdl中的代码替换为文字值。

为什么这种改变会导致报告继续罢工/罢工?

更具体地说,以下是旧报告与派生报告之间的唯一区别:

1) 遗留:

<DataSetName>CPSData</DataSetName>

新:

<DataSetName>DataSetOldChicago</DataSetName>

2) 遗留:

<Value>=Parameters!Unit.value+", For Price Period: "+Parameters!BegDate.value+" - "+Parameters!EndDate.value</Value>

新:

<Value>="For Price Period: "+Parameters!BegDate.value+" - "+Parameters!EndDate.value</Value>

3) 遗留:

<DataSet Name="CPSData">
  <Query>
    <DataSourceName>CPSData</DataSourceName>
    <QueryParameters>
      <QueryParameter Name="@Unit">
        <Value>=Parameters!Unit.Value</Value>
      </QueryParameter>
      <QueryParameter Name="@BegDate">
        <Value>=Parameters!BegDate.Value</Value>
      </QueryParameter>
      <QueryParameter Name="@EndDate">
        <Value>=Parameters!EndDate.Value</Value>
      </QueryParameter>
      <QueryParameter Name="@SortBy">
        <Value>="Products"</Value>
      </QueryParameter>
    </QueryParameters>
    <CommandType>StoredProcedure</CommandType>
    <CommandText>sp_ViewPriceMatrix_Variance_RockBottom</CommandText>
    <rd:UseGenericDesigner>true</rd:UseGenericDesigner>
  </Query>

新:

<DataSet Name="DataSetOldChicago">
  <Query>
    <DataSourceName>CPSData</DataSourceName>
    <QueryParameters>
      <QueryParameter Name="@BegDate">
        <Value>=Parameters!BegDate.Value</Value>
      </QueryParameter>
      <QueryParameter Name="@EndDate">
        <Value>=Parameters!EndDate.Value</Value>
      </QueryParameter>
      <QueryParameter Name="@SortBy">
        <Value>=Parameters!SortBy.Value</Value>
      </QueryParameter>
    </QueryParameters>
    <CommandType>StoredProcedure</CommandType>
    <CommandText>ViewPriceMatrix_CraftworksRollup_OldChicago</CommandText>
  </Query>
  • 所以新的缺少“单位”参数;之后,显示的字段除了
  • 外是相同的

由于某种原因,顺序略有不同 - 我不知道为什么会这样,但无法想象这会导致问题(字段列在哪个顺序)。

4) 遗留:

<DataSet Name="UnitDS">
  <Query>
    <DataSourceName>CPSData</DataSourceName>
    <CommandText>select Unit from MasterUnits order by Unit</CommandText>
    <rd:UseGenericDesigner>true</rd:UseGenericDesigner>
  </Query>
  <Fields>
    <Field Name="Unit">
      <DataField>Unit</DataField>
      <rd:TypeName>System.String</rd:TypeName>
    </Field>
  </Fields>
</DataSet>

新:

缺少,因为用户不再选择单位

5) 遗留:

<ReportParameter Name="Unit">
  <DataType>String</DataType>
  <AllowBlank>true</AllowBlank>
  <Prompt>Unit</Prompt>
  <ValidValues>
    <DataSetReference>
      <DataSetName>UnitDS</DataSetName>
      <ValueField>Unit</ValueField>
      <LabelField>Unit</LabelField>
    </DataSetReference>
  </ValidValues>
</ReportParameter>

新:

失踪 - 现在按字面意思提供。

6) 遗留:

[这里没什么]

新:

<ReportParameter Name="SortBy">
  <DataType>String</DataType>
  <Prompt>Sort By</Prompt>
</ReportParameter>

- 所以新的/不工作的报告有这个“SortBy”参数,它被隐藏并提供了一个默认值。但是另一个派生报告具有相同的参数设置,并且没有问题。

关于为什么这个问题会引起类似食人魔的面貌的任何想法?

更新

旧(工作)和派生(非工作)SP之间的差异是:

1)

旧:

ALTER Procedure [dbo].[sp_ViewPriceMatrix_Variance_test2]
    @Unit varchar(4000),
    @BegDate datetime,
    @EndDate datetime,
    @SortBy varchar(20) 

新:

IF OBJECT_ID ( 'ViewPriceMatrix_CraftworksRollup_OldChicago', 'P' ) IS NOT NULL   
    DROP PROCEDURE ViewPriceMatrix_CraftworksRollup_OldChicago;  
GO
CREATE PROCEDURE [dbo].[ViewPriceMatrix_CraftworksRollup_OldChicago]
    @BegDate datetime,
    @EndDate datetime

2)

旧:

where up.Unit = @Unit 

新:

where up.Unit = 'OLD CHICAGO'

3)

- 同为2)

4)

旧:

Select @Statement = ('Update #TempContract Set [' + @PriceWeek  + ']=''' + IsNull(@Price,'0.00') + ''' where ItemCode=''' + @ItemCode + ''' and Unit=''' + @Unit + ''' and [ShortName]=''' + @ShortName +'''')

新:

Select @Statement = ('Update #TempContract Set [' + @PriceWeek  + ']=''' + IsNull(@Price,'0.00') + ''' where ItemCode=''' + @ItemCode + ''' and Unit=''''OLD CHICAGO'''' and [ShortName]=''' + @ShortName +'''')

5)

旧:

            fetch next from SetPriceWeekSQL into @PriceWeek, @BegDate
while @@fetch_status = 0
    begin
        SET @Week = @Week + 1 
        IF(@SQLstring='')
        Begin
            SET @SQLstring = @SQLstring + 'Insert Into #Temp Select Unit, ShortName, ItemCode, Description, regionorder, Contractprice, IsNull('+
            '['+@PriceWeek+'],''0.00'') as Price, (convert(decimal(10,3),''-0.001'')) as Variance, 
            '''+@PriceWeek+''' as PriceWeek, ''WK'+convert(varchar(2),@Week)+''' as Week From #TempContract'+@WherePriceWeek

            IF(@SortBy='Members')
            Begin
                SET @SQLstring = @SQLstring + ' UNION Select Unit, ShortName, '''', ''zzzz'', '''', '''', ''0'' as Price, ''-0.001'' as Variance, '''' as PriceWeek, ''WK'+convert(varchar(2),@Week)+''' as Week From #TempContract'+@WherePriceWeek
            End
            Else
            Begin
                SET @SQLstring = @SQLstring + ' UNION Select Unit, '''', ItemCode, Description, ''1000'', Contractprice, ''0'' as Price, ''-0.001'' as Variance, '''' as PriceWeek, ''WK'+convert(varchar(2),@Week)+''' as Week From #TempContract'+@WherePriceWeek
            End
        End
        ELSE 
        Begin
            SET @SQLstring = @SQLstring + ' UNION '
            SET @SQLstring = @SQLstring + 'Select Unit, ShortName, ItemCode, Description, regionorder, Contractprice, IsNull('+
            '['+@PriceWeek+'],''0.00'') as Price, IsNull(convert(decimal(10,2),['+@PriceWeek+'])-convert(decimal(10,2),['+@LastPriceWeek+']),''0.00'') as Variance, 
            '''+@PriceWeek+''' as PriceWeek, ''WK'+convert(varchar(2),@Week)+''' as Week From #TempContract'+@WherePriceWeek

            IF(@SortBy='Members')
            Begin
                SET @SQLstring = @SQLstring + ' UNION Select Unit, ShortName, '''', ''zzzz'', '''', '''', ''0'' as Price, ''0'' as Variance, '''' as PriceWeek, ''WK'+convert(varchar(2),@Week)+''' as Week From #TempContract Where IsNull(['+@LastPriceWeek+'],''0.00'') 
<> ''0.00'' or IsNull(['+@PriceWeek+'],''0.00'') <> ''0.00'' '
            End
            Else
            Begin
                SET @SQLstring = @SQLstring + ' UNION Select Unit, '''', ItemCode, Description, ''1000'', Contractprice, ''0'' as Price, ''0'' as Variance, '''' as PriceWeek, ''WK'+convert(varchar(2),@Week)+''' as Week From #TempContract Where IsNull(['+@LastPriceWeek+'],''0.00'') <> ''0.00'' or IsNull(['+@PriceWeek+'],''0.00'') <> ''0.00'' '
            End
        End

新:

fetch next from SetPriceWeekSQL into @PriceWeek, @BegDate
while @@fetch_status = 0
    begin
        SET @Week = @Week + 1 
        IF(@SQLstring='')
        Begin
            SET @SQLstring = @SQLstring + 'Insert Into #Temp Select Unit, ShortName, ItemCode, Description, regionorder, Contractprice, IsNull('+
            '['+@PriceWeek+'],''0.00'') as Price, (convert(decimal(10,3),''-0.001'')) as Variance, 
            '''+@PriceWeek+''' as PriceWeek, ''WK'+convert(varchar(2),@Week)+''' as Week From #TempContract'+@WherePriceWeek

                SET @SQLstring = @SQLstring + ' UNION Select Unit, '''', ItemCode, Description, ''1000'', Contractprice, ''0'' as Price, ''-0.001'' as Variance, '''' as PriceWeek, ''WK'+convert(varchar(2),@Week)+''' as Week From #TempContract'+@WherePriceWeek
        End
        ELSE 
        Begin
            SET @SQLstring = @SQLstring + ' UNION '
            SET @SQLstring = @SQLstring + 'Select Unit, ShortName, ItemCode, Description, regionorder, Contractprice, IsNull('+
            '['+@PriceWeek+'],''0.00'') as Price, IsNull(convert(decimal(10,2),['+@PriceWeek+'])-convert(decimal(10,2),['+@LastPriceWeek+']),''0.00'') as Variance, 
            '''+@PriceWeek+''' as PriceWeek, ''WK'+convert(varchar(2),@Week)+''' as Week From #TempContract'+@WherePriceWeek

                SET @SQLstring = @SQLstring + ' UNION Select Unit, '''', ItemCode, Description, ''1000'', Contractprice, ''0'' as Price, ''0'' as Variance, '''' as PriceWeek, ''WK'+convert(varchar(2),@Week)+''' as Week From #TempContract Where IsNull(['+@LastPriceWeek+'],''0.00'') <> ''0.00'' or IsNull(['+@PriceWeek+'],''0.00'') <> ''0.00'' '
        End
        SET @LastPriceWeek = @PriceWeek
        fetch next from SetPriceWeekSQL into @PriceWeek, @BegDate
    end

6)

旧:

IF(@SortBy='Members')
Begin
    Select 
        Unit,
        ShortName,
        ItemCode,
        Description,
        regionorder,
        Contractprice,
        convert(varchar(20),convert(decimal(10,2),Price)) as Price,
        sum(convert(money,Variance)) as Variance,
        VarianceAverage = convert(varchar(25),convert(decimal(10,2),(Select sum(convert(money,Variance)) From #Temp Where ShortName=T.ShortName and Week=T.Week) / Replace(((Select count(regionorder) From #Temp Where ShortName=T.ShortName and Week=T.Week)-count(
Variance)),'0','1'))), 
        PriceWeek,Week
    From #Temp T
    Group By
        Unit,
        ShortName,
        ItemCode,
        Description,
        regionorder,
        Contractprice,
        Price,
        PriceWeek,Week  
    Order By Week,ShortName,Description
End
ELSE
Begin
    Select 
        Unit,
        ShortName,
        ItemCode,
        Description,
        regionorder,
        Contractprice,
        convert(varchar(20),convert(decimal(10,2),Price)) as Price,
        sum(convert(money,Variance)) as Variance,
        VarianceAverage = convert(varchar(25),convert(decimal(10,2),(Select sum(convert(money,Variance)) From #Temp Where ItemCode=T.ItemCode and Week=T.Week) / Replace(((Select count(regionorder) From #Temp Where ItemCode=T.ItemCode and Week=T.Week)-count(Variance)),'0','1'))), 
        PriceWeek,Week
    From #Temp T 
    Group By
        Unit,
        ShortName,
        ItemCode,
        Description,
        regionorder,
        Contractprice,
        Price,
        PriceWeek,Week  
    Order By Week,Description,regionorder 
End

新:

 Select 
    Unit,
    ShortName,
    ItemCode,
    Description,
    regionorder,
    Contractprice,
    convert(varchar(20),convert(decimal(10,2),Price)) as Price,
    sum(convert(money,Variance)) as Variance,
    VarianceAverage = convert(varchar(25),convert(decimal(10,2),(Select sum(convert(money,Variance)) From #Temp Where ItemCode=T.ItemCode and Week=T.Week) / Replace(((Select count(regionorder) From #Temp Where ItemCode=T.ItemCode and Week=T.Week)-count(Variance)),'0','1'))), 
    PriceWeek,Week
From #Temp T 
Group By
    Unit,
    ShortName,
    ItemCode,
    Description,
    regionorder,
    Contractprice,
    Price,
    PriceWeek,Week  
Order By Week,Description,regionorder 

2 个答案:

答案 0 :(得分:1)

SQL中的参数在如何确定特定语句的执行计划方面起着重要作用。例如,如果查询具有变量vs硬编码的文字,则SQL可能会为此创建两个完全不同的计划。在WHERE子句中添加/删除搜索参数也很可能会导致更改索引。同样,如果一个计划已经使用多年,然后你改变它,甚至稍微改变它,现在需要经历建立新计划,优化它,缓存它(如果可行)等的额外开销...... / p>

简而言之,这个看似很小的变化很可能完全改变了您的执行计划。在性能方面,这可能会产生各种意想不到的结果。我建议运行你的两个不同的版本,删除所有输出(PRINT / SELECT)(我希望这会降低内存使用量并允许你的第二个版本完成?)并看看你是否可以捕获实际执行计划。它可能会对它的不同做法有所了解,以及为什么它会突然耗尽并最终失败。

答案 1 :(得分:1)

您似乎正在调用两个完全独立的存储过程sp_ViewPriceMatrix_Variance_RockBottom和ViewPriceMatrix_CraftworksRollup_OldChicago。无论您在SSRS定义中所做的更改,您需要查看的基础数据查询之间的差异。我怀疑他们非常不同。