Dynamische Sortierung in gespeicherten SQL-Prozeduren

126

Dies ist ein Thema, über das ich in der Vergangenheit stundenlang recherchiert habe. Es scheint mir etwas zu sein, das von modernen RDBMS- Lösungen hätte angegangen werden sollen , aber ich habe noch nichts gefunden, das wirklich das anspricht, was ich als unglaublich häufig in einer Web- oder Windows-Anwendung mit einem Datenbank-Back-End betrachte.

Ich spreche von dynamischer Sortierung. In meiner Fantasiewelt sollte es so einfach sein wie:

ORDER BY @sortCol1, @sortCol2

Dies ist das kanonische Beispiel, das von neuen SQL- und Stored Procedure- Entwicklern in allen Foren im Internet gegeben wurde. "Warum ist das nicht möglich?" Sie Fragen. Ausnahmslos kommt irgendwann jemand vorbei, um sie über die Kompilierung gespeicherter Prozeduren, Ausführungspläne im Allgemeinen und viele andere Gründe zu belehren, warum es nicht möglich ist, einen Parameter direkt in eine ORDER BYKlausel einzufügen.


Ich weiß, was einige von Ihnen bereits denken: "Dann lassen Sie den Kunden die Sortierung durchführen." Dies entlastet natürlich die Arbeit aus Ihrer Datenbank. In unserem Fall sind unsere Datenbankserver jedoch in 99% der Fälle nicht einmal ins Schwitzen geraten, und sie sind noch nicht einmal mehrkernig oder eine der anderen unzähligen Verbesserungen der Systemarchitektur, die alle 6 Monate stattfinden. Allein aus diesem Grund wäre es kein Problem, wenn unsere Datenbanken die Sortierung übernehmen. Darüber hinaus sind Datenbanken sehrgut sortieren. Sie sind dafür optimiert und hatten Jahre Zeit, um es richtig zu machen. Die Sprache dafür ist unglaublich flexibel, intuitiv und einfach. Vor allem jeder SQL-Anfänger weiß, wie es geht, und was noch wichtiger ist, er weiß, wie man es bearbeitet. Nehmen Sie Änderungen vor, führen Sie Wartungsarbeiten durch usw. Wenn Ihre Datenbanken weit davon entfernt sind, besteuert zu werden, und Sie nur die Entwicklungszeit vereinfachen (und verkürzen!) möchten, scheint dies eine naheliegende Wahl zu sein.

Dann gibt es das Webproblem. Ich habe mit JavaScript herumgespielt, das das clientseitige Sortieren von HTML-Tabellen ermöglicht, aber sie sind unweigerlich nicht flexibel genug für meine Anforderungen, und da meine Datenbanken nicht übermäßig besteuert sind und das Sortieren wirklich sehr einfach durchführen können, bin ich es auch Es fällt mir schwer, die Zeit zu rechtfertigen, die erforderlich wäre, um meinen eigenen JavaScript-Sortierer neu zu schreiben oder zu rollen. Das Gleiche gilt im Allgemeinen für die serverseitige Sortierung, obwohl sie wahrscheinlich bereits JavaScript vorgezogen wird. Ich bin nicht einer, der den Overhead von DataSets besonders mag, also verklagen Sie mich.

Dies bringt jedoch den Punkt zurück, dass es nicht möglich ist - oder vielmehr nicht einfach. Ich habe mit früheren Systemen einen unglaublich hackigen Weg gefunden, um eine dynamische Sortierung zu erreichen. Es war weder hübsch noch intuitiv, einfach oder flexibel, und ein Anfänger-SQL-Writer würde innerhalb von Sekunden verloren gehen. Dies scheint bereits weniger eine "Lösung" als vielmehr eine "Komplikation" zu sein.


Die folgenden Beispiele sollen weder Best Practices noch einen guten Codierungsstil oder ähnliches aufzeigen, noch zeigen sie meine Fähigkeiten als T-SQL-Programmierer an. Sie sind das, was sie sind, und ich gebe voll und ganz zu, dass sie verwirrend sind, eine schlechte Form haben und einfach nur hacken.

