SELECT * INTO retains ORDER BY in SQL Server 2008 but not 2012
How can you tell what the order is inside a table by using select * from #result
? There is no guarantee as to the order in a select
query.
However, the results are different on SQL Fiddle. If you want to guarantee that the results are the same, then add a primary key. Then the insertion order is guaranteed:
CREATE TABLE MyTable(Name VARCHAR(50), SortOrder INT)
INSERT INTO MyTable SELECT 'b', 2 UNION ALL SELECT 'c', 3 UNION ALL SELECT 'a', 1 UNION ALL SELECT 'e', 5 UNION ALL SELECT 'd', 4
select top 0 * into result from MyTable;
alter table Result add id int identity(1, 1) primary key;
insert into Result(name, sortorder)
SELECT * FROM MyTable
ORDER BY SortOrder;
I still abhor doing select * from Result
after this. But yes, it does return them in the correct order in both SQL Server 2008 and 2012. Not only that, but because SQL Server guarantees that primary keys are inserted in the proper order, the records are even guaranteed to be in the correct order in this case.
BUT . . . just because the records are in a particular order on the pages doesn't mean they will be retrieved in that order with no order by
clause.
First, thanks sgeddes for the explanation, it helped a lot. The thing about defining a table variable or creating a temp table is you have to define it, and if you are going to go through the work of defining it, you might as well do the insert the correct way:
INSERT INTO #Result (col1, col2...)
SELECT Col1, Col2... FROM #MyTable....
In my case, the ORDER BY in the INSERT was dynamic so when I called "SELECT * FROM #Result", the ORDER BY was unknown. My solution was to add a ROW_NUMBER column that I could hardcode into the SELECT when I was getting the data. Yea, I still have to include an ORDER BY, but at least it's static. Here's what I did:
--Insert
SELECT ROW_NUMBER() OVER (ORDER BY T.SortOrder ASC) AS RowNum, T.*
INTO #Result
FROM (SELECT * FROM #MyTable ...) AS T;
--Get data out
SELECT * FROM #Result ORDER BY RowNum;
Hope this helps.
When using ORDER BY
with an INSERT
, it has never been guaranteed to do anything other than control the order of the identity column if present.
Prior to SQL Server 2012, the optimizer always produced a plan as if an identity column existed and thus appears to order correctly. SQL Server 2012 correctly does not assume an identity column exists, and only orders if the table actually has an identity column.
So you can resolve this issue by adding an Identity column to your temp result table.
However, you really should just add an ORDER BY
clause to your SELECT
statement? SELECT
statements without an ORDER BY
have never been guaranteed to return the results in any specific order. Always add the ORDER BY
clause to ensure you receive the results the way you expect.