For two last statements of the code below produce actual execution plan. You can see that startup predicate on @Par1
is placed in a different position that completely changes the actual number of rows that come from test_fn1
function. I need to control this behaviour.
create or alter function dbo.test_fn1(@Par1 varchar(100), @Par2 varchar(1))
returns @t table(item varchar(100))
as
begin
insert into @t (item) select value from STRING_SPLIT(@Par1, @Par2);
return
end
GO
create or alter function dbo.test_fn(@Par1 varchar(100), @Par2 varchar(100))
returns table
as
return (
select s.*
from dbo.test_fn1(@Par2,';') x
inner join sys.objects s on s.name = x.item
where @Par1 = 'CASE1'
)
GO
create or alter function dbo.test_fnx(@Par1 varchar(100), @Par2
varchar(100))
returns table
as
return (
select s.*
from sys.objects s
inner join dbo.test_fn1(@Par2,';') x ON s.name = x.item
where @Par1 = 'CASE1'
)
GO
declare @Par1 varchar(100), @Par2 varchar(100)
select @Par1 = 'CASE2', @Par2 = 'test1;test2'
select * from dbo.test_fn(@Par1, @Par2)
select * from dbo.test_fnx(@Par1, @Par2)
Below is the proper plan where startup predicate makes the query does not work on any data.
Here is the plan that show wrong behaviour of placing startup predicate. In both cases we start from the same function and only order in T-SQL is changed.
Tested on SQL Server 2016 SP2.
Is there any whitepaper or documentation on how SQL Server is placing startup predicates?