I spent the last day and a half trying to figure out why a query using FOR XML AUTO was returning the wrong result set. Some background is in order. I’m migrating a database from SQL 2000 to SQL 2005, as well as running the same database created from scripts on SQL 2005 but in a different environment. Both databases contain the exact same SQL in the stored procedure that was the source of the problem, but they were returning different result sets. I even restored the database that worked to the server that had the non-working database and saw that the database created from scripts was still working as expected.
I figured there was a database level setting causing the issue, so I opened up the database properties for both databases and compared them side by side, except I missed the 3 drop down boxes at the top, specifically the compatibility mode. I finally decided to run the SQL 2005 Update Advisor, which comes on the install media, or available online as a download. After about 10 minutes of checking my database (it was across a remote connection), it found the exact problem I was having, and the fix was to get rid of my derived tables, or set the comparability mode to 90.
From the Upgrade Advisor help, here is an example of my original problem.
Consider the following table:
CREATE TABLE Test(id int); INSERT INTO Test VALUES(1); INSERT INTO Test VALUES(2);
Now run this query, which produces different results under different compatibility levels.
SELECT * FROM (SELECT a.id AS a, b.id AS b FROM Test a JOIN Test b ON a.id=b.id) AS DerivedTest FOR XML AUTO;
Under Compatibility Level 80 you get:
<a a="1"><b b="1"/></a><a a="2"><b b="2"/></a>
Under Compatibility Level 90 you get:
<DerivedTest a="1" b="1"/><DerivedTest a="2" b="2"/>
The XML under Level 90 is what I was looking for. Remmeber, under SQL 2000, the same query worked fine, it was only under SQL 2005 with Level 80 that I started having problems.
Of course after switching to level 90 I found another bug, and wouldn’t you know it, the compatibility wizard told me about this one as well, I just felt like ignoring it at first. This time it was a problem with a table prefix in an order by clause. Funny thing is, the table prefix didn’t even exist in the stored procedure, but under SQL 2000 it worked fine. Turns out someone else had already fixed the issue in the SQL 2005 version.
While looking for the stored procedure in error (since at first I ignored the warning in the upgrade advisor which even told me what stored procedure), I found a quick way to search stored procedures and functions in SQL 2005.
SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_DEFINITION LIKE '%SearchString%'
Lesson of the day, try using and paying attention to the tools that Microsoft gives you.
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.