簡體   English   中英

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

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

在2008和2012中執行以下SQL。在2008年執行時,返回的結果按正確的排序順序排列。 在2012年,不保留排序順序。

這是一個已知的變化嗎? 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

如何使用select * from #result表中的順序是什么? 無法保證select查詢中的訂單。

但是,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;

在此之后,我仍然厭惡select * from Result 但是,它確實在SQL Server 2008和2012中以正確的順序返回它們。不僅如此,而且因為SQL Server保證以正確的順序插入主鍵,所以記錄甚至保證在正確的順序中這個案例。

但是。 僅因為記錄在頁面上的特定順序並不意味着它們將按順序檢索而沒有order by子句。

ORDER BYINSERT一起使用時,除了控制標識列的順序(如果存在)之外,從未保證執行任何操作。

在SQL Server 2012之前,優化器始終生成一個計划,就像存在標識列一樣,因此看起來可以正確排序。 SQL Server 2012正確地假設不存在標識列,並且只有在表實際具有標識列時才會進行排序。

因此,您可以通過向臨時結果表中添加Identity列來解決此問題。

但是,您真的應該只在SELECT語句中添加ORDER BY子句嗎? 沒有ORDER BY SELECT語句從未保證以任何特定順序返回結果。 始終添加ORDER BY子句以確保以預期的方式接收結果。

首先,感謝sgeddes的解釋,它幫助了很多。 關於定義表變量或創建臨時表的事情是你必須定義它,如果你要完成定義它的工作,你也可以插入正確的方法:

INSERT INTO #Result (col1, col2...)
SELECT Col1, Col2... FROM #MyTable....

在我的例子中,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;

希望這可以幫助。

如果在查詢每個數據庫時有不同的排序結果,則兩者之間的排序規則可能不同。

嘗試在查詢中明確設置排序規則,並查看兩個數據庫中的結果是否以相同的順序返回,例如

SELECT * FROM #Result ORDER BY C1 COLLATE Latin1_General_CS_AS

解決方法:您可以在此類查詢之前添加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

您必須按要訂購的列創建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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM