Dynamiczne sortowanie w ramach procedur składowanych SQL

126

Jest to problem, nad którym w przeszłości spędziłem godziny. Wydaje mi się, że jest to coś, co powinno było zostać rozwiązane przez nowoczesne rozwiązania RDBMS , ale jak dotąd nie znalazłem niczego, co naprawdę odnosi się do tego, co uważam za niezwykle powszechną potrzebę w dowolnej aplikacji internetowej lub Windows z zapleczem bazy danych.

Mówię o sortowaniu dynamicznym. W moim świecie fantasy powinno to być tak proste, jak coś takiego:

ORDER BY @sortCol1, @sortCol2

Jest to kanoniczny przykład podawany przez początkujących programistów SQL i procedur składowanych na forach w Internecie. "Dlaczego nie jest to możliwe?" pytają. Niezmiennie ktoś w końcu przychodzi, aby pouczyć ich o skompilowanej naturze procedur składowanych, ogólnie o planach wykonania i wielu innych powodach, dla których nie jest możliwe umieszczenie parametru bezpośrednio w ORDER BYklauzuli.


Wiem, co niektórzy z was już sobie myślą: „Pozwól więc klientowi sortować”. Oczywiście odciąża to pracę bazy danych. Jednak w naszym przypadku nasze serwery bazodanowe nie są nawet obciążone w 99% przypadków, a nawet nie są jeszcze wielordzeniowe ani nie są żadnymi innymi niezliczonymi ulepszeniami architektury systemu, które mają miejsce co 6 miesięcy. Tylko z tego powodu posiadanie przez nasze bazy danych obsługi sortowania nie byłoby problemem. Dodatkowo bazy danych są bardzodobry w sortowaniu. Są pod tym kątem zoptymalizowane i mieli lata, aby to zrobić dobrze, język do tego jest niesamowicie elastyczny, intuicyjny i prosty, a przede wszystkim każdy początkujący pisarz SQL wie, jak to zrobić, a co ważniejsze, umie go edytować wprowadzać zmiany, konserwować itp. Gdy Twoje bazy danych są dalekie od opodatkowania i chcesz po prostu uprościć (i skrócić!) czas programowania, wydaje się to oczywistym wyborem.

Jest też problem z siecią. Bawiłem się JavaScriptem, który wykonuje sortowanie tabel HTML po stronie klienta, ale nieuchronnie nie są one wystarczająco elastyczne dla moich potrzeb, a ponieważ moje bazy danych nie są nadmiernie opodatkowane i potrafią naprawdę bardzo łatwo sortować, ja Trudno mi uzasadnić czas potrzebny na ponowne napisanie lub zrolowanie własnego sortownika JavaScript. To samo dotyczy generalnie sortowania po stronie serwera, chociaż jest już prawdopodobnie znacznie preferowane niż JavaScript. Nie jestem osobą, która szczególnie lubi narzuty związane z DataSets, więc pozwól mi.

Ale to przypomina, że ​​nie jest to możliwe - a raczej niełatwe. Z poprzednimi systemami zrobiłem niesamowity sposób na uzyskanie dynamicznego sortowania. Nie był ani ładny, ani intuicyjny, prosty ani elastyczny, a początkujący pisarz SQL zostałby stracony w ciągu kilku sekund. Już teraz wygląda to nie tyle na „rozwiązanie”, ale na „komplikację”.


Poniższe przykłady nie mają na celu ujawnienia jakichkolwiek najlepszych praktyk ani dobrego stylu kodowania ani niczego takiego, ani nie wskazują na moje umiejętności jako programisty T-SQL. Są tym, czym są i przyznaję, że są zagmatwane, mają złą formę i są po prostu hackami.

Przekazujemy wartość całkowitą jako parametr do procedury składowanej (nazwijmy parametr po prostu „sort”) i na tej podstawie określamy kilka innych zmiennych. Na przykład ... powiedzmy, że sortowanie to 1 (lub wartość domyślna):

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

Możesz już zobaczyć, jak gdybym zadeklarował więcej zmiennych @colX, aby zdefiniować inne kolumny, naprawdę mógłbym uzyskać kreatywność z kolumnami do sortowania na podstawie wartości „sort”… aby go użyć, zwykle kończy się to następująco niesamowicie niechlujna klauzula:

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

Oczywiście jest to bardzo okrojony przykład. Prawdziwe rzeczy, ponieważ zwykle mamy cztery lub pięć kolumn do obsługi sortowania, każda z ewentualnymi drugorzędnymi lub nawet trzecimi kolumnami do sortowania oprócz tego (na przykład data malejąca, a następnie sortowana wtórnie według nazwy rosnąco) i każda obsługująca bi- sortowanie kierunkowe, które skutecznie podwaja liczbę przypadków. Tak ... bardzo szybko robi się owłosiony.

Chodzi o to, że można „łatwo” zmienić sortowanie przypadków, tak aby identyfikator pojazdu był sortowany przed czasem przechowywania ... ale pseudoelastyczność, przynajmniej w tym prostym przykładzie, naprawdę się kończy. Zasadniczo każdy przypadek, który nie przejdzie testu (ponieważ nasza metoda sortowania nie ma do niego zastosowania tym razem) renderuje wartość NULL. W ten sposób otrzymujesz klauzulę, która działa jak poniżej:

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

Masz pomysł. Działa, ponieważ SQL Server skutecznie ignoruje wartości null w kolejności według klauzul. Jest to niezwykle trudne do utrzymania, co prawdopodobnie zauważy każdy z podstawową wiedzą praktyczną na temat SQL. Jeśli straciłem kogokolwiek z was, nie czuj się źle. Zajęło nam dużo czasu, zanim zaczęło działać, a wciąż jesteśmy zdezorientowani, próbując go edytować lub tworzyć nowe, podobne do tego. Na szczęście nie trzeba go często zmieniać, w przeciwnym razie szybko stałby się „nie wart zachodu”.

A jednak zadziałało.


Moje pytanie brzmi zatem: czy jest lepszy sposób?

Nie przeszkadzają mi rozwiązania inne niż procedury składowane, ponieważ zdaję sobie sprawę, że może to nie być droga. Najlepiej chciałbym wiedzieć, czy ktokolwiek może zrobić to lepiej w ramach procedury składowanej, ale jeśli nie, jak wszyscy poradzicie sobie z umożliwieniem użytkownikowi dynamicznego sortowania tabel danych (również dwukierunkowo) za pomocą ASP.NET?

I dziękuję za przeczytanie (lub przynajmniej przejrzenie) tak długiego pytania!

PS: Ciesz się, że nie pokazałem mojego przykładu procedury składowanej, która obsługuje dynamiczne sortowanie, dynamiczne filtrowanie / wyszukiwanie tekstu kolumn, paginację za pomocą ROWNUMBER () OVER, AND spróbuj ... złapać wycofywanie transakcji na błędach ... „wielkości behemota” nawet nie zaczyna ich opisywać.


Aktualizacja:

  • Chciałbym uniknąć dynamicznego SQL . Parsowanie łańcucha razem i uruchomienie na nim procedury EXEC podważa wiele z celów posiadania procedury składowanej w pierwszej kolejności. Czasami jednak zastanawiam się, czy wady zrobienia czegoś takiego nie byłyby tego warte, przynajmniej w tych specjalnych dynamicznych przypadkach sortowania. Mimo to zawsze czuję się brudny, gdy robię takie dynamiczne ciągi SQL - jakbym nadal żył w świecie klasycznej ASP.
  • Głównym powodem, dla którego chcemy, aby procedury składowane były przede wszystkim, jest bezpieczeństwo . Nie mogę dzwonić w sprawach bezpieczeństwa, tylko sugeruję rozwiązania. Dzięki SQL Server 2005 możemy ustawić uprawnienia (w zależności od użytkownika, jeśli zajdzie taka potrzeba) na poziomie schematu dla poszczególnych procedur składowanych, a następnie bezpośrednio odmówić wszelkich zapytań dotyczących tabel. Krytyka zalet i wad tego podejścia to być może inna kwestia, ale znowu nie jest to moja decyzja. Jestem tylko małpą prowadzącą kod. :)
Sean Hanley
źródło
Odnieś się do stackoverflow.com/questions/3659981/ ... także - SQL Server dynamiczne ORDER BY z mieszanymi typami danych
LCJ
Dynamiczny SQL jest DUŻO lepszym sposobem ... JEŻELI [a to jest duże IF] ... Twoja warstwa dostępu do danych jest ścisła, a dynamiczny SQL jest generowany przez system, który jest sztywno zaprogramowany z regułami RDBMS wyrażonymi w doskonałej formie. Architektura baz danych
zaprojektowana przez

Odpowiedzi:

97

Tak, to ból, a sposób, w jaki to robisz, wygląda podobnie do tego, co ja:

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

Jest to dla mnie nadal znacznie lepsze niż budowanie dynamicznego SQL z kodu, co dla administratorów baz danych zamienia się w koszmar skalowalności i utrzymania.

To, co robię z kodu, to refaktoryzacja stronicowania i sortowania, więc przynajmniej nie mam tam wielu powtórzeń z wypełnianiem wartości dla @SortExpri @SortDir.

Jeśli chodzi o SQL, zachowaj projekt i formatowanie takie same między różnymi procedurami składowanymi, aby było co najmniej schludne i rozpoznawalne, gdy wchodzisz do wprowadzania zmian.

Eric Z Beard
źródło
1
Dokładnie. Moim celem było uniknięcie wykonywania polecenia EXEC na dużym łańcuchu varchar o wartości 5000. Wszystko, co robimy, musi odbywać się za pośrednictwem procedur składowanych, choćby dla dodatkowego bezpieczeństwa, ponieważ możemy ustawić uprawnienia do nich na poziomie schematu. W naszym przypadku skalowalność i wzrost wydajności to tylko plus.
Sean Hanley
1
Dodaj łatwość konserwacji do {bezpieczeństwo, skalowalność, wydajność}. Gdy masz już 3 lub 4 aplikacje z dynamicznym SQL działającym w oparciu o twoją bazę danych, masz spieprzone, nie możesz niczego zmienić, zwłaszcza gdy aplikacje się starzeją i programiści się rozwijają. Exec i dynamiczny sql są złe.
Eric Z Beard
To po prostu to - już to robimy, zanim tu dotarłem, dla wszystkich wciąż działających aplikacji internetowych Classic ASP i wielu, wielu aplikacji Access VB wciąż w obiegu. Drżę i muszę powstrzymywać chęć naprawienia rażących błędów za każdym razem, gdy muszę konserwować którykolwiek z nich.
Sean Hanley,
1
To również robię, z wyjątkiem tego, że koduję kierunek w SortExpr: ORDER BY CASE WHEN sort = 'FirstName' THEN FirstName END ASC, CASE WHEN sort = '-FirstName' THEN FirstName END DESC
Michael Bray
To jest koszmar zarówno dla administratorów baz danych, jak i inżynierów oprogramowania. Zamiast więc mieć dynamiczne, ale ścisłe systemy, które generują ekspresyjne instrukcje SQL w oparciu o schemat informacji, masz tę obrzydliwą plątaninę zakodowanego bełkotu. To kiepskie programowanie w najlepszym wydaniu.
lista pieszych wędrówek
23

Takie podejście zapobiega dwukrotnemu duplikowaniu sortowanych kolumn w kolejności i jest trochę bardziej czytelne w 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
Jason DeFontes
źródło
Wydawało się, że to dobra odpowiedź, ale nie działa, gdy sortowalne kolumny mają różne typy danych
SlimSim
6

Moje aplikacje często to robią, ale wszystkie dynamicznie budują SQL. Jednak kiedy mam do czynienia z procedurami składowanymi, robię to:

  1. Uczyń procedurę składowaną funkcją zwracającą tabelę wartości - bez sortowania.
  2. Następnie w kodzie aplikacji wykonaj a, select * from dbo.fn_myData() where ... order by ...aby dynamicznie określić tam porządek sortowania.

W takim razie przynajmniej część dynamiczna jest w twojej aplikacji, ale baza danych nadal wykonuje ciężkie prace.

Ron Savage
źródło
1
To prawdopodobnie najlepszy kompromis, jaki do tej pory widziałem między jednoczesnym używaniem dynamicznego SQL i procedur składowanych. Lubię to. Mógłbym kiedyś poeksperymentować z podobnym podejściem, ale taka zmiana byłaby zaporowa w każdym z naszych istniejących projektów w toku.
Sean Hanley,
1
Możesz osiągnąć to samo, używając lokalnej zmiennej tabeli zamiast funkcji tabelarycznej zwracającej dane. Uważam, że tabele lokalne są bardziej elastyczne niż funkcje, ponieważ można wyświetlić informacje o debugowaniu.
Sanjay Zalke
5

Technika procedury składowanej (hack?), Której używałem, aby uniknąć dynamicznego SQL dla niektórych zadań, polega na posiadaniu unikalnej kolumny sortowania. To znaczy,

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

Ten jest łatwy do pokonania podczas przesyłania - możesz łączyć pola w kolumnie mySort, odwracać kolejność za pomocą funkcji matematycznych lub dat itp.

Najlepiej jednak używać moich widoków siatki asp.net lub innych obiektów z wbudowanym sortowaniem, aby wykonać sortowanie za mnie PO pobraniu danych z Sql-Server. Lub nawet jeśli nie jest wbudowany - np. Zbiory danych itp. W asp.net.

dave
źródło
4

Istnieje kilka różnych sposobów na włamanie się do tego.

Wymagania wstępne:

  1. Tylko jedno oświadczenie SELECT w sp
  2. Pomiń sortowanie (lub ustaw domyślne)

Następnie wstaw do tabeli tymczasowej:

create table #temp ( your columns )

insert #temp
exec foobar

select * from #temp order by whatever

Metoda nr 2: skonfiguruj połączony serwer z powrotem do siebie, a następnie wybierz z tego za pomocą zapytania otwartego: http://www.sommarskog.se/share_data.html#OPENQUERY

Matt Rogish
źródło
4

Może istnieć trzecia opcja, ponieważ twój serwer ma wiele zapasowych cykli - użyj procedury pomocniczej, aby wykonać sortowanie za pomocą tabeli tymczasowej. Coś jak

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

Uwaga: nie testowałem tego, ale „powinno” działać w SQL Server 2005 (który utworzy tymczasową tabelę z zestawu wyników bez wcześniejszego określania kolumn).

Steven A. Lowe
źródło
2

Czy w pewnym momencie nie warto odejść od procedur składowanych i po prostu używać zapytań parametrycznych, aby uniknąć tego rodzaju włamań?

Hank Gay
źródło
1
W niektórych przypadkach może to być młot kowalski na gwoździu, ale często chcemy ustawić uprawnienia (w szczególności EXECUTE) bezpośrednio do procedur składowanych i zabronić wykonywania zapytań SQL bezpośrednio w tabelach, nawet SELECT. Ja też nie lubię tego włamania, ale bezpieczeństwo nie jest moim wezwaniem.
Sean Hanley,
1
Dlatego tak wiele osób przechodzi na mapowanie relacyjno-obiektowe. Niepotrzebne wędrówki w obie strony do sortowania, ogromne bloki CASE dla tych samych, bezsensownych aktualizacji ton kolumn, gdy tak naprawdę tylko jedna wymagała aktualizacji itd. Jedynym zwycięskim argumentem za procedurami składowanymi, który wciąż pozostaje, jest bezpieczeństwo.
Pittsburgh DBA
Przechodzę z ORM (EF) do procedury składowanej, ponieważ ORM nie obsługuje wyszukiwania pełnotekstowego.
Ronnie Overby
@RonnieOverby Wyszukiwanie pełnotekstowe jest często lepiej obsługiwane przez dedykowane rozwiązanie, np. Lucene.
Hank Gay
@HankGay Mam dziwne wrażenie, że framework encji również nie obsługuje Lucene.
Ronnie Overby
2

Zgadzam się, używam strony klienta. Ale wygląda na to, że nie jest to odpowiedź, którą chcesz usłyszeć.

Tak więc jest doskonały, taki jaki jest. Nie wiem, dlaczego chciałbyś to zmienić, a nawet zapytać „Czy jest lepszy sposób”. Naprawdę powinno się nazywać „Drogą”. Poza tym wydaje się, że działa i pasuje do potrzeb projektu i prawdopodobnie będzie wystarczająco rozszerzalny przez wiele lat. Ponieważ Twoje bazy danych nie są opodatkowane, a sortowanie jest naprawdę łatwe , powinno tak pozostać przez wiele lat.

Nie przejmowałbym się tym.