Wir übergeben einen ganzzahligen Wert als Parameter an eine gespeicherte Prozedur (nennen wir den Parameter nur "sortieren") und bestimmen daraus eine Reihe anderer Variablen. Zum Beispiel ... Nehmen wir an, sort ist 1 (oder die Standardeinstellung):

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

Sie können bereits sehen, wie ich, wenn ich mehr @ colX-Variablen deklariert habe, um andere Spalten zu definieren, mit den zu sortierenden Spalten basierend auf dem Wert von "sort" wirklich kreativ werden könnte ... um sie zu verwenden, sieht sie normalerweise wie folgt aus unglaublich unordentliche Klausel:

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

Offensichtlich ist dies ein sehr reduziertes Beispiel. Das eigentliche Zeug, da wir normalerweise vier oder fünf Spalten haben, um das Sortieren zu unterstützen, jede mit einer möglichen sekundären oder sogar einer dritten Spalte, um zusätzlich zu sortieren (zum Beispiel Datum absteigend, dann sekundär sortiert nach aufsteigendem Namen) und jede unterstützende Bi- Richtungssortierung, die die Anzahl der Fälle effektiv verdoppelt. Ja ... es wird sehr schnell haarig.

Die Idee ist, dass man die Sortierfälle "leicht" so ändern könnte, dass die Fahrzeug-ID vor der Speicherzeit sortiert wird ... aber die Pseudoflexibilität, zumindest in diesem einfachen Beispiel, endet wirklich dort. Im Wesentlichen wird in jedem Fall, in dem ein Test fehlschlägt (da unsere Sortiermethode diesmal nicht darauf angewendet wird), ein NULL-Wert ausgegeben. Und so erhalten Sie eine Klausel, die wie folgt funktioniert:

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

Du hast die Idee. Dies funktioniert, weil SQL Server Nullwerte in der Reihenfolge nach Klauseln effektiv ignoriert. Dies ist unglaublich schwer zu pflegen, wie wahrscheinlich jeder mit grundlegenden SQL-Kenntnissen sehen kann. Wenn ich einen von euch verloren habe, fühle dich nicht schlecht. Wir haben lange gebraucht, um es zum Laufen zu bringen, und wir sind immer noch verwirrt, wenn wir versuchen, es zu bearbeiten oder neue wie dieses zu erstellen. Zum Glück muss es nicht oft gewechselt werden, sonst würde es schnell "die Mühe nicht wert" werden.

Doch es tat Arbeit.


Meine Frage ist dann: Gibt es einen besseren Weg?

Ich bin mit anderen Lösungen als den gespeicherten Prozeduren einverstanden, da mir klar ist, dass dies möglicherweise nicht der richtige Weg ist. Am liebsten würde ich wissen, ob jemand es innerhalb der gespeicherten Prozedur besser machen kann, aber wenn nicht, wie gehen Sie alle damit um, dass der Benutzer Datentabellen mit ASP.NET dynamisch (auch bidirektional) sortiert?

Und danke, dass Sie eine so lange Frage gelesen (oder zumindest überflogen) haben!

PS: Seien Sie froh, dass ich mein Beispiel einer gespeicherten Prozedur nicht gezeigt habe, die dynamisches Sortieren, dynamisches Filtern / Textsuchen von Spalten, Paginierung über ROWNUMBER () OVER unterstützt, und versuchen Sie ... mit Transaktions-Rollbacking bei Fehlern zu fangen ... "gigantisch groß" beginnt nicht einmal, sie zu beschreiben.


Aktualisieren:

  • Ich möchte dynamisches SQL vermeiden . Das Parsen eines Strings und das Ausführen einer EXEC darauf macht einen großen Teil des Zwecks zunichte, eine gespeicherte Prozedur überhaupt zu haben. Manchmal frage ich mich jedoch, ob sich die Nachteile eines solchen Vorgangs nicht lohnen würden, zumindest in diesen speziellen Fällen der dynamischen Sortierung. Trotzdem fühle ich mich immer schmutzig, wenn ich solche dynamischen SQL-Zeichenfolgen mache - als würde ich immer noch in der klassischen ASP-Welt leben.
  • Viele der Gründe, warum wir gespeicherte Prozeduren überhaupt wollen, sind aus Sicherheitsgründen . Ich kann nicht auf Sicherheitsbedenken anrufen, sondern nur Lösungen vorschlagen. Mit SQL Server 2005 können wir Berechtigungen (bei Bedarf auf Benutzerbasis) auf Schemaebene für einzelne gespeicherte Prozeduren festlegen und dann alle Abfragen für die Tabellen direkt ablehnen. Die Vor- und Nachteile dieses Ansatzes zu kritisieren, ist vielleicht eine andere Frage, aber auch hier ist es nicht meine Entscheidung. Ich bin nur der Lead-Code-Affe. :) :)
Sean Hanley
quelle
Siehe auch stackoverflow.com/questions/3659981/… - SQL Server Dynamic ORDER BY mit gemischten Datentypen
LCJ
Dynamisches SQL ist der weitaus bessere Weg ... WENN [und dies ist ein großes WENN] ... Ihre Datenzugriffsschicht ist streng und Ihr dynamisches SQL wird von einem System generiert, das starr mit RDBMS-Regeln programmiert ist, die in perfekter Form ausgedrückt werden. Eine algorithmisch
konstruierte

Antworten:

97

Ja, es ist ein Schmerz und die Art, wie du es tust, sieht ähnlich aus wie das, was ich tue:

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

Für mich ist dies immer noch viel besser als das Erstellen von dynamischem SQL aus Code, was für DBAs zu einem Alptraum für Skalierbarkeit und Wartung wird.

Was ich aus Code mache, ist das Refactor des Paging und Sortierens, so dass ich dort zumindest nicht viele Wiederholungen mit dem Auffüllen von Werten für @SortExprund habe @SortDir.

Behalten Sie in Bezug auf SQL das Design und die Formatierung zwischen verschiedenen gespeicherten Prozeduren bei, damit es zumindest ordentlich und erkennbar ist, wenn Sie Änderungen vornehmen.

Eric Z Bart
quelle
1
Genau. Mein Ziel war es, einen EXEC-Befehl für eine große 5000-Varchar-Zeichenfolge zu vermeiden. Alles, was wir tun, muss über gespeicherte Prozeduren erfolgen, wenn auch nur für die zusätzliche Sicherheit, da wir Berechtigungen für sie auf Schemaebene festlegen können. Die Skalierbarkeit und Leistungssteigerung sind in unserem Fall nur ein Plus.
Sean Hanley
1
Fügen Sie {Sicherheit, Skalierbarkeit, Leistung} Wartbarkeit hinzu. Sobald Sie 3 oder 4 Apps mit dynamischem SQL auf Ihrer Datenbank haben, können Sie nichts mehr ändern, insbesondere wenn die Apps älter werden und die Entwickler weiterarbeiten. Exec und Dynamic SQL sind böse.
Eric Z Beard
Das ist es nur - wir tun es bereits von Anfang an für alle noch laufenden Classic ASP-Web-Apps und viele, viele Access VB-Apps, die noch im Umlauf sind. Ich zucke und muss den Drang zurückhalten, krasse Fehler zu beheben, wenn ich Wartungsarbeiten an einem von ihnen durchführen muss.
Sean Hanley
1
Dies ist, was ich auch tue, außer dass ich die Richtung in SortExpr codiere: ORDER BY CASE WHEN sort = 'Vorname' DANN Vorname END ASC, FALL WENN sort = '-FirstName' DANN Vorname END DESC
Michael Bray
Dies ist DER Albtraum für Datenbankadministratoren und Softwareentwickler. Anstatt in der Lage zu sein, dynamische, aber strenge Systeme zu haben, die auf der Grundlage Ihres Informationsschemas ausdrucksstarke SQL-Anweisungen generieren, haben Sie diesen ekelhaften Hauch von hartcodiertem Kauderwelsch. Es ist schlechte Programmierung vom Feinsten.
Hajikelist
23

