I have seen people build procedures that rely on a result set being returned in a certain order. This is fine if an order by clause is used, but SQL Server will not guarantee the order of the results without one.
It is interesting to look at the way SQL Server normally returns a result set though. So, lets make a small sample table:
create table orderTest (n varchar(15)) insert into orderTest (n) values (2), (1), (3), (1)
If we run a simple “select n from orderTest” the results I get back are 2, 1, 3, 1. In other words, it returns the results in the order they were inserted. This is relatively consistent. I have tried similar tests on multiple versions of sql on multiple machines. As I said at the beginning, I have seen some programs rely on the data being returned in the order it was inserted and those programs have gone for extended periods of time without any problems. But I want to emphasize that SQL Server will not guarantee the order without an order by clause. If you want to be able to guarantee that you can get the data back in the order that it was inserted in then you can add an identity column and order by that.
The tendency to return things in the order they were inserted seems fairly stable with simple where clauses, but asking SQL Server to return distinct results will change the order as it checks for duplicates. For instance “select distinct n from orderTest” gives me 1, 2, 3.
And SQL Server seems to return the results of a union all by just concatenating the results of the two queries. So
select n from orderTest UNION ALL select n from orderTest
Gives 2, 1, 3, 1, 2, 1, 3, 1. Essentially, the contents of the table repeated twice. But union makes the results distinct and so it changes the order. Redoing that with union instead of union all gives 1, 2, 3.
Indexes will also affect the order. You may notice the tests were all done on a heap with no indexes. But if I add an index (either clustered or nonclustered) it makes the order for “select n from orderTest” become 1, 1, 2, 3. Of course, you cannot always rely on the data being returned in index order either, unless there is an order by clause. Similarly, as Conor Cunningham pointed out, the size of the dataset can affect it and break apparent order as the optimizer seeks to increase parallelization.
In short, SQL Server has certain ways it will normally return data and it can be helpful to be aware of those. Even small changes to the query or changes in the size of the data can have a major impact on the order the results are returned. Without an order by clause, SQL is not guaranteed to return the data in the way it normally does and you cannot rely on that order. If the order actually matters, use an order by clause.