We are moving from SQL Server 2008 to SQL Server 2012 and immediately noticed that all our table-valued functions no longer deliver their temp table contents in the correctly sorted order.
CODE:
INSERT INTO @Customer
SELECT Customer_ID, Name,
CASE
WHEN Expiry_Date < GETDATE() then 1
WHEN Expired = 1 then 1
ELSE 0
END
from Customer **order by Name**
In SQL Server 2008 this function returns the customers sorted by Name. In SQL Server 2012 it returns the table unsorted. The "order by" is ignored in SQL 2012.
Do we have to re-write all the functions to include a sort_id
and then sort them when they are called in the main application or is there an easy fix??
add a column named rowno to @Customer table
There were two things wrong with your original approach.
ORDER BY
on theINSERT ... SELECT ... ORDER BY
would be the order that the rows were actually inserted.SELECT
without anORDER BY
will return the rows in any particular order such as insertion order anyway.In 2012 it looks as though the behaviour has changed with respect to item 1. It now generally ignores the
ORDER BY
on theSELECT
statement that is the source for anINSERT
2008 Plan
2012 Plan
The reason for the change of behaviour is that in previous versions SQL Server produced one plan that was shared between executions with
SET ROWCOUNT 0
(off) andSET ROWCOUNT N
. The sort operator was only there to ensure the correct semantics in case the plan was run by a session with a non zeroROWCOUNT
set. TheTOP
operator to the left of it is aROWCOUNT TOP
.SQL Server 2012 now produces separate plans for the two cases so there is no need to add these to the
ROWCOUNT 0
version of the plan.A sort may still appear in the plan in 2012 if the
SELECT
has an explicitTOP
defined (other thanTOP 100 PERCENT
) but this still doesn't guarantee actual insertion order of rows, the plan might then have another sort after theTOP N
is established to get the rows into clustered index order for example.For the example in your question I would just adjust the calling code to specify
ORDER BY name
if that is what it requires.Regarding your
sort_id
idea from Ordering guarantees in SQL Server it is guaranteed when inserting into a table withIDENTITY
that the order these are allocated will be as per theORDER BY
so you could also dobut you would still need to order by the
sort_id
in your selecting queries as there is no guaranteed ordering without that (perhaps thissort_id
approach might be useful in the case where the original columns used for ordering aren't being copied into the table variable)