Dieser Ansatz verhindert, dass die sortierbaren Spalten zweimal in der Reihenfolge von dupliziert werden, und ist IMO etwas besser lesbar:

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
quelle
Dies schien eine gute Antwort zu sein, scheint aber nicht zu funktionieren, wenn die sortierbaren Spalten unterschiedliche Datentypen haben
SlimSim
6

Meine Anwendungen tun dies häufig, aber sie alle bauen das SQL dynamisch auf. Wenn ich mich jedoch mit gespeicherten Prozeduren beschäftige, mache ich Folgendes:

  1. Machen Sie die gespeicherte Prozedur zu einer Funktion, die eine Tabelle Ihrer Werte zurückgibt - keine Sortierung.
  2. Führen Sie dann in Ihrem Anwendungscode a aus, select * from dbo.fn_myData() where ... order by ...damit Sie dort die Sortierreihenfolge dynamisch angeben können.

Dann befindet sich zumindest der dynamische Teil in Ihrer Anwendung, aber die Datenbank erledigt immer noch das schwere Heben.

Ron Savage
quelle
1
Das ist wahrscheinlich der beste Kompromiss, den ich bisher zwischen der gemeinsamen Verwendung von dynamischem SQL und gespeicherten Prozeduren gesehen habe. Ich mag das. Ich könnte irgendwann mit einem ähnlichen Ansatz experimentieren, aber eine solche Änderung wäre in keinem unserer laufenden Projekte untragbar.
Sean Hanley
1
Sie können dasselbe erreichen, indem Sie eine lokale Tabellenvariable anstelle einer Tabellenfunktion verwenden, die Daten zurückgibt. Ich finde lokale Tabellen flexibler als Funktionen, da Sie einige Debug-Informationen ausgeben können.
Sanjay Zalke
5

Eine gespeicherte Prozedur (Hack?), Die ich verwendet habe, um dynamisches SQL für bestimmte Jobs zu vermeiden, besteht darin, eine eindeutige Sortierspalte zu haben. Dh

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

Dieser ist leicht zu übermitteln - Sie können Felder in Ihrer mySort-Spalte verknüpfen, die Reihenfolge mit mathematischen oder Datumsfunktionen umkehren usw.

Am besten verwende ich jedoch meine asp.net-Rasteransichten oder andere Objekte mit integrierter Sortierung, um die Sortierung für mich durchzuführen, nachdem ich die Daten von SQL-Server abgerufen habe. Oder auch wenn es nicht eingebaut ist - z. B. Datentabellen usw. in asp.net.

Dave
quelle
4

Es gibt verschiedene Möglichkeiten, wie Sie dies hacken können.

Voraussetzungen:

  1. Nur eine SELECT-Anweisung in der sp
  2. Lassen Sie jede Sortierung weg (oder haben Sie eine Standardeinstellung)

Dann in eine temporäre Tabelle einfügen:

create table #temp ( your columns )

insert #temp
exec foobar

select * from #temp order by whatever

Methode 2: Richten Sie einen Verbindungsserver wieder für sich selbst ein und wählen Sie ihn dann mit openquery aus: http://www.sommarskog.se/share_data.html#OPENQUERY

Matt Rogish
quelle
4

Es gibt möglicherweise eine dritte Option, da Ihr Server über viele freie Zyklen verfügt. Verwenden Sie eine Hilfsprozedur, um die Sortierung über eine temporäre Tabelle durchzuführen. Etwas wie

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

Vorsichtsmaßnahme: Ich habe dies nicht getestet, aber es sollte in SQL Server 2005 "funktionieren" (wodurch eine temporäre Tabelle aus einer Ergebnismenge erstellt wird, ohne die Spalten im Voraus anzugeben.)

Steven A. Lowe
quelle
2

Lohnt es sich nicht irgendwann, sich von gespeicherten Prozeduren zu entfernen und nur parametrisierte Abfragen zu verwenden, um diese Art von Hackery zu vermeiden?

