Why does it matter whether a SQL Where clause value is provided by the user or embedded in the code matter?

我的梦境 提交于 2019-12-11 05:38:24

问题


I have a legacy SSRS report that works as designed - returns a ton of data.

I created a derivation of it that is targeted toward using a specific value.

IOW, in the legacy report, the value is selected by the user, whereas in the derived report, it is "baked in."

The derived report, after much hourglassing and hamster cage rattling, finally throws up its hands and says, "An error occurred during local report processing. The size necessary to buffer the XML content exceeded the buffer quota."

A related question is here.

The only difference between the two reports is:

1) I removed one of the parameters

2) Where reference is made to that parameter, I replaced the code in the .rdl with a literal value.

Why would that change cause the report to go on strike/go AWOL?

To be more specific, here are the only differences between the legacy report and the derived report:

1) Legacy:

<DataSetName>CPSData</DataSetName>

New:

<DataSetName>DataSetOldChicago</DataSetName>

2) Legacy:

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

New:

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

3) Legacy:

<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>

New:

<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>
  • so the new one lacks the "Unit" parameter; after that, the fields are shown, which are identical except

in slightly different order for some reason - I don't know why that would be, but can't imagine that would cause a problem (which order the fields are listed in).

4) Legacy:

<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>

New:

Missing, as user no longer selects the Unit

5) Legacy:

<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>

New:

Missing - now provided literally.

6) Legacy:

[ Nothing here ]

New:

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

-- so the new/non-working report has this "SortBy" param, which is hidden and provided a default value. But another derived report has the same parameter set up that way, and it causes no problems.

Any ideas on why this problem would raise its ogre-like visage?

UPDATE

The differences between the old (working) and derived (non-working) SPs are:

1)

Old:

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

New:

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)

Old:

where up.Unit = @Unit 

New:

where up.Unit = 'OLD CHICAGO'

3)

-same as 2)

4)

Old:

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

New:

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

5)

Old:

            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

New:

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)

Old:

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

New:

 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 

回答1:


Parameters in SQL play a huge part in how it determines it's execution plan for a specific statement. For instance, if a query has a variable vs a hard-coded literal, SQL will likely create two completely different plans for that. It's also quite possible that the addition/removal of a search parameter in a WHERE clause will cause the Indexes used to be changed. As well, if one plan has been used for ages and then you change it, even slightly, it now needs to go through the extra overhead of building a new plan, optimizing it, caching it (if viable), etc...

In short, it's quite possible that this seemingly small change has completely altered your execution plan. This can have all kinds of unexpected results in terms of performance. I would recommend running your two different versions with all outputs (PRINT/SELECTs) removed (I'm hoping that will lower memory usage and allow your second version to finish?) and seeing if you can capture the Actual Execution Plan. It may shed some light on what it's doing differently and why it's suddenly taking forever and, eventually, failing.




回答2:


You seem to be calling two completely seperate stored procedures sp_ViewPriceMatrix_Variance_RockBottom and ViewPriceMatrix_CraftworksRollup_OldChicago. Irrespective of the changes you've made in your SSRS definition, its the difference between the underlying data query you need to look at. I suspect they are very different.



来源:https://stackoverflow.com/questions/37754698/why-does-it-matter-whether-a-sql-where-clause-value-is-provided-by-the-user-or-e

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!