Execute the following SQL in 2008 and 2012. When executed in 2008, the returned result is in its correct sort order. In 2012, the sortorder is not retained.
在2008和2012中执行以下SQL。在2008年执行时,返回的结果按正确的排序顺序排列。在2012年,不保留排序顺序。
Is this a known change? Is there a work-around for 2012 to retain the sort order?
这是一个已知的变化吗? 2012年是否有解决方案来保留排序顺序?
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 * INTO #Result FROM #MyTable ORDER BY SortOrder
SELECT * FROM #Result
DROP TABLE #MyTable
DROP TABLE #Result
6 个解决方案
#1
17
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.
如何使用select * from #result来判断表中的顺序是什么?无法保证选择查询中的订单。
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:
但是,SQL Fiddle的结果不同。如果要保证结果相同,请添加主键。然后保证插入顺序:
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.
在此之后我仍然厌恶从结果中选择*。但是,它确实在SQL Server 2008和2012中以正确的顺序返回它们。不仅如此,而且因为SQL Server保证以正确的顺序插入主键,所以记录甚至保证在正确的顺序中这个案例。
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.
但是。 。 。仅因为记录在页面上的特定顺序并不意味着它们将按顺序检索而没有order by子句。
#2
9
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.
将ORDER BY与INSERT一起使用时,除了控制标识列的顺序(如果存在)之外,从未保证执行任何操作。
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.
在SQL Server 2012之前,优化器始终生成一个计划,就好像存在标识列一样,因此看起来可以正确排序。 SQL Server 2012正确地假设不存在标识列,并且只有在表实际具有标识列时才会进行排序。
So you can resolve this issue by adding an Identity column to your temp result table.
因此,您可以通过向临时结果表中添加Identity列来解决此问题。
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.
但是,您真的应该只在SELECT语句中添加ORDER BY子句吗?没有ORDER BY的SELECT语句从未保证以任何特定顺序返回结果。始终添加ORDER BY子句以确保以预期的方式接收结果。
#3
2
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:
首先,感谢sgeddes的解释,它帮助了很多。关于定义表变量或创建临时表的事情是你必须定义它,如果你要完成定义它的工作,你也可以插入正确的方法:
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中的ORDER BY是动态的,所以当我调用“SELECT * FROM #Result”时,ORDER BY是未知的。我的解决方案是添加一个ROW_NUMBER列,当我获取数据时,我可以将其硬编码到SELECT中。是的,我仍然需要包含一个ORDER BY,但至少它是静态的。这是我做的:
--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.
希望这可以帮助。
#4
0
If you have different sorted results when querying each database, your collation is probably different between the two.
如果在查询每个数据库时有不同的排序结果,则两者之间的排序规则可能不同。
Try explicitly setting the collation in your query and see if your results are returned in the same order in both databases, e.g.
尝试在查询中明确设置排序规则,并查看两个数据库中的结果是否以相同的顺序返回,例如
SELECT * FROM #Result ORDER BY C1 COLLATE Latin1_General_CS_AS
#5
0
Workaround : You could add a SET ROWCOUNT
before this type of query, then put if back to zero after to reset it, it works. This will force SQL to keep the order in your query.
解决方法:您可以在此类查询之前添加SET ROWCOUNT,然后在重置之后将其置为零,它可以正常工作。这将强制SQL保持查询中的顺序。
SET ROWCOUNT 1000000000
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 * INTO #Result FROM #MyTable ORDER BY SortOrder
SELECT * FROM #Result
SET ROWCOUNT 0
DROP TABLE #MyTable
DROP TABLE #Result
#6
0
You must to create ROW_NUMBER() order by column you want to order. Order by directly in the select, is ignored when insert is executed.
您必须按要订购的列创建ROW_NUMBER()订单。直接在select中排序,在执行insert时被忽略。
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 Name, ROW_NUMBER() OVER (ORDER BY MyTable.SortOrder) AS SortOrder INTO #Result FROM #MyTable AS MyTable ORDER BY SortOrder SELECT * FROM #Result DROP TABLE #MyTable DROP TABLE #Result
#1
17
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.
如何使用select * from #result来判断表中的顺序是什么?无法保证选择查询中的订单。
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:
但是,SQL Fiddle的结果不同。如果要保证结果相同,请添加主键。然后保证插入顺序:
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.
在此之后我仍然厌恶从结果中选择*。但是,它确实在SQL Server 2008和2012中以正确的顺序返回它们。不仅如此,而且因为SQL Server保证以正确的顺序插入主键,所以记录甚至保证在正确的顺序中这个案例。
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.
但是。 。 。仅因为记录在页面上的特定顺序并不意味着它们将按顺序检索而没有order by子句。
#2
9
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.
将ORDER BY与INSERT一起使用时,除了控制标识列的顺序(如果存在)之外,从未保证执行任何操作。
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.
在SQL Server 2012之前,优化器始终生成一个计划,就好像存在标识列一样,因此看起来可以正确排序。 SQL Server 2012正确地假设不存在标识列,并且只有在表实际具有标识列时才会进行排序。
So you can resolve this issue by adding an Identity column to your temp result table.
因此,您可以通过向临时结果表中添加Identity列来解决此问题。
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.
但是,您真的应该只在SELECT语句中添加ORDER BY子句吗?没有ORDER BY的SELECT语句从未保证以任何特定顺序返回结果。始终添加ORDER BY子句以确保以预期的方式接收结果。
#3
2
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:
首先,感谢sgeddes的解释,它帮助了很多。关于定义表变量或创建临时表的事情是你必须定义它,如果你要完成定义它的工作,你也可以插入正确的方法:
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中的ORDER BY是动态的,所以当我调用“SELECT * FROM #Result”时,ORDER BY是未知的。我的解决方案是添加一个ROW_NUMBER列,当我获取数据时,我可以将其硬编码到SELECT中。是的,我仍然需要包含一个ORDER BY,但至少它是静态的。这是我做的:
--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.
希望这可以帮助。
#4
0
If you have different sorted results when querying each database, your collation is probably different between the two.
如果在查询每个数据库时有不同的排序结果,则两者之间的排序规则可能不同。
Try explicitly setting the collation in your query and see if your results are returned in the same order in both databases, e.g.
尝试在查询中明确设置排序规则,并查看两个数据库中的结果是否以相同的顺序返回,例如
SELECT * FROM #Result ORDER BY C1 COLLATE Latin1_General_CS_AS
#5
0
Workaround : You could add a SET ROWCOUNT
before this type of query, then put if back to zero after to reset it, it works. This will force SQL to keep the order in your query.
解决方法:您可以在此类查询之前添加SET ROWCOUNT,然后在重置之后将其置为零,它可以正常工作。这将强制SQL保持查询中的顺序。
SET ROWCOUNT 1000000000
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 * INTO #Result FROM #MyTable ORDER BY SortOrder
SELECT * FROM #Result
SET ROWCOUNT 0
DROP TABLE #MyTable
DROP TABLE #Result
#6
0
You must to create ROW_NUMBER() order by column you want to order. Order by directly in the select, is ignored when insert is executed.
您必须按要订购的列创建ROW_NUMBER()订单。直接在select中排序,在执行insert时被忽略。
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 Name, ROW_NUMBER() OVER (ORDER BY MyTable.SortOrder) AS SortOrder INTO #Result FROM #MyTable AS MyTable ORDER BY SortOrder SELECT * FROM #Result DROP TABLE #MyTable DROP TABLE #Result