DS
źródło
Nie mam problemu ze stroną klienta, ponieważ idę tą drogą z aplikacjami Windows. A co z aplikacjami internetowymi? Nie wydaje mi się, aby żadne rozwiązanie JavaScript było wystarczająco elastyczne. I tak, działa tak, jak powiedziałem, tak, jak to mamy, ale to koszmar SQL. Oczywiście chciałbym wiedzieć, czy istnieją lepsze sposoby.
Sean Hanley
Jest wbudowany w nowsze (2.0 i nowsze) kontrolki .NET. Możesz też utworzyć własne i zastosować je do widoku danych. msdn.microsoft.com/en-us/library/hwf94875(VS.80).aspx
DS,
2
Mój problem to skalowalność i wydajność. Wykonywanie sortowania po stronie klienta lub serwera WWW wymaga załadowania wszystkich danych, a nie tylko 10 lub 15, które mają być wyświetlane na stronie naraz. Na dłuższą metę jest to niezwykle kosztowne, podczas gdy sortowanie baz danych tego nie wymaga.
Sean Hanley,
2

Podczas stronicowania posortowanych wyników dobrym rozwiązaniem jest dynamiczny SQL. Jeśli masz paranoję co do iniekcji SQL, możesz użyć numerów kolumn zamiast nazwy kolumny. Zrobiłem to przed użyciem wartości ujemnych do zejścia. Coś takiego...

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

Następnie musisz tylko upewnić się, że liczba znajduje się w kolumnach od 1 do #. Można nawet rozszerzyć ten do listy numerów kolumn i analizować to pod tabelą wskazówki przy użyciu funkcji takich jak ten . Następnie budowałbyś kolejność po klauzuli w ten sposób ...

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

Wadą jest to, że musisz pamiętać o kolejności poszczególnych kolumn po stronie klienta. Szczególnie, gdy nie wyświetlasz wszystkich kolumn lub wyświetlasz je w innej kolejności. Gdy klient chce sortować, mapujesz nazwy kolumn na kolejność kolumn i generujesz listę liczb całkowitych.

dotjoe
źródło
Używamy sp_executesql do tworzenia dynamicznych zapytań raportowych. Bardzo skuteczna. SQL nie można zbudować z aplikacji, ale parametry są wstawiane w razie potrzeby i wykonywane normalnie.
Josh Smeaton
2

Argumentem przeciwko sortowaniu po stronie klienta są duże ilości danych i paginacja. Gdy liczba wierszy przekroczy to, co możesz łatwo wyświetlić, często sortujesz jako część pominięcia / ujęcia, które prawdopodobnie chcesz uruchomić w języku SQL.

W przypadku Entity Framework można użyć procedury składowanej do obsługi wyszukiwania tekstu. Jeśli napotkasz ten sam problem z sortowaniem, rozwiązaniem, które widziałem, jest użycie zapisanego procesu do wyszukiwania, zwracając tylko zestaw kluczy id dla dopasowania. Następnie przeprowadź ponowne zapytanie (z sortowaniem) względem bazy danych, używając identyfikatorów z listy (zawiera). EF radzi sobie z tym całkiem dobrze, nawet jeśli zestaw identyfikatorów jest dość duży. Tak, są to dwie rundy, ale pozwala zawsze zachować sortowanie w bazie danych, co może być ważne w niektórych sytuacjach, i zapobiega zapisywaniu logiki w procedurze składowanej.

Paul Schirf
źródło
1

A co z sortowaniem po elementach wyświetlających wyniki - siatkach, raportach itp., A nie na SQL?

EDYTOWAĆ:

Aby wyjaśnić sprawę, ponieważ ta odpowiedź została wcześniej przegłosowana, opowiem trochę o tym ...

Powiedziałeś, że wiesz o sortowaniu po stronie klienta, ale chciałeś tego uniknąć. To oczywiście twoja decyzja.

Chcę jednak podkreślić, że robiąc to po stronie klienta, możesz pobrać dane RAZ, a następnie pracować z nimi w dowolny sposób - w przeciwieństwie do wielokrotnych podróży w tę iz powrotem na serwer za każdym razem sortowanie ulegnie zmianie.

Twój SQL Server nie jest teraz opodatkowany i to jest niesamowite. Nie powinno. Ale to, że nie jest jeszcze przeciążony, nie oznacza, że ​​pozostanie tak na zawsze.

Jeśli używasz nowszych elementów ASP.NET do wyświetlania w Internecie, wiele z nich jest już gotowych.

Czy warto dodawać tyle kodu do każdej procedury składowanej, aby obsłużyć sortowanie? Znowu twoja decyzja.

To nie ja będę ostatecznie odpowiedzialny za wspieranie tego. Ale zastanów się, co będzie związane z dodawaniem / usuwaniem kolumn w różnych zestawach danych używanych przez procedury składowane (wymagające modyfikacji instrukcji CASE) lub gdy nagle zamiast sortować według dwóch kolumn, użytkownik zdecyduje, że potrzebują trzech - wymagające teraz zaktualizowania wszystkich procedur składowanych korzystających z tej metody.

