Ada dua hal yang salah dengan pendekatan awal Anda.
- Saat menyisipkan ke tabel, tidak pernah dijamin bahwa
ORDER BY
padaINSERT ... SELECT ... ORDER BY
akan menjadi urutan baris yang benar-benar dimasukkan. - Saat memilih darinya SQL Server tidak menjamin bahwa
SELECT
tanpaORDER BY
akan mengembalikan baris dalam urutan tertentu seperti urutan penyisipan.
Pada tahun 2012 sepertinya perilaku telah berubah sehubungan dengan item 1. Sekarang umumnya mengabaikan ORDER BY
pada SELECT
pernyataan yang merupakan sumber untuk INSERT
DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
Paket 2008
Rencana 2012
Alasan untuk perubahan perilaku adalah bahwa di versi sebelumnya SQL Server menghasilkan satu rencana yang dibagi antara eksekusi dengan SET ROWCOUNT 0
(mati) dan SET ROWCOUNT N
. Operator sortir hanya ada di sana untuk memastikan semantik yang benar jika rencana dijalankan oleh sesi dengan ROWCOUNT
bukan nol mengatur. TOP
operator di sebelah kirinya adalah ROWCOUNT TOP
.
SQL Server 2012 sekarang menghasilkan paket terpisah untuk dua kasus sehingga tidak perlu menambahkan ini ke ROWCOUNT 0
versi rencana.
Semacam mungkin masih muncul dalam rencana tahun 2012 jika SELECT
memiliki TOP
yang eksplisit ditentukan (selain TOP 100 PERCENT
) tetapi ini masih tidak menjamin urutan penyisipan baris yang sebenarnya, rencananya mungkin akan memiliki pengurutan lain setelah TOP N
ditetapkan untuk mendapatkan baris ke dalam urutan indeks berkerumun misalnya.
Untuk contoh dalam pertanyaan Anda, saya hanya akan menyesuaikan kode panggilan untuk menentukan ORDER BY name
jika itu yang dibutuhkan.
Mengenai sort_id
Anda ide dari Jaminan pemesanan di SQL Server
dijamin saat memasukkan ke dalam tabel dengan IDENTITY
bahwa urutan yang dialokasikan ini akan sesuai dengan ORDER BY
jadi kamu juga bisa melakukan
DECLARE @Customer TABLE (
Sort_Id INT IDENTITY PRIMARY KEY,
Customer_ID INT,
Name INT,
Expired BIT )
INSERT INTO @Customer
SELECT Customer_ID,
Name,
CASE
WHEN Expiry_Date < Getdate() THEN 1
WHEN Expired = 1 THEN 1
ELSE 0
END
FROM Customer
ORDER BY Name
tetapi Anda masih perlu memesan dengan sort_id
dalam kueri pemilihan Anda karena tidak ada jaminan pemesanan tanpa itu (mungkin sort_id
ini pendekatan mungkin berguna dalam kasus di mana kolom asli yang digunakan untuk pemesanan tidak disalin ke dalam variabel tabel)