I have a TVP myTVP
implemented as select val.* from vw_MyView val
. The other day, I modified vw_MyView
, replacing:
select Foo,Bar from DB
with
select Foo, Bash, Bar from DB
.
This had a strange side effect: Calling select Bar from myTVP()
returned a column named Bar
populated with the contents of Bash
(despite the fact that Bar
and Bash
don't even have the same type).
Anonymized plan demonstrating the problem: https://www.brentozar.com/pastetheplan/?id=ryJLJmqdl
Note that Object2
and Object1
are identical, but the output list of the left-most Nested Loop is completely different between the two plans.
Notes:
- There are no plan hints in use. No trace flags are set.
- CheckDB found no errors.
- Using option(recompile) did not fix the issue.
- Running right-click alter on the TVP with no changes fixed the issue.
- Running right-click alter on the TVP with a name change fixed the issue, but the new TVP was identical to the previous other than the name.
- Using SQL 2014 Standard Edition.
Questions:
- Is it normal for adding a new column to a view to change which column
of the view is used in by other references to that view? - Under what circumstances will adding a column to a view cause such behavior?
Best Answer
Yes, this is expected. Functions and views that use
SELECT *
end up storing part of the metadata themselves relating to the underlying columns, so it is very easy for them to get confused. I talk about this problem in the following post from 2009:And also in my recent GroupBy presentation:
How do you avoid this problem?
SELECT *
in objects.WITH SCHEMABINDING
, which means you can't modify the underlying objects without also modifying the objects that reference them (this also has the side effect of prevent*
so win-win).In this specific case, you can fix the object so that
Bar
returns the correct data by using:Incidentally, the documentation for
sys.sp_refreshsqlmodule
describes this exact scenario:As an aside, you should never use
FROM myTVP()
but instead always specify the schema, e.g.FROM dbo.myTVP()
. I talk about that in an old post, too.