Hank Gay
quelle
1
In bestimmten Fällen sind sie vielleicht Vorschlaghammer auf einem Nagel, aber oft möchten wir Berechtigungen (insbesondere EXECUTE) direkt für die gespeicherten Prozeduren festlegen und SQL-Abfragen direkt für die Tabellen, sogar SELECTs, nicht zulassen. Ich mag den Hackery auch nicht sehr, aber Sicherheit ist nicht meine Aufgabe.
Sean Hanley
1
Aus diesem Grund wechseln so viele Menschen zur objektrelationalen Zuordnung. Unnötige Roundtrips zum Sortieren, riesige CASE-Blöcke für dieselben, sinnlose Aktualisierungen von Tonnen von Spalten, wenn wirklich nur eine aktualisiert werden musste usw. Das einzige entscheidende Argument für gespeicherte Prozeduren, das noch übrig bleibt, ist die Sicherheit.
Pittsburgh DBA
Ich wechsle von einem ORM (EF) zu einer gespeicherten Prozedur, da das ORM die Volltextsuche nicht unterstützt.
Ronnie Overby
@RonnieOverby Die Volltextsuche wird häufig durch eine spezielle Lösung, z. B. Lucene, besser bedient.
Hank Gay
@HankGay Ich habe das seltsame Gefühl, dass das Entity Framework auch Lucene nicht unterstützt.
Ronnie Overby
2

Ich bin damit einverstanden, Client-Seite zu verwenden. Aber es scheint, dass dies nicht die Antwort ist, die Sie hören möchten.

Es ist also perfekt so wie es ist. Ich weiß nicht, warum Sie es ändern oder sogar fragen möchten: "Gibt es einen besseren Weg?" Eigentlich sollte es "The Way" heißen. Außerdem scheint es gut zu funktionieren und den Anforderungen des Projekts zu entsprechen und wird wahrscheinlich für die kommenden Jahre erweiterbar genug sein. Da Ihre Datenbanken nicht besteuert werden und das Sortieren wirklich sehr einfach ist , sollte dies auch in den kommenden Jahren so bleiben.

Ich würde es nicht schwitzen.

DS
quelle
Ich habe kein Problem mit der Clientseite, da ich diesen Weg mit Windows-Apps gehe. Aber was ist mit Web-Apps? Ich finde keine JavaScript-Lösung wirklich flexibel genug. Und ja, es funktioniert so, wie ich es gesagt habe, aber es ist ein Albtraum von SQL. Natürlich würde ich gerne wissen, ob es bessere Möglichkeiten gibt.
Sean Hanley
Es ist in die neueren (2.0 und höher) .NET-Steuerelemente integriert. Oder Sie können Ihre eigene erstellen und auf eine Datenansicht anwenden. msdn.microsoft.com/en-us/library/hwf94875(VS.80).aspx
DS
2
Mein Problem ist dann die Skalierbarkeit und Leistung. Für die clientseitige oder web-serverseitige Sortierung müssen alle Daten geladen werden, anstatt nur die 10 oder 15, die jeweils auf einer Seite angezeigt werden. Dies ist auf lange Sicht äußerst kostspielig, während die Datenbanksortierung dies nicht hat.
Sean Hanley
2

Wenn Sie sortierte Ergebnisse auslagern, ist dynamisches SQL eine gute Option. Wenn Sie in Bezug auf SQL-Injection paranoid sind, können Sie die Spaltennummern anstelle des Spaltennamens verwenden. Ich habe dies getan, bevor ich negative Werte für den Abstieg verwendet habe. Etwas wie das...

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

Dann müssen Sie nur noch sicherstellen, dass die Anzahl innerhalb von 1 bis # der Spalten liegt. Man könnte sogar diese zu einer Liste von Spaltennummern erweitern und analysiert , die in eine Tabelle von Ints eine Funktion wie mit dieser . Dann würden Sie die Order by-Klausel wie folgt erstellen ...

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

Ein Nachteil ist, dass Sie sich die Reihenfolge jeder Spalte auf der Clientseite merken müssen. Insbesondere, wenn Sie nicht alle Spalten oder in einer anderen Reihenfolge anzeigen. Wenn der Client sortieren möchte, ordnen Sie die Spaltennamen der Spaltenreihenfolge zu und generieren die Liste der Ints.

dotjoe
quelle
Wir verwenden sp_executesql zum Erstellen dynamischer Berichtsabfragen. Sehr effektiv. Das SQL kann nicht aus der Anwendung erstellt werden, aber die Parameter werden nur bei Bedarf eingefügt und wie gewohnt ausgeführt.
Josh Smeaton
2

Ein Argument gegen die Sortierung auf der Clientseite sind große Datenmengen und Paginierung. Sobald Ihre Zeilenanzahl über das hinausgeht, was Sie leicht anzeigen können, sortieren Sie häufig als Teil eines Überspringens / Nehmens, das Sie wahrscheinlich in SQL ausführen möchten.

Für Entity Framework können Sie eine gespeicherte Prozedur verwenden, um Ihre Textsuche durchzuführen. Wenn Sie auf dasselbe Sortierproblem stoßen, besteht die Lösung darin, einen gespeicherten Prozess für die Suche zu verwenden und nur einen für die Übereinstimmung festgelegten ID-Schlüssel zurückzugeben. Als nächstes fragen Sie (mit der Sortierung) erneut nach der Datenbank ab, indem Sie die IDs in einer Liste (enthält) verwenden. EF handhabt dies ziemlich gut, selbst wenn der ID-Satz ziemlich groß ist. Ja, dies sind zwei Roundtrips, aber Sie können Ihre Sortierung immer in der Datenbank behalten, was in bestimmten Situationen wichtig sein kann, und verhindern, dass Sie eine Schiffsladung Logik in die gespeicherte Prozedur schreiben.

Paul Schirf
quelle
1

Wie wäre es mit der Sortierung nach dem Material, das die Ergebnisse anzeigt - Raster, Berichte usw. anstatt nach SQL?

BEARBEITEN:

Um die Dinge zu klären, da diese Antwort früher abgelehnt wurde, werde ich ein wenig näher darauf eingehen ...

Sie gaben an, dass Sie sich mit clientseitiger Sortierung auskennen, sich aber davon fernhalten wollten. Das ist natürlich dein Anruf.

Ich möchte jedoch darauf hinweisen, dass Sie auf der Clientseite EINMAL Daten abrufen und dann nach Belieben damit arbeiten können - anstatt jedes Mal mehrere Fahrten zum Server hin und her zu machen Die Sortierung wird geändert.

Ihr SQL Server wird momentan nicht besteuert und das ist großartig. Es sollte nicht sein. Aber nur weil es noch nicht überladen ist, heißt das nicht, dass es für immer so bleiben wird.

Wenn Sie eines der neueren ASP.NET-Elemente für die Anzeige im Web verwenden, ist ein Großteil dieses Materials bereits direkt eingebrannt.

Lohnt es sich, jeder gespeicherten Prozedur so viel Code hinzuzufügen, um die Sortierung zu übernehmen? Wieder dein Anruf.

Ich bin nicht derjenige, der letztendlich dafür verantwortlich sein wird, es zu unterstützen. Denken Sie jedoch darüber nach, worum es beim Hinzufügen / Entfernen von Spalten in den verschiedenen Datensätzen geht, die von den gespeicherten Prozeduren verwendet werden (Änderungen an den CASE-Anweisungen erforderlich), oder wenn der Benutzer plötzlich statt nach zwei Spalten zu sortieren, entscheidet, dass drei - erforderlich sind. Sie müssen jetzt alle gespeicherten Prozeduren aktualisieren, die diese Methode verwenden.

Für mich lohnt es sich, eine funktionierende clientseitige Lösung zu finden und sie auf die wenigen benutzerbezogenen Datenanzeigen anzuwenden und damit fertig zu sein. Wenn eine neue Spalte hinzugefügt wird, wird diese bereits behandelt. Wenn der Benutzer nach mehreren Spalten sortieren möchte, kann er nach zwei oder zwanzig Spalten sortieren.

