Bu, geçmişte araştırmak için saatler harcadığım bir konu. Bana öyle geliyor ki, modern RDBMS çözümleri tarafından ele alınması gereken bir şey var, ancak henüz veritabanı arka uçlu herhangi bir Web veya Windows uygulamasında inanılmaz derecede yaygın bir ihtiyaç olarak gördüğüm şeyi gerçekten karşılayan hiçbir şey bulamadım.
Dinamik sıralamadan bahsediyorum. Benim fantezi dünyamda, şöyle bir şey kadar basit olmalı:
ORDER BY @sortCol1, @sortCol2
Bu, yeni başlayan SQL ve Depolanan Prosedür geliştiricileri tarafından İnternet'in her yerinde forumlarda verilen kanonik örnektir . "Bu neden mümkün değil?" onlar sorar. Değişmez bir şekilde, birileri sonunda onlara depolanmış yordamların, genel olarak yürütme planlarının derlenmiş doğası ve bir parametreyi doğrudan bir ORDER BY
maddeye koymanın mümkün olmadığı her türden diğer nedenler hakkında ders vermek için gelir .
Bazılarınızın halihazırda ne düşündüğünü biliyorum: "Öyleyse, müşteri sıralamayı yapsın." Doğal olarak, bu işi veritabanınızdan kaldırır. Yine de bizim durumumuzda, veritabanı sunucularımız zamanın% 99'unda ter bile atmıyor ve henüz çok çekirdekli değiller veya her 6 ayda bir sistem mimarisinde yapılan diğer sayısız iyileştirmelerden hiçbiri. Bu nedenle tek başına, veritabanlarımızın sıralamayı ele alması sorun olmaz. Ek olarak, veritabanları çoksıralama konusunda iyi. Bunun için optimize edilmişlerdir ve doğru yapmak için yılları olmuştur, bunu yapmak için kullanılan dil inanılmaz derecede esnek, sezgisel ve basittir ve hepsinden önemlisi, yeni başlayan herhangi bir SQL yazarı bunu nasıl yapacağını bilir ve daha da önemlisi onu nasıl düzenleyeceğini bilir, değişiklikler yapın, bakım yapın, vb. Veritabanlarınız vergilendirilmekten uzaksa ve yalnızca geliştirme süresini basitleştirmek (ve kısaltmak!) istiyorsanız, bu bariz bir seçim gibi görünüyor.
Sonra web sorunu var. HTML tablolarının istemci tarafında sıralanmasını sağlayacak JavaScript ile oynadım, ancak bunlar kaçınılmaz olarak ihtiyaçlarım için yeterince esnek değiller ve yine, veritabanlarım fazla vergilendirilmediğinden ve gerçekten kolayca sıralama yapabildiğinden , ben Kendi JavaScript sıralayıcımı yeniden yazmak veya almak için gereken zamanı haklı çıkarmada güçlük çekiyorum. Aynı durum genellikle sunucu tarafında sıralama için de geçerlidir, ancak muhtemelen JavaScript'e göre daha çok tercih edilmektedir. DataSets'in ek yükünü özellikle beğenen biri değilim, bu yüzden beni dava et.
Ancak bu, mümkün olmadığı veya daha doğrusu kolay olmadığı noktasını geri getiriyor. Önceki sistemlerle, dinamik sıralama elde etmenin inanılmaz derecede hacklenmiş bir yolunu yaptım. Güzel, sezgisel, basit veya esnek değildi ve yeni başlayan bir SQL yazarı saniyeler içinde kaybolurdu. Zaten bu bir "çözüm" değil, bir "karmaşıklık" olarak görünüyor.
Aşağıdaki örnekler, herhangi bir tür en iyi uygulamayı veya iyi kodlama stilini veya herhangi bir şeyi ortaya çıkarmayı amaçlamaz veya bir T-SQL programcısı olarak yeteneklerimi göstermez. Onlar oldukları gibi ve kafa karıştırıcı, kötü formda ve sadece basit bir hack olduklarını tamamen itiraf ediyorum.
Depolanmış bir prosedüre parametre olarak bir tamsayı değeri iletiriz (parametreyi sadece "sırala" diyelim) ve bundan bir grup başka değişken belirleriz. Örneğin ... sıralamanın 1 (veya varsayılan) olduğunu varsayalım:
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
Diğer sütunları tanımlamak için daha fazla @colX değişkeni bildirmişsem, "sırala" değerine göre sıralama yapmak için sütunlarla gerçekten yaratıcı olabileceğimi zaten görebilirsiniz ... kullanmak için, genellikle aşağıdaki gibi görünür inanılmaz derecede dağınık madde:
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
Açıkçası bu çok sade bir örnek. Gerçek şeyler, sıralamayı desteklemek için genellikle dört veya beş sütuna sahip olduğumuz için, her biri buna ek olarak sıralamak için olası ikincil veya hatta üçüncü bir sütun (örneğin, azalan tarih sonra ikinci olarak ad artan şekilde sıralanır) ve her birini destekleyen iki sütun vaka sayısını etkili bir şekilde ikiye katlayan yönlü sıralama. Evet ... çok çabuk kıllı oluyor.
Buradaki fikir, araç kimliğinin depolama süresinden önce sıralanacağı şekilde sıralama durumlarının "kolayca" değiştirilebilmesidir ... ancak sözde esneklik, en azından bu basit örnekte, gerçekten burada biter. Esasen, bir testi geçemeyen her durum (çünkü bizim sıralama yöntemimiz bu sefer onun için geçerli değildir) bir NULL değeri verir. Ve böylece aşağıdaki gibi işleyen bir cümle ile sonuçlanırsınız:
ORDER BY NULL DESC, NULL, [storagedatetime] DESC, blah blah
Kaptın bu işi. Çalışır çünkü SQL Server, cümleciklere göre sırayla boş değerleri yok sayar. Temel SQL çalışma bilgisine sahip herkesin muhtemelen görebileceği gibi, bunu sürdürmek inanılmaz derecede zordur. Herhangi birinizi kaybedersem, kendinizi kötü hissetmeyin. Çalışması uzun zamanımızı aldı ve onu düzenlemeye veya buna benzer yenilerini oluşturmaya çalışırken hala kafamız karışıyor. Neyse ki sık sık değişmesi gerekmiyor, aksi takdirde çabucak "zahmete değmez" hale gelirdi.
Yine de işe yaradı .
O zaman sorum şu: daha iyi bir yol var mı?
Depolanan Prosedür dışındaki çözümlerde sorun yok, çünkü bunun gidecek yol olmayabileceğinin farkındayım. Tercihen, herhangi birinin Depolanan Prosedür içinde bunu daha iyi yapıp yapamayacağını bilmek isterim, ancak değilse, kullanıcının ASP.NET ile veri tablolarını dinamik olarak (çift yönlü olarak da) sıralamasına izin vermeyi nasıl başaracaksınız?
Ve bu kadar uzun bir soruyu okuduğunuz (veya en azından gözden geçirdiğiniz) için teşekkür ederiz!
Not: Dinamik sıralamayı, dinamik filtrelemeyi / sütunların metin aramasını, ROWNUMBER () OVER aracılığıyla sayfalandırmayı destekleyen VE deneyin ... hatalarda işlem geri alma ile yakala ... "Devasa boyutta" onları tanımlamaya bile başlamaz.
Güncelleme:
- Dinamik SQL'den kaçınmak istiyorum . Bir dizeyi birlikte ayrıştırmak ve üzerinde bir EXEC çalıştırmak, ilk etapta bir saklı yordama sahip olma amacının çoğunu ortadan kaldırır. Bazen böyle bir şeyi yapmanın eksilerinin buna değip değmeyeceğini merak ediyorum, en azından bu özel dinamik sıralama durumlarında. Yine de, böyle dinamik SQL dizeleri yaptığımda her zaman kendimi kirli hissediyorum - sanki hala Klasik ASP dünyasında yaşıyormuşum gibi.
- Depolanan prosedürleri ilk etapta istememizin birçok nedeni güvenlik içindir . Güvenlik endişeleri için arama yapmıyorum, sadece çözüm öneriyorum. SQL Server 2005 ile ayrı saklı yordamlarda şema düzeyinde izinler (gerekirse kullanıcı bazında) ayarlayabilir ve ardından tablolara yönelik herhangi bir sorguyu doğrudan reddedebiliriz. Bu yaklaşımın artılarını ve eksilerini eleştirmek belki başka bir soru için olabilir, ama yine de bu benim kararım değil. Ben sadece baş kod maymuyum. :)