Dla mnie warto uzyskać działające rozwiązanie po stronie klienta i zastosować je do kilku wyświetlanych przez użytkownika wyświetlaczy danych i skończyć z tym. Jeśli zostanie dodana nowa kolumna, jest już obsługiwana. Jeśli użytkownik chce sortować według wielu kolumn, może sortować według dwóch lub dwudziestu z nich.

Kevin Fairchild
źródło
To byłaby właściwa droga, ale nie jest uważana za „lepszą drogę”
DS,
Ponieważ nadal piszę własne sortowanie w C # lub JavaScript i wydaje się, że powinno być o wiele łatwiejsze i szybsze w SQL. Stąd moje pytanie. Czy po prostu przegapiłem coś oczywistego, czy też utknęliśmy w pisaniu własnego, niestandardowego sortowania (w C # lub JavaScript) każdej cholernej aplikacji, nad którą pracujemy?
Sean Hanley,
3
Zaraz, a co z zestawami wyników z dziesiątkami tysięcy wierszy? Nie możesz zwrócić wszystkich tych danych klientowi. Musisz zrobić stronicowanie i sortowanie w bazie danych.
Eric Z Beard
Yadyn, zrozumiałem. Ale kiedy masz już ogólny sortownik do swoich siatek, po prostu używasz go do wszystkich swoich rzeczy.
Kevin Fairchild,
Eric, prawda… W takich przypadkach potrzebujesz dodatkowej obsługi i może miałoby to sens w SQL. To nie jest kwestia dobra i zła. W niektórych przypadkach ma to sens w przypadku SQL, a w niektórych przypadkach na kliencie.
Kevin Fairchild,
1

Przepraszam, że spóźniłem się na imprezę, ale oto kolejna opcja dla tych, którzy naprawdę chcą uniknąć dynamicznego SQL, ale chcą oferowanej przez niego elastyczności:

Zamiast dynamicznie generować SQL w locie, napisz kod, aby wygenerować unikalny proces dla każdej możliwej odmiany. Następnie możesz napisać w kodzie metodę, która zajrzy do opcji wyszukiwania i wybierze odpowiedni proces do wywołania.

Jeśli masz tylko kilka odmian, możesz po prostu ręcznie utworzyć procesy. Ale jeśli masz wiele odmian, to zamiast utrzymywać je wszystkie, po prostu utrzymujesz generator procentów zamiast tego, aby je odtworzył.

Dodatkową korzyścią jest uzyskanie lepszych planów SQL zapewniających lepszą wydajność, robiąc to również w ten sposób.

BVernon
źródło
-1

To rozwiązanie może działać tylko w .NET, nie wiem.

Pobieram dane do C # z początkową kolejnością sortowania w klauzuli SQL order by, umieszczam te dane w DataView, buforuję je w zmiennej Session i używam ich do tworzenia strony.

Kiedy użytkownik klika nagłówek kolumny, aby posortować (lub stronę lub filtr), nie wracam do bazy danych. Zamiast tego wracam do mojego buforowanego DataView i ustawiam jego właściwość „Sort” na wyrażenie, które buduję dynamicznie, tak jak w przypadku dynamicznego SQL. (Filtrowanie wykonuję w ten sam sposób, używając właściwości „RowFilter”).

Możesz zobaczyć / poczuć, jak działa w wersji demonstracyjnej mojej aplikacji BugTracker.NET na http://ifdefined.com/btnet/bugs.aspx

Corey Trager
źródło
SŁODKIE! Bug tracker.NET rządzi!
digiguru
-7

Należy unikać sortowania SQL Server, chyba że jest to konieczne. Dlaczego nie posortować na serwerze aplikacji lub po stronie klienta? Również .NET Generics robi wyjątkowe sortowanie

Saif Khan
źródło
6
Ze względu na skalowalność. Jest dobrze dla kilku tysięcy rzędów, ale nie chcę ściągać dziesięciu tysięcy i sortować tego. Albo więcej. A co ze stronicowaniem? Często chcę wyciągnąć tylko to, co chcę wyświetlić. Sortowanie wierszy 21-30 z 24056 po fakcie byłoby nieprawidłowe.
Sean Hanley