Kevin Fairchild
quelle
Das wäre der richtige Weg, wird aber nicht als "besserer Weg" angesehen
DS
Denn dann schreibe ich immer noch meine eigene Sortierung in C # oder JavaScript und es scheint, dass es in SQL so viel einfacher und schneller sein sollte. Also meine Frage. Hat mir nur etwas Offensichtliches gefehlt oder stecken wir fest, unsere eigene benutzerdefinierte Sortierung (in C # oder JavaScript) für jede verdammte App zu schreiben, an der wir arbeiten?
Sean Hanley
3
Warten Sie, was ist mit Ergebnismengen mit Zehntausenden von Zeilen? Sie können nicht alle diese Daten an den Client zurückgeben. Sie müssen in der Datenbank blättern und sortieren.
Eric Z Beard
Yadyn, verstanden. Aber sobald Sie einen generischen Sortierer für Ihre Gitter haben, verwenden Sie diesen einfach für alle Ihre Sachen.
Kevin Fairchild
Eric, stimmt ... In solchen Fällen benötigen Sie zusätzliche Behandlung, und möglicherweise ist dies in SQL sinnvoll. Es ist weit entfernt von einem richtigen oder falschen Thema. In einigen Fällen ist dies für SQL und in einigen Fällen auf dem Client sinnvoll.
Kevin Fairchild
1

Es tut mir leid, dass ich zu spät zur Party komme, aber hier ist eine weitere Option für diejenigen, die dynamisches SQL wirklich vermeiden möchten, aber die Flexibilität wünschen, die es bietet:

Anstatt das SQL im laufenden Betrieb dynamisch zu generieren, schreiben Sie Code, um für jede mögliche Variation einen eindeutigen Prozess zu generieren. Anschließend können Sie eine Methode in den Code schreiben, um die Suchoptionen anzuzeigen und den entsprechenden aufrufenden Prozess auszuwählen.

Wenn Sie nur wenige Variationen haben, können Sie die Prozesse einfach von Hand erstellen. Wenn Sie jedoch viele Variationen haben, müssen Sie nicht alle warten, sondern nur Ihren Proc-Generator warten, damit er sie neu erstellt.

Als zusätzlichen Vorteil erhalten Sie auch auf diese Weise bessere SQL-Pläne für eine bessere Leistung.

BVernon
quelle
-1

Diese Lösung funktioniert möglicherweise nur in .NET, ich weiß es nicht.

Ich rufe die Daten mit der anfänglichen Sortierreihenfolge in der SQL-Reihenfolge nach Klausel in das C # ab, füge diese Daten in eine DataView ein, speichere sie in einer Sitzungsvariablen zwischen und erstelle damit eine Seite.

Wenn der Benutzer auf eine Spaltenüberschrift klickt, um sie zu sortieren (oder eine Seite oder einen Filter), gehe ich nicht zurück zur Datenbank. Stattdessen kehre ich zu meiner zwischengespeicherten DataView zurück und setze die Eigenschaft "Sortieren" auf einen Ausdruck, den ich dynamisch erstelle, genau wie ich es mit dynamischem SQL tun würde. (Ich filtere auf die gleiche Weise mit der Eigenschaft "RowFilter").

Sie können es in einer Demo meiner App BugTracker.NET unter http://ifdefined.com/btnet/bugs.aspx sehen / fühlen

Corey Trager
quelle
SÜSS! Bug tracker.NET rockt!
Digiguru
-7

Sie sollten die SQL Server-Sortierung vermeiden, sofern dies nicht erforderlich ist. Warum nicht auf App-Server- oder Client-Seite sortieren? Auch .NET Generics führt außergewöhnliche Sortierungen durch

Saif Khan
quelle
6
Wegen der Skalierbarkeit. Es ist in Ordnung für ein paar tausend Reihen, aber ich möchte nicht zehntausend runterziehen und das sortieren. Oder mehr. Und was ist mit Paging? Ich möchte oft nur das ziehen, was ich anzeigen muss. Das Sortieren der Zeilen 21-30 von 24056 nachträglich wäre falsch.
Sean Hanley