简体   繁体   English

SELECT * INTO在SQL Server 2008中保留ORDER BY,但不保留2012

[英]SELECT * INTO retains ORDER BY in SQL Server 2008 but not 2012

Execute the following SQL in 2008 and 2012. When executed in 2008, the returned result is in its correct sort order. 在2008和2012中执行以下SQL。在2008年执行时,返回的结果按正确的排序顺序排列。 In 2012, the sortorder is not retained. 在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

How can you tell what the order is inside a table by using select * from #result ? 如何使用select * from #result表中的顺序是什么? There is no guarantee as to the order in a select query. 无法保证select查询中的订单。

However, the results are different on SQL Fiddle. 但是,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. 在此之后,我仍然厌恶select * from Result 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子句。

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 BYINSERT一起使用时,除了控制标识列的顺序(如果存在)之外,从未保证执行任何操作。

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之前,优化器始终生成一个计划,就像存在标识列一样,因此看起来可以正确排序。 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正确地假设不存在标识列,并且只有在表实际具有标识列时才会进行排序。

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语句中添加ORDER BY子句吗? SELECT statements without an ORDER BY have never been guaranteed to return the results in any specific order. 没有ORDER BY SELECT语句从未保证以任何特定顺序返回结果。 Always add the ORDER BY clause to ensure you receive the results the way you expect. 始终添加ORDER BY子句以确保以预期的方式接收结果。

First, thanks sgeddes for the explanation, it helped a lot. 首先,感谢sgeddes的解释,它帮助了很多。 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. 在我的例子中,INSERT中的ORDER BY是动态的,所以当我调用“SELECT * FROM #Result”时,ORDER BY是未知的。 My solution was to add a ROW_NUMBER column that I could hardcode into the SELECT when I was getting the data. 我的解决方案是添加一个ROW_NUMBER列,当我获取数据时,我可以将其硬编码到SELECT中。 Yea, I still have to include an ORDER BY, but at least it's static. 是的,我仍然需要包含ORDER BY,但至少它是静态的。 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. 希望这可以帮助。

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, eg 尝试在查询中明确设置排序规则,并查看两个数据库中的结果是否以相同的顺序返回,例如

SELECT * FROM #Result ORDER BY C1 COLLATE Latin1_General_CS_AS

Workaround : You could add a SET ROWCOUNT before this type of query, then put if back to zero after to reset it, it works. 解决方法:您可以在此类查询之前添加SET ROWCOUNT ,然后在重置之后将其置于零,它可以正常工作。 This will force SQL to keep the order in your query. 这将强制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

You must to create ROW_NUMBER() order by column you want to order. 您必须按要订购的列创建ROW_NUMBER()订单。 Order by directly in the select, is ignored when insert is executed. 直接在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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM