Penyortiran Dinamis dalam Prosedur yang Disimpan SQL


126

Ini adalah masalah yang saya habiskan berjam-jam meneliti di masa lalu. Tampaknya bagi saya adalah sesuatu yang seharusnya ditangani oleh solusi RDBMS modern tetapi sampai sekarang saya belum menemukan apa pun yang benar-benar menjawab apa yang saya lihat sebagai kebutuhan yang sangat umum dalam aplikasi Web atau Windows dengan basis data back-end.

Saya berbicara tentang penyortiran dinamis. Di dunia fantasi saya, itu harus sesederhana sesuatu seperti:

ORDER BY @sortCol1, @sortCol2

Ini adalah contoh kanonik yang diberikan oleh pengembang SQL dan Stored Procedure pemula di seluruh forum di Internet. "Mengapa ini tidak mungkin?" mereka bertanya. Selalu, seseorang akhirnya datang untuk memberi tahu mereka tentang sifat kompilasi dari prosedur tersimpan, rencana eksekusi secara umum, dan segala macam alasan lain mengapa tidak mungkin untuk menempatkan parameter secara langsung ke dalam ORDER BYklausa.


Saya tahu apa yang sudah Anda pikirkan: "Biarkan klien melakukan penyortiran, kalau begitu." Secara alami, ini membongkar pekerjaan dari basis data Anda. Dalam kasus kami, server database kami bahkan tidak berkeringat 99% dari waktu dan mereka bahkan belum multi-core atau salah satu dari banyak sekali peningkatan lainnya untuk arsitektur sistem yang terjadi setiap 6 bulan. Untuk alasan ini saja, memiliki database kami menangani penyortiran tidak akan menjadi masalah. Selain itu, basis data sangatpandai menyortir. Mereka dioptimalkan untuk itu dan telah bertahun-tahun untuk melakukannya dengan benar, bahasa untuk melakukannya sangat fleksibel, intuitif, dan sederhana dan di atas semua penulis SQL pemula tahu bagaimana melakukannya dan bahkan lebih penting lagi mereka tahu cara mengeditnya, membuat perubahan, melakukan pemeliharaan, dll. Ketika database Anda jauh dari pajak dan Anda hanya ingin menyederhanakan (dan mempersingkat!) waktu pengembangan ini sepertinya pilihan yang jelas.

Lalu ada masalah web. Saya telah bermain-main dengan JavaScript yang akan melakukan pemilahan tabel HTML sisi klien, tetapi mereka pasti tidak cukup fleksibel untuk kebutuhan saya dan, sekali lagi, karena basis data saya tidak dikenai pajak dan dapat melakukan pengurutan dengan sangat mudah, saya mengalami kesulitan membenarkan waktu yang diperlukan untuk menulis ulang atau menyortir penyortir JavaScript saya sendiri. Hal yang sama berlaku untuk penyortiran sisi server, meskipun mungkin sudah lebih disukai daripada JavaScript. Saya bukan orang yang suka overhead DataSets, jadi tuntut saya.

Tetapi ini membawa kembali poin bahwa itu tidak mungkin - atau lebih tepatnya, tidak mudah. Saya telah melakukan, dengan sistem sebelumnya, cara hack yang luar biasa untuk mendapatkan penyortiran dinamis. Itu tidak cantik, tidak intuitif, sederhana, atau fleksibel dan penulis SQL pemula akan hilang dalam hitungan detik. Sudah mencari bukan "solusi" tapi "komplikasi."


Contoh-contoh berikut ini tidak dimaksudkan untuk mengekspos segala praktik terbaik atau gaya pengkodean yang baik atau apa pun, juga tidak menunjukkan kemampuan saya sebagai programmer T-SQL. Mereka adalah apa adanya dan saya sepenuhnya mengakui mereka membingungkan, bentuk buruk, dan sekadar peretasan.

Kami meneruskan nilai integer sebagai parameter ke prosedur tersimpan (sebut saja parameter "sort") dan dari situ kami menentukan banyak variabel lain. Misalnya ... katakanlah sort adalah 1 (atau default):

DECLARE @sortCol1 AS varchar(20)
DECLARE @sortCol2 AS varchar(20)
DECLARE @dir1 AS varchar(20)
DECLARE @dir2 AS varchar(20)
DECLARE @col1 AS varchar(20)
DECLARE @col2 AS varchar(20)

SET @col1 = 'storagedatetime';
SET @col2 = 'vehicleid';

IF @sort = 1                -- Default sort.
BEGIN
    SET @sortCol1 = @col1;
    SET @dir1 = 'asc';
    SET @sortCol2 = @col2;
    SET @dir2 = 'asc';
END
ELSE IF @sort = 2           -- Reversed order default sort.
BEGIN
    SET @sortCol1 = @col1;
    SET @dir1 = 'desc';
    SET @sortCol2 = @col2;
    SET @dir2 = 'desc';
END

Anda sudah dapat melihat bagaimana jika saya mendeklarasikan lebih banyak variabel @colX untuk mendefinisikan kolom lain, saya benar-benar bisa berkreasi dengan kolom untuk mengurutkan berdasarkan nilai "sort" ... untuk menggunakannya, biasanya berakhir seperti berikut ini. klausa yang sangat berantakan:

ORDER BY
    CASE @dir1
        WHEN 'desc' THEN
            CASE @sortCol1
                WHEN @col1 THEN [storagedatetime]
                WHEN @col2 THEN [vehicleid]
            END
    END DESC,
    CASE @dir1
        WHEN 'asc' THEN
            CASE @sortCol1
                WHEN @col1 THEN [storagedatetime]
                WHEN @col2 THEN [vehicleid]
            END
    END,
    CASE @dir2
        WHEN 'desc' THEN
            CASE @sortCol2
                WHEN @col1 THEN [storagedatetime]
                WHEN @col2 THEN [vehicleid]
            END
    END DESC,
    CASE @dir2
        WHEN 'asc' THEN
            CASE @sortCol2
                WHEN @col1 THEN [storagedatetime]
                WHEN @col2 THEN [vehicleid]
            END
    END

Jelas ini adalah contoh yang sangat sederhana. Hal-hal nyata, karena kami biasanya memiliki empat atau lima kolom untuk mendukung penyortiran, masing-masing dengan kemungkinan kolom kedua atau bahkan ketiga untuk disortir di samping itu (misalnya tanggal turun lalu disortir secara sekunder dengan nama naik) dan masing-masing mendukung dua pengurutan terarah yang secara efektif menggandakan jumlah kasus. Ya ... rambut itu menjadi sangat cepat.

Idenya adalah bahwa seseorang dapat "dengan mudah" mengubah kasus semacam itu sehingga vehicleid bisa disortir sebelum masa penyimpanan ... tetapi fleksibilitas semu, setidaknya dalam contoh sederhana ini, benar-benar berakhir di sana. Pada dasarnya, setiap kasus yang gagal tes (karena metode pengurutan kami tidak berlaku untuk kali ini) memberikan nilai NULL. Dan akhirnya Anda memiliki klausa yang berfungsi seperti berikut:

ORDER BY NULL DESC, NULL, [storagedatetime] DESC, blah blah

Anda mendapatkan idenya. Ini berfungsi karena SQL Server secara efektif mengabaikan nilai null dalam urutan klausa. Ini sangat sulit untuk dipertahankan, karena siapa pun yang memiliki pengetahuan dasar SQL mungkin bisa melihatnya. Jika saya kehilangan salah satu dari Anda, jangan merasa buruk. Kami butuh waktu lama untuk membuatnya berfungsi dan kami masih bingung mencoba mengeditnya atau membuat yang baru seperti itu. Untungnya itu tidak perlu sering berubah, kalau tidak cepat akan menjadi "tidak sepadan dengan masalah."

Namun melakukan pekerjaan.


Pertanyaan saya kemudian: apakah ada cara yang lebih baik?

Saya baik-baik saja dengan solusi selain yang Disimpan Prosedur, karena saya menyadari itu mungkin bukan jalan untuk pergi. Lebih disukai, saya ingin tahu apakah ada yang bisa melakukannya dengan lebih baik dalam Prosedur Tersimpan, tetapi jika tidak, bagaimana Anda semua menangani membiarkan pengguna secara dinamis mengurutkan tabel data (dua arah juga) dengan ASP.NET?

Dan terima kasih telah membaca (atau setidaknya membaca sepintas lalu) pertanyaan panjang!

PS: Senang saya tidak menunjukkan contoh saya tentang prosedur tersimpan yang mendukung penyortiran dinamis, penyaringan dinamis / pencarian teks kolom, pagination melalui ROWNUMBER () LEBIH, DAN coba ... tangkap dengan transaksi rollbacking pada kesalahan ... "ukuran raksasa" bahkan tidak mulai menggambarkannya.


Memperbarui:

  • Saya ingin menghindari SQL dinamis . Parsing string bersama-sama dan menjalankan EXEC di atasnya mengalahkan banyak tujuan memiliki prosedur tersimpan di tempat pertama. Kadang-kadang saya bertanya-tanya apakah jika melakukan hal seperti itu tidak akan sepadan, setidaknya dalam kasus penyortiran dinamis khusus ini. Namun, saya selalu merasa kotor setiap kali saya melakukan string SQL dinamis seperti itu - seperti saya masih hidup di dunia ASP Klasik.
  • Banyak alasan kami ingin prosedur tersimpan di tempat pertama adalah untuk keamanan . Saya tidak bisa membuat panggilan pada masalah keamanan, hanya menyarankan solusi. Dengan SQL Server 2005 kita dapat mengatur izin (berdasarkan per pengguna jika perlu) di tingkat skema pada masing-masing prosedur yang tersimpan dan kemudian menolak setiap pertanyaan terhadap tabel secara langsung. Mengkritik pro dan kontra dari pendekatan ini mungkin untuk pertanyaan lain, tetapi sekali lagi itu bukan keputusan saya. Saya hanya monyet kode utama. :)

Referensikan stackoverflow.com/questions/3659981/… juga - SQL Server dynamic ORDER BY dengan tipe data campuran
LCJ

Dynamic SQL adalah cara JAUH unggul ... JIKA [dan ini adalah JIKA besar] .. Lapisan Akses Data Anda ketat dan SQL dinamis Anda dihasilkan oleh sistem yang diprogram secara kaku dengan aturan RDBMS yang dinyatakan dalam bentuk sempurna. Arsitektur Database yang Direkayasa secara Algoritm adalah sesuatu yang indah ...
hajikelist

Jawaban:


97

Ya, itu menyebalkan, dan cara Anda melakukannya mirip dengan apa yang saya lakukan:

order by
case when @SortExpr = 'CustomerName' and @SortDir = 'ASC' 
    then CustomerName end asc, 
case when @SortExpr = 'CustomerName' and @SortDir = 'DESC' 
    then CustomerName end desc,
...

Bagi saya, ini masih jauh lebih baik daripada membangun SQL dinamis dari kode, yang berubah menjadi skalabilitas dan pemeliharaan mimpi buruk untuk DBA.

Apa yang saya lakukan dari kode adalah refactor halaman dan penyortiran jadi saya setidaknya tidak memiliki banyak pengulangan di sana dengan mengisi nilai untuk @SortExprdan @SortDir.

Sejauh menyangkut SQL, pertahankan desain dan format yang sama antara berbagai prosedur tersimpan, jadi setidaknya rapi dan dapat dikenali saat Anda masuk untuk membuat perubahan.


1
Persis. Tujuan saya adalah untuk menghindari melakukan perintah EXEC pada 5000 varchar string yang besar. Semua yang kami lakukan harus dilakukan melalui prosedur tersimpan jika hanya untuk keamanan tambahan karena kami dapat menetapkan izin pada mereka di tingkat skema. Peningkatan skalabilitas dan kinerja hanyalah nilai tambah dalam kasus kami.
Sean Hanley

1
Tambahkan rawatan ke {keamanan, skalabilitas, kinerja}. Setelah Anda memiliki 3 atau 4 aplikasi di luar sana dengan SQL dinamis yang berjalan melawan DB, Anda kacau, Anda tidak dapat mengubah apa pun, terutama karena usia aplikasi dan pengembang terus berjalan. Sql Exec dan dinamis adalah jahat.
Eric Z Beard

Itu saja --- kami sudah melakukannya, dari jauh sebelum saya tiba di sini, untuk semua aplikasi web Classic ASP yang masih berjalan dan banyak, banyak aplikasi Access VB yang masih beredar. Saya berkedut dan harus menahan dorongan untuk memperbaiki kesalahan mencolok setiap kali saya harus melakukan pemeliharaan pada salah satu dari mereka.
Sean Hanley

1
Ini adalah apa yang saya lakukan juga, kecuali saya menyandikan arah ke dalam SortExpr: PESANAN DENGAN KASUS KETIKA sort = 'FirstName' KEMUDIAN FirstName END ASC, KASUS KETIKA sort = '-FirstName' KEMUDIAN FirstName END DESC
Michael Bray

Ini adalah mimpi buruk bagi para DBA dan insinyur perangkat lunak. Jadi alih-alih mampu memiliki sistem yang dinamis namun ketat yang menghasilkan pernyataan SQL ekspresif berdasarkan skema informasi Anda, Anda memiliki gumpalan menjijikkan dari hardcoded omong kosong yang menjijikkan ini. Pemrograman yang buruk itu yang terbaik.
hajikelist

23

Pendekatan ini menjaga kolom yang dapat disortir dari digandakan dua kali dalam urutan oleh, dan sedikit lebih mudah dibaca IMO:

SELECT
  s.*
FROM
  (SELECT
    CASE @SortCol1
      WHEN 'Foo' THEN t.Foo
      WHEN 'Bar' THEN t.Bar
      ELSE null
    END as SortCol1,
    CASE @SortCol2
      WHEN 'Foo' THEN t.Foo
      WHEN 'Bar' THEN t.Bar
      ELSE null
    END as SortCol2,
    t.*
  FROM
    MyTable t) as s
ORDER BY
  CASE WHEN @dir1 = 'ASC'  THEN SortCol1 END ASC,
  CASE WHEN @dir1 = 'DESC' THEN SortCol1 END DESC,
  CASE WHEN @dir2 = 'ASC'  THEN SortCol2 END ASC,
  CASE WHEN @dir2 = 'DESC' THEN SortCol2 END DESC

Ini sepertinya jawaban yang bagus tapi sepertinya tidak berfungsi ketika kolom yang diurutkan memiliki tipe data yang berbeda
SlimSim


6

Aplikasi saya banyak melakukan ini tetapi mereka semua secara dinamis membangun SQL. Namun, ketika saya berurusan dengan prosedur tersimpan saya melakukan ini:

  1. Jadikan prosedur tersimpan sebagai fungsi yang mengembalikan tabel nilai Anda - tanpa sortir.
  2. Kemudian dalam kode aplikasi Anda, lakukan select * from dbo.fn_myData() where ... order by ...sehingga Anda dapat menentukan urutan sortir secara dinamis di sana.

Maka setidaknya bagian dinamis ada di aplikasi Anda, tetapi database masih melakukan tugas berat.


1
Itu mungkin kompromi terbaik yang pernah saya lihat antara menggunakan SQL dinamis dan prosedur tersimpan bersama. Saya suka itu. Saya mungkin bereksperimen kadang-kadang dengan pendekatan yang serupa, tetapi perubahan seperti itu akan menjadi penghalang dalam proyek kami yang sedang berjalan.
Sean Hanley

1
Anda dapat mencapai hal yang sama menggunakan variabel tabel lokal alih-alih fungsi tabel mengembalikan data. Saya menemukan tabel lokal lebih fleksibel daripada fungsi, karena Anda dapat menampilkan beberapa informasi debug.
Sanjay Zalke

5

Teknik prosedur tersimpan (hack?) Saya telah menggunakan untuk menghindari SQL dinamis untuk pekerjaan tertentu adalah memiliki kolom semacam unik. Yaitu,

SELECT
   name_last,
   name_first,
   CASE @sortCol WHEN 'name_last' THEN [name_last] ELSE 0 END as mySort
FROM
   table
ORDER BY 
    mySort

Yang satu ini mudah dikalahkan dalam pengiriman - Anda dapat menggabungkan bidang di kolom mySort Anda, membalik urutan dengan fungsi matematika atau tanggal, dll

Lebih disukai, saya menggunakan tampilan jaringan asp.net saya atau objek lain dengan penyortiran bawaan untuk melakukan penyortiran bagi saya SETELAH mengambil data dari Sql-Server. Atau bahkan jika itu bukan built-in - misalnya, datatables, dll di asp.net.


4

Ada beberapa cara berbeda untuk meretas ini.

Prasyarat:

  1. Hanya satu pernyataan SELECT di sp
  2. Tinggalkan penyortiran apa pun (atau memiliki default)

Kemudian masukkan ke tabel temp:

create table #temp ( your columns )

insert #temp
exec foobar

select * from #temp order by whatever

Metode # 2: mengatur server tertaut kembali ke dirinya sendiri, lalu pilih dari ini menggunakan openquery: http://www.sommarskog.se/share_data.html#OPENQUERY


4

Mungkin ada opsi ketiga, karena server Anda memiliki banyak siklus cadangan - gunakan prosedur pembantu untuk melakukan penyortiran melalui tabel sementara. Sesuatu seperti

create procedure uspCallAndSort
(
    @sql varchar(2048),        --exec dbo.uspSomeProcedure arg1,'arg2',etc.
    @sortClause varchar(512)    --comma-delimited field list
)
AS
insert into #tmp EXEC(@sql)
declare @msql varchar(3000)
set @msql = 'select * from #tmp order by ' + @sortClause
EXEC(@msql)
drop table #tmp
GO

Peringatan: Saya belum menguji ini, tetapi "harus" bekerja di SQL Server 2005 (yang akan membuat tabel sementara dari hasil yang ditetapkan tanpa menentukan kolom di muka.)


2

Pada titik tertentu, tidakkah menjadi layak untuk beralih dari prosedur tersimpan dan hanya menggunakan kueri yang diparameterisasi untuk menghindari peretasan semacam ini?


1
Dalam kasus-kasus tertentu mungkin mereka adalah palu godam, tetapi seringkali kita ingin mengatur izin (khususnya EXECUTE) pada prosedur yang tersimpan dan tidak mengizinkan query SQL langsung terhadap tabel, bahkan SELECT. Saya juga tidak terlalu suka peretasan, tetapi keamanan bukanlah panggilan saya untuk melakukannya.
Sean Hanley

1
Inilah sebabnya mengapa begitu banyak orang yang pindah ke Object Relational Mapping. Perjalanan bolak-balik yang tidak perlu untuk menyortir, blok KASUS besar untuk pembaruan yang sama, tidak masuk akal untuk banyak kolom ketika benar-benar hanya satu yang perlu diperbarui, dll. Argumen yang menang untuk prosedur tersimpan yang masih tersisa adalah keamanan.
Pittsburgh DBA

Saya pindah dari ORM (EF) ke prosedur tersimpan karena ORM tidak mendukung pencarian teks lengkap.
Ronnie Overby

@RonnieOverby Pencarian teks lengkap seringkali lebih baik dilayani oleh solusi khusus, misalnya, Lucene.
Hank Gay

@HankGay Saya punya perasaan aneh bahwa kerangka kerja entitas juga tidak mendukung Lucene.
Ronnie Overby

2

Saya setuju, gunakan sisi klien. Tapi sepertinya itu bukan jawaban yang ingin Anda dengar.

Jadi, itu sempurna sebagaimana adanya. Saya tidak tahu mengapa Anda ingin mengubahnya, atau bahkan bertanya, "Apakah ada cara yang lebih baik." Sungguh, itu harus disebut "Jalan". Selain itu, tampaknya berfungsi dan sesuai dengan kebutuhan proyek dengan baik dan mungkin akan cukup panjang untuk tahun-tahun mendatang. Karena basis data Anda tidak dikenai pajak dan pengurutan benar-benar mudah, itu harus tetap seperti itu selama bertahun-tahun yang akan datang.

Saya tidak akan berkeringat.


Saya tidak punya masalah dengan sisi klien, karena saya menempuh rute itu dengan aplikasi Windows. Tetapi bagaimana dengan aplikasi web? Saya tidak menemukan banyak solusi JavaScript yang cukup fleksibel. Dan ya, itu berfungsi seperti yang saya katakan seperti yang kita miliki, tapi itu mimpi buruk SQL. Tentu saja saya ingin tahu apakah ada cara yang lebih baik.
Sean Hanley

Itu dibangun ke dalam kontrol .NET yang lebih baru (2.0 dan lebih tinggi). Atau Anda dapat membuat sendiri dan menerapkannya ke tampilan data. msdn.microsoft.com/en-us/library/hwf94875(VS.80).aspx
DS

2
Masalah saya kemudian adalah skalabilitas dan kinerja. Melakukan penyortiran sisi-klien atau sisi-server memerlukan pemuatan semua data, bukan hanya 10 atau 15 yang akan Anda tampilkan pada satu halaman pada satu waktu. Ini sangat mahal, dalam jangka panjang, sedangkan penyortiran basis data tidak memilikinya.
Sean Hanley

2

Ketika Anda paging hasil diurutkan, SQL dinamis adalah pilihan yang baik. Jika Anda paranoid tentang injeksi SQL, Anda dapat menggunakan nomor kolom alih-alih nama kolom. Saya sudah melakukan ini sebelum menggunakan nilai negatif untuk turun. Sesuatu seperti ini...

declare @o int;
set @o = -1;

declare @sql nvarchar(2000);
set @sql = N'select * from table order by ' + 
    cast(abs(@o) as varchar) + case when @o < 0 then ' desc' else ' asc' end + ';'

exec sp_executesql @sql

Maka Anda hanya perlu memastikan nomornya ada di dalam 1 hingga # kolom. Anda bahkan dapat memperluas ini ke daftar nomor kolom dan menguraikannya ke dalam tabel int menggunakan fungsi seperti ini . Maka Anda akan membangun pesanan dengan klausa seperti ...

declare @cols varchar(100);
set @cols = '1 -2 3 6';

declare @order_by varchar(200)

select @order_by = isnull(@order_by + ', ', '') + 
        cast(abs(number) as varchar) + 
        case when number < 0 then ' desc' else '' end
from dbo.iter_intlist_to_tbl(@cols) order by listpos

print @order_by

Salah satu kelemahannya adalah Anda harus mengingat urutan setiap kolom di sisi klien. Terutama, ketika Anda tidak menampilkan semua kolom atau Anda menampilkannya dalam urutan yang berbeda. Ketika klien ingin menyortir, Anda memetakan nama kolom ke urutan kolom dan menghasilkan daftar int.


Kami menggunakan sp_executesql untuk membangun kueri pelaporan dinamis. Sangat efektif. SQL tidak dapat dibangun dari aplikasi, tetapi parameternya hanya dimasukkan jika diperlukan dan dijalankan seperti biasa.
Josh Smeaton,

2

Argumen yang menentang melakukan pengurutan di sisi klien adalah data volume besar dan pagination. Setelah jumlah baris melampaui apa yang dapat Anda tampilkan dengan mudah, Anda sering menyortir sebagai bagian dari lompatan / ambil, yang mungkin ingin Anda jalankan dalam SQL.

Untuk Kerangka Entity, Anda bisa menggunakan prosedur tersimpan untuk menangani pencarian teks Anda. Jika Anda mengalami masalah pengurutan yang sama, solusi yang saya lihat adalah menggunakan proc yang disimpan untuk pencarian, hanya mengembalikan kunci id yang ditetapkan untuk pertandingan. Selanjutnya, permintaan ulang (dengan pengurutan) terhadap db menggunakan id dalam daftar (berisi). EF menangani ini dengan cukup baik, bahkan ketika set ID cukup besar. Ya, ini adalah dua perjalanan bolak-balik, tetapi memungkinkan Anda untuk selalu menyortir dalam DB, yang dapat menjadi penting dalam beberapa situasi, dan mencegah Anda dari menulis muatan logika dalam prosedur yang tersimpan.


1

Bagaimana dengan penanganan pengurutan pada hal-hal yang menampilkan hasil - kisi, laporan, dll, bukan pada SQL?

EDIT:

Untuk memperjelas hal-hal sejak jawaban ini dipilih sebelumnya, saya akan menguraikan sedikit ...

Anda menyatakan Anda tahu tentang penyortiran sisi klien tetapi ingin menghindari itu. Itu panggilan Anda, tentu saja.

Apa yang ingin saya tunjukkan adalah dengan melakukannya di sisi klien, Anda dapat menarik data SEKALI dan kemudian bekerja dengannya sesuka Anda - dibandingkan melakukan beberapa perjalanan bolak-balik ke server setiap kali semacam itu berubah.

SQL Server Anda tidak dikenakan pajak sekarang dan itu luar biasa. Seharusnya tidak. Tetapi hanya karena itu tidak kelebihan beban namun tidak berarti bahwa itu akan tetap seperti itu selamanya.

Jika Anda menggunakan salah satu dari hal-hal ASP.NET yang lebih baru untuk ditampilkan di web, banyak hal yang sudah dipanggang.

Apakah perlu menambahkan begitu banyak kode ke setiap prosedur tersimpan hanya untuk menangani penyortiran? Sekali lagi, teleponmu.

Saya bukan orang yang pada akhirnya akan bertanggung jawab untuk mendukungnya. Tetapi pikirkan apa yang akan terlibat ketika kolom ditambahkan / dihapus dalam berbagai dataset yang digunakan oleh prosedur tersimpan (membutuhkan modifikasi pada pernyataan KASUS) atau ketika tiba-tiba alih-alih menyortir oleh dua kolom, pengguna memutuskan mereka membutuhkan tiga - mengharuskan Anda untuk memperbarui semua prosedur tersimpan Anda yang menggunakan metode ini.

Bagi saya, itu layak untuk mendapatkan solusi sisi klien yang berfungsi dan menerapkannya pada beberapa tampilan data yang dihadapi pengguna dan dilakukan dengan itu. Jika kolom baru ditambahkan, itu sudah ditangani. Jika pengguna ingin mengurutkan berdasarkan beberapa kolom, mereka dapat mengurutkannya dengan dua atau dua puluh kolom.


Itu akan menjadi cara yang benar, tetapi tidak dianggap "cara yang lebih baik"
DS

Karena saat itu saya masih menulis pengurutan saya sendiri di C # atau JavaScript dan sepertinya itu akan menjadi jauh lebih mudah dan lebih cepat dalam SQL. Demikian pertanyaan saya. Apakah saya hanya melewatkan sesuatu yang jelas atau apakah kita terjebak menulis penyortiran khusus kita sendiri (dalam C # atau JavaScript) setiap aplikasi sialan yang kita kerjakan?
Sean Hanley

3
Tunggu, bagaimana dengan set hasil dengan puluhan ribu baris? Anda tidak dapat mengembalikan semua data itu ke klien. Anda harus melakukan paging dan mengurutkan pada database.
Eric Z Beard

Yadyn, mengerti. Tetapi begitu Anda memiliki penyortir generik untuk kisi-kisi Anda, Anda hanya menggunakannya untuk semua barang Anda.
Kevin Fairchild

Eric, Benar ... Dalam kasus seperti itu, Anda perlu penanganan ekstra dan mungkin masuk akal dalam SQL. Itu jauh dari masalah benar vs salah. Dalam beberapa kasus, akan masuk akal untuk SQL dan beberapa kasus, pada klien.
Kevin Fairchild

1

Maaf saya terlambat ke pesta, tapi di sini ada pilihan lain bagi mereka yang benar-benar ingin menghindari SQL dinamis, tetapi menginginkan fleksibilitas yang ditawarkannya:

Alih-alih secara dinamis menghasilkan SQL on the fly, tulis kode untuk menghasilkan proc unik untuk setiap variasi yang mungkin. Kemudian Anda dapat menulis metode dalam kode untuk melihat opsi pencarian dan memilihnya untuk memanggil proc.

Jika Anda hanya memiliki beberapa variasi maka Anda cukup membuat procs dengan tangan. Tetapi jika Anda memiliki banyak variasi maka alih-alih harus mempertahankan semuanya, Anda hanya perlu mempertahankan generator proc Anda untuk membuatnya membuatnya kembali.

Sebagai manfaat tambahan, Anda akan mendapatkan paket SQL yang lebih baik untuk kinerja yang lebih baik melakukannya dengan cara ini juga.


-1

Solusi ini mungkin hanya bekerja di .NET, saya tidak tahu.

Saya mengambil data ke dalam C # dengan urutan pengurutan awal dalam urutan SQL oleh klausa, memasukkan data itu ke dalam DataView, menyimpannya dalam variabel Sesi, dan menggunakannya untuk membangun halaman.

Ketika pengguna mengklik pada judul kolom untuk mengurutkan (atau halaman, atau filter), saya tidak kembali ke database. Sebagai gantinya, saya kembali ke DataView yang di-cache dan mengatur properti "Sort" ke ekspresi yang saya buat secara dinamis, sama seperti saya akan dinamis SQL. (Saya melakukan penyaringan dengan cara yang sama, menggunakan properti "RowFilter").

Anda dapat melihat / merasakannya berfungsi dalam demo aplikasi saya, BugTracker.NET, di http://ifdefined.com/btnet/bugs.aspx


MANIS! Pelacak bug. NET rock!
digiguru

-7

Anda harus menghindari penyortiran SQL Server, kecuali jika perlu. Mengapa tidak mengurutkan pada server aplikasi atau sisi klien? Juga .NET Generics melakukan sortin yang luar biasa


6
Karena skalabilitas. Tidak apa-apa untuk beberapa ribu baris, tetapi saya tidak ingin menarik sepuluh ribu baris dan menyortirnya. Atau lebih. Juga, bagaimana dengan paging? Saya sering hanya ingin menarik apa yang perlu saya tampilkan. Menyortir baris 21-30 dari 24056 setelah faktanya akan salah.
Sean Hanley
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.