Everyone, at the beginning of their SQL career, get’s told that it is important to include an ORDER BY if they want the results ordered. Otherwise the order in which they are returned is not guaranteed.
But then you run queries a lot of times that don’t need a specific order – and you see that they (at least seem to) come out in the same order every time. You could (almost) be forgiven for thinking you can rely on that.
There was even a question on a Microsoft SQL certification exam a few years ago that asked what the default order was for records returned by a simple SELECT – the answer it was looking for was that it would be according to the order of the clustered index. So you can rely on that – right?
Wrong. The question was a bad question, and the answer was incorrect. Let’s look at this in action. First I’ll create a table and add some rows:
CREATE TABLE dbo.NoSuchThingAsDefaultSortOrder ( Id INT IDENTITY(1,1) CONSTRAINT PK_NoSuchThingAsDefaultSortOrder PRIMARY KEY CLUSTERED, FirstName VARCHAR(30) ); INSERT INTO dbo. NoSuchThingAsDefaultSortOrder (FirstName) VALUES ('John'), ('Fred'), ('Bob'), ('Sue'), ('Jenny'), ('Matt'), ('Alexis'), ('Zebedee');
Now let’s SELECT from the table, without specifying an order:
SELECT Id, FirstName FROM dbo.NoSuchThingAsDefaultSortOrder;
Here’s our results:
Okay, so they’ve come out ordered by Id according to our clustered index.
But what if someone comes along and decides they want to be able to look up records in the table by name, so they create a non-clustered index for that:
CREATE NONCLUSTERED INDEX IX_NoSuchThingAsDefaultSortOrder_FirstName ON dbo.NoSuchThingAsDefaultSortOrder(FirstName);
We run our original query again and this time these are the results we get:
They’ve come out in a different order – this time ordered by FirstName – like the index we just added.
The reason is that this time SQL decided that it would be better to use our new index to execute the query. In general, it will try and use the smallest index that will satisfy the query – and in this case it decided that was the non-clustered index. I’d show you the execution plans to prove that, but I think it’s pretty obvious from the order the results are returned in.
So, don’t go relying on there being a “default” sort order. It’s just not true, changes to indexing – or even conceivably to statistics about the data distribution, could change the way SQL chooses to execute your query, and that could change your order.
Unless you make sure to specify ORDER BY.