Als eine Erweiterung von akzeptierte Antwort Oracle verwendet intern ROW_NUMBER/RANK
Funktionen. OFFSET FETCH
Syntax ist ein Syntaxzucker.
Dies kann beobachtet werden durch die Verwendung von DBMS_UTILITY.EXPAND_SQL_TEXT
Verfahren:
Vorbereiten der Probe:
CREATE TABLE rownum_order_test (
val NUMBER
);
INSERT ALL
INTO rownum_order_test
SELECT level
FROM dual
CONNECT BY level <= 10;
COMMIT;
Abfrage:
SELECT val
FROM rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS ONLY;
ist regelmäßig:
SELECT "A1"."VAL" "VAL"
FROM (SELECT "A2"."VAL" "VAL","A2"."VAL" "rowlimit_$_0",
ROW_NUMBER() OVER ( ORDER BY "A2"."VAL" DESC ) "rowlimit_$$_rownumber"
FROM "ROWNUM_ORDER_TEST" "A2") "A1"
WHERE "A1"."rowlimit_$$_rownumber"<=5 ORDER BY "A1"."rowlimit_$_0" DESC;
db<>fiddle demo
Abrufen von erweitertem SQL-Text:
declare
x VARCHAR2(1000);
begin
dbms_utility.expand_sql_text(
input_sql_text => '
SELECT val
FROM rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS ONLY',
output_sql_text => x);
dbms_output.put_line(x);
end;
/
WITH TIES
wird erweitert zu RANK
:
declare
x VARCHAR2(1000);
begin
dbms_utility.expand_sql_text(
input_sql_text => '
SELECT val
FROM rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS WITH TIES',
output_sql_text => x);
dbms_output.put_line(x);
end;
/
SELECT "A1"."VAL" "VAL"
FROM (SELECT "A2"."VAL" "VAL","A2"."VAL" "rowlimit_$_0",
RANK() OVER ( ORDER BY "A2"."VAL" DESC ) "rowlimit_$$_rank"
FROM "ROWNUM_ORDER_TEST" "A2") "A1"
WHERE "A1"."rowlimit_$$_rank"<=5 ORDER BY "A1"."rowlimit_$_0" DESC
und Versatz:
declare
x VARCHAR2(1000);
begin
dbms_utility.expand_sql_text(
input_sql_text => '
SELECT val
FROM rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY',
output_sql_text => x);
dbms_output.put_line(x);
end;
/
SELECT "A1"."VAL" "VAL"
FROM (SELECT "A2"."VAL" "VAL","A2"."VAL" "rowlimit_$_0",
ROW_NUMBER() OVER ( ORDER BY "A2"."VAL") "rowlimit_$$_rownumber"
FROM "ROWNUM_ORDER_TEST" "A2") "A1"
WHERE "A1"."rowlimit_$$_rownumber"<=CASE WHEN (4>=0) THEN FLOOR(TO_NUMBER(4))
ELSE 0 END +4 AND "A1"."rowlimit_$$_rownumber">4
ORDER BY "A1"."rowlimit_$_0"
21 Stimmen
Standardisiert in SQL:2008.
1 Stimmen
Es sieht so aus, als ob in Ihrem ersten MySQL-Beispiel Offset und Row_count vertauscht sind. Diese Abfrage wählt die Zeilen 11 bis 30 aus, nicht 21 bis 30.
17 Stimmen
Limit wurde von Tom Kyte für Oracle 12c angekündigt...
0 Stimmen
Betrachten Sie es als Offtopic, aber ich kann mir kaum vorstellen, dass es im wirklichen Leben Anwendungsfälle gibt, in denen man Daten aus der Mitte eines Datensatzes extrahieren muss. Kein Scherz. Vielleicht bin ich der Glückliche, der noch nicht auf solche Anforderungen gestoßen ist. Wenn jemand ein Beispiel nennen könnte, das auf echten Erfahrungen beruht...
18 Stimmen
Abrufen der nächsten Seite in einer Ergebnismenge?
8 Stimmen
@YaroslavShabalin Bei einer Seitensuche wird insbesondere dieses Muster verwendet todos die Zeit. Fast jede Anwendung mit irgendeiner Art von Suchfunktion wird sie verwenden. Ein weiterer Anwendungsfall wäre, nur einen Teil einer langen Liste oder Tabelle clientseitig zu laden und dem Benutzer die Möglichkeit zu geben, diese zu erweitern.
2 Stimmen
@MathieuLongtin @jpmc26 Beginnen Sie bei Google zunächst auf Seite 10? Warum müssen Sie die Abfrage jedes Mal ausführen, wenn die nächste Seite geladen wird, wenn Sie sie einmal ausführen, den Cursor öffnen und durch das Laden eines bestimmten Teils des Datensatzes navigieren können? Ja, Sie müssen sich mit der Speicherverwaltung befassen, wenn die Ergebnismenge groß ist, aber Sie vermeiden mögliche Inkonsistenzen. Bedenken Sie, dass sich die Anzahl der Zeilen in der Ergebnismenge jedes Mal ändert, wenn Sie die obige Abfrage erneut ausführen.
limit 20,10
können Sie unterschiedliche Ergebnisse erzielen.4 Stimmen
@YaroslavShabalin Sie können keine andere Ergebnismenge erhalten, es sei denn, die zugrunde liegenden Daten ändern sich aufgrund der
ORDER BY
. Das ist ja der Sinn der ersten Bestellung. Wenn sich die zugrundeliegenden Daten ändern und sich Ihre Ergebnismenge dadurch ändert, warum zeigen Sie dem Benutzer dann nicht die aktualisierten Ergebnisse anstelle der veralteten Informationen? Außerdem ist die Zustandsverwaltung eine Plage, die so weit wie möglich vermieden werden sollte. Sie ist eine ständige Quelle von Komplikationen und Fehlern; deshalb wird funktionales Management so beliebt. Und wann würden Sie wissen, dass die gesamte Ergebnismenge im Speicher ablaufen soll? Im Web können Sie nicht wissen, wann der Benutzer die Seite verlässt.2 Stimmen
@jpmc26 OK, ich verstehe, was Sie meinen. Jetzt macht es Sinn.
4 Stimmen
@YaroslavShabalin - das Öffnen eines Cursors und dessen längeres Offenhalten in einem Mehrbenutzerszenario ist eine gute Möglichkeit, eine relationale Datenbank zu verknotet. In einer Einbenutzer-Datenbank spielt das wahrscheinlich keine Rolle, aber wenn Sie Hunderte von gleichzeitigen Verbindungen haben, führt das sehr wahrscheinlich zu Problemen. Relationale Datenbanken sind im Allgemeinen als transaktionale DBs mit relativ kurzen Transaktionsdauern konzipiert. YMMV. Teilen und genießen.
1 Stimmen
Siehe Wie die Paginierung in Oracle SQL funktioniert
1 Stimmen
Siehe auch Paging mit Oracle
0 Stimmen
youtube.com/watch?v=rhOVF82KY7E