Grundlegendes Tutorial zur SQL-Optimierung

Wir müssen nicht nur SQL schreiben, sondern auch SQL-Anweisungen mit hervorragender Leistung schreiben.

(1) Wählen Sie die effizienteste Reihenfolge der Tabellennamen (nur gültig in regelbasierten Optimierern):

Der Parser von Oracle verarbeitet die Tabellennamen in der FROM-Klausel in der Reihenfolge von rechts nach links. Die letzte in die FROM-Klausel geschriebene Tabelle (Basistabellen-Treibertabelle) wird zuerst verarbeitet, und mehrere Tabellen sind in der FROM-Klausel enthalten. Im Fall von , müssen Sie die Tabelle mit der geringsten Anzahl an Datensätzen als Basistabelle auswählen. Wenn mehr als drei Tabellen mit der Abfrage verbunden sind, müssen Sie die Schnittmengentabelle als Basistabelle auswählen. Die Schnittmengentabelle bezieht sich auf die Tabelle, auf die andere Tabellen verweisen.

(2) Die Verbindungsreihenfolge in der WHERE-Klausel:

Oracle verwendet eine Bottom-up-Reihenfolge zum Parsen der WHERE-Klausel. Nach diesem Prinzip muss die Verbindung zwischen Tabellen vor anderen WHERE-Bedingungen geschrieben werden, und diejenigen Bedingungen, die die maximale Anzahl von Datensätzen herausfiltern können, müssen am Ende geschrieben werden WHERE-Klausel.

(3) Vermeiden Sie die Verwendung von „*“ in der SELECT-Klausel:

Während des Analysevorgangs konvertiert Oracle nacheinander „*“ in alle Spaltennamen. Diese Arbeit wird durch Abfragen des Datenwörterbuchs erledigt, was bedeutet, dass es mehr Zeit in Anspruch nimmt.

(4) Reduzieren Sie die Anzahl der Zugriffe auf die Datenbank:

Oracle führt intern eine Menge Arbeit aus: SQL-Anweisungen analysieren, Indexauslastung schätzen, Variablen binden, Datenblöcke lesen usw.

(5) Das Zurücksetzen des ARRAYSIZE-Parameters in SQL Plus, SQL Forms und Pro*C kann die Menge der abgerufenen Daten für jeden Datenbankzugriff erhöhen. Der empfohlene Wert ist 200.

(6) Verwenden Sie die DECODE-Funktion, um die Verarbeitungszeit zu verkürzen:

Verwenden Sie die DECODE-Funktion, um wiederholtes Scannen derselben Datensätze oder wiederholte Verknüpfungen mit denselben Tabellen zu vermeiden.

(7) Integrieren Sie einfachen, nicht verknüpften Datenbankzugriff:

Wenn Sie mehrere einfache Datenbankabfragen haben, können Sie diese zu einer Abfrage zusammenfassen (auch wenn keine Beziehung zwischen ihnen besteht).

(8) Doppelte Datensätze löschen:

Beispiel für die effizienteste Methode zum Löschen doppelter Datensätze (da ROWID verwendet wird):

DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO);

(9) Ersetzen Sie DELETE durch TRUNCATE:

Beim Löschen von Datensätzen in einer Tabelle werden unter normalen Umständen Rollback-Segmente (Rollback-Segmente) zum Speichern wiederherstellbarer Informationen verwendet. Wenn Sie keine COMMIT-Transaktion haben, stellt ORACLE die Daten in den Zustand vor dem Löschen zurück (genauer: Wiederherstellen). (in den Zustand vor der Ausführung des Löschbefehls versetzt) ​​und wenn TRUNCATE verwendet wird, speichert das Rollback-Segment keine Informationen mehr, die wiederhergestellt werden können. Nachdem der Befehl ausgeführt wurde, können die Daten nicht wiederhergestellt werden. Daher werden nur wenige Ressourcen beansprucht und die Ausführungszeit ist kurz. (TRUNCATE ist nur zum Löschen der gesamten Tabelle anwendbar, TRUNCATE ist DDL, nicht DML).

(10) Verwenden Sie COMMIT so oft wie möglich:

Verwenden Sie COMMIT nach Möglichkeit so oft wie möglich im Programm, um die Leistung des Programms zu verbessern und die Nachfrage aufgrund der von COMMIT freigegebenen Ressourcen zu verringern. Die von COMMIT freigegebenen Ressourcen sind:

a. Informationen, die zum Wiederherstellen von Daten im Rollback-Segment verwendet werden.

b. Durch Programmanweisungen erworbene Sperren.

c. Platz im Redo-Log-Puffer.

d. Oracle verwaltet die internen Ausgaben der oben genannten drei Ressourcen.

(11) Ersetzen Sie die HAVING-Klausel durch die Where-Klausel:

Vermeiden Sie die Verwendung der HAVING-Klausel. HAVING filtert die Ergebnismenge erst, nachdem alle Datensätze abgerufen wurden. Diese Verarbeitung erfordert Vorgänge wie Sortieren und Summieren. Wenn Sie die Anzahl der Datensätze durch die WHERE-Klausel begrenzen können, können Sie diesen Overhead reduzieren. (Nicht in Oracle) Unter den drei Klauseln, die mit Bedingungen hinzugefügt werden können, on, where und getting, wird on zuerst ausgeführt, where ist das zweite und playing das letzte, weil on zuerst Datensätze filtert, die die Bedingungen nicht erfüllen, bevor es ausgeführt wird Statistiken können die in der Zwischenoperation zu verarbeitenden Daten reduzieren. Es liegt auf der Hand, dass es am schnellsten sein sollte, und zwar schneller als mit, da es die Daten vor der Summe filtert und nur dann verwendet, wenn zwei Tabellen vorhanden sind werden verbunden. In einer Tabelle wird also nur wo mit haben verglichen. Wenn bei Einzeltabellen-Abfragestatistiken die zu filternden Bedingungen nicht die zu berechnenden Felder betreffen, sind ihre Ergebnisse dieselben, aber wo kann die Rushmore-Technologie verwendet werden, was jedoch nicht möglich ist, und letztere ist langsamer In Bezug auf die Geschwindigkeit. Wenn das berechnete Feld betroffen ist, bedeutet dies, dass der Wert dieses Felds vor der Berechnung ungewiss ist. Gemäß dem im vorherigen Artikel beschriebenen Arbeitsablauf ist die Aktionszeit, in der die Berechnung abgeschlossen ist, und das Vorhandene nach der Berechnung. funktioniert, daher werden in diesem Fall die Ergebnisse der beiden unterschiedlich sein. Bei einer Multi-Table-Join-Abfrage funktioniert „on“ früher als „wo“. Das System kombiniert zunächst mehrere Tabellen gemäß den Verknüpfungsbedingungen zwischen den Tabellen zu einer temporären Tabelle, filtert dann nach „Wo“, berechnet dann und filtert dann nach „Haben“ nach der Berechnung. Es ist ersichtlich, dass wir, damit die Filterbedingung eine korrekte Rolle spielt, zunächst verstehen müssen, wann die Bedingung funktionieren soll, und dann entscheiden müssen, wo sie platziert werden soll.

(12) Reduzieren Sie Abfragen für Tabellen:

Bei SQL-Anweisungen, die Unterabfragen enthalten, sollte besonderes Augenmerk auf die Reduzierung von Abfragen auf Tabellen gelegt werden. Beispiel:

SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECTTAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)

(13) Verbessern Sie die SQL-Effizienz durch interne Funktionen:

Kompliziertes SQL beeinträchtigt häufig die Ausführungseffizienz. Es ist sehr sinnvoll, die oben genannten Methoden zur Verwendung von Funktionen zur Lösung von Problemen in der praktischen Arbeit zu beherrschen.

(14) Verwenden Sie den Alias ​​der Tabelle (Alias):

Wenn Sie mehrere Tabellen in der SQL-Anweisung verbinden, verwenden Sie bitte den Alias ​​der Tabelle und stellen Sie den Alias ​​jeder Spalte voran. Auf diese Weise kann die Analysezeit verkürzt und die durch Spaltenmehrdeutigkeit verursachten Syntaxfehler reduziert werden.

(15) Ersetzen Sie IN durch EXISTS und NOT IN durch NOT EXISTS:

Bei vielen Abfragen, die auf Basistabellen basieren, ist es zum Erfüllen einer Bedingung häufig erforderlich, eine andere Tabelle zu verknüpfen. In diesem Fall verbessert die Verwendung von EXISTS (oder NOT EXISTS ) normalerweise die Effizienz der Abfrage. In einer Unterabfrage führt die NOT IN-Klausel eine interne Sortierung und Zusammenführung durch. In beiden Fällen ist NOT IN am wenigsten effizient (da es einen vollständigen Table Walk für die Tabelle in der Unterabfrage durchführt). Um die Verwendung von NOT IN zu vermeiden, können wir es in Outer Joins oder NOT EXISTS umschreiben.

Beispiel:

(高效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND EXISTS (SELECT 'X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = 'MELB')(低效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = 'MELB')

(16) Identifizieren Sie SQL-Anweisungen mit „ineffizienter Ausführung“:

Obwohl in einem endlosen Strom verschiedene grafische Tools zur SQL-Optimierung auftauchen, ist es immer die beste Möglichkeit, eigene SQL-Tools zur Lösung von Problemen zu schreiben:

SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio, ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run, SQL_TEXT FROM V$SQLAREA WHERE EXECUTIONS>0 AND BUFFER_GETS > 0 AND (BUFFER_GETS-DISK_READS) /BUFFER_GETS < 0,8 ORDER BY 4 DESC;

Der Index ist ein konzeptioneller Teil der Tabelle, der zur Verbesserung der Effizienz beim Datenabruf verwendet wird. Oracle verwendet eine komplexe selbstausgleichende B-Baumstruktur. Im Allgemeinen ist das Abfragen von Daten über einen Index schneller als ein vollständiger Tabellenscan. Der Oracle-Optimierer verwendet Indizes, wenn Oracle den besten Pfad zum Ausführen von Abfragen und Update-Anweisungen ermittelt. Auch die Verwendung von Indizes beim Zusammenführen mehrerer Tabellen kann die Effizienz verbessern. Ein weiterer Vorteil der Verwendung eines Index besteht darin, dass er eine Eindeutigkeitsüberprüfung des Primärschlüssels ermöglicht. Dabei handelt es sich um LONG- oder LONG RAW-Datentypen. Sie können fast jede Spalte indizieren. Im Allgemeinen ist die Verwendung von Indizes besonders effektiv bei großen Tabellen. Natürlich werden Sie auch feststellen, dass die Verwendung von Indizes auch die Effizienz beim Scannen kleiner Tabellen verbessern kann. Obwohl die Verwendung von Indizes die Abfrageeffizienz verbessern kann, müssen wir auch auf die Kosten achten. Indizes benötigen Speicherplatz für die Speicherung und regelmäßige Wartung. Immer wenn ein Datensatz zu einer Tabelle hinzugefügt oder daraus entfernt oder eine Indexspalte geändert wird, wird auch der Index selbst geändert. Das bedeutet, dass das INSERT, DELETE und UPDATE jedes Datensatzes 4 oder 5 weitere Festplatten-E/As kostet. Da Indizes zusätzlichen Speicherplatz und Verarbeitung erfordern, können unnötige Indizes tatsächlich die Antwortzeiten von Abfragen verlangsamen. Regelmäßige Indexneuerstellungen sind erforderlich:

INDEX NEU ERSTELLEN

(18) Ersetzen Sie DISTINCT durch EXISTS:

Vermeiden Sie die Verwendung von DISTINCT in der SELECT-Klausel, wenn Sie eine Abfrage senden, die Informationen aus Eins-zu-vielen-Tabellen wie Abteilungs- und Mitarbeitertabellen enthält. Im Allgemeinen können Sie erwägen, es durch EXIST zu ersetzen. EXISTS beschleunigt die Abfrage, da das RDBMS-Kernmodul das Ergebnis zurückgibt, sobald die Bedingungen der Unterabfrage erfüllt sind. Beispiel:

(nicht verfügbar): SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E WHERE D.DEPT_NO = E.DEPT_NO (nicht verfügbar): SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT 'X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);

(19) Verwenden Sie Großbuchstaben für SQL-Anweisungen, da Oracle SQL-Anweisungen immer zuerst analysiert, Kleinbuchstaben in Großbuchstaben umwandelt und diese dann ausführt.

(20) Verwenden Sie den Connector „+“ so selten wie möglich, um Zeichenfolgen im Java-Code zu verbinden.

(21) Vermeiden Sie die Verwendung von NOT für Indexspalten. Im Allgemeinen möchten wir die Verwendung von NOT für Indexspalten vermeiden. NOT hat die gleichen Auswirkungen wie die Verwendung von Funktionen für Indexspalten. Wenn Oracle auf „NICHT“ stößt, verwendet es den Index nicht mehr und führt stattdessen einen vollständigen Tabellenscan durch.

(22) Vermeiden Sie die Verwendung von Berechnungen für indizierte Spalten. WHERE-Klausel, wenn die Indexspalte Teil der Funktion ist. Der Optimierer verwendet keinen Index, sondern einen vollständigen Tabellenscan.

Beispiel:

Ineffizient: SELECT … FROM DEPT WHERE SAL * 12 > 25000; Effizient: SELECT … FROM DEPT WHERE SAL > 25000/12;

(23) Ersetzen Sie > durch >=:

Effizient: SELECT * FROM EMP WHERE DEPTNO >=4 Ineffizient: SELECT * FROM EMP WHERE DEPTNO >3

Der Unterschied zwischen den beiden besteht darin, dass das erstere DBMS direkt zum ersten Datensatz mit DEPT gleich 4 springt, während das letztere zuerst den Datensatz mit DEPTNO=3 findet und vorwärts zum ersten Datensatz mit DEPT größer als 3 scannt.

(24) Ersetzen Sie OR durch UNION (für indizierte Spalten):

Normalerweise hat das Ersetzen des OR in der WHERE-Klausel durch UNION eine bessere Wirkung. Die Verwendung von OR für indizierte Spalten führt zu einem vollständigen Tabellenscan. Beachten Sie, dass die oben genannten Regeln nur für mehrere Indexspalten gelten. Wenn Spalten vorhanden sind, die nicht indiziert sind, verringert sich möglicherweise die Abfrageeffizienz, da Sie OR nicht auswählen. Im folgenden Beispiel gibt es Indizes sowohl für LOC_ID als auch für REGION.

Hinweis: SELECT LOC_ID 。 LOC_DESC ,REGION FROM LOCATION WHERE LOC_ID = 10 UNION SELECT LOC_ID ,LOC_DESC ,REGION FROM LOCATION WHERE REGION = „MELBOURNE“

Beispiel: SELECT LOC_ID,LOC_DESC,REGION FROM LOCATION WHERE LOC_ID = 10 OR REGION = „MELBOURNE“

(25) Ersetzen Sie OR durch IN:

Dies ist eine einfache und leicht zu merkende Regel, aber der tatsächliche Ausführungseffekt muss getestet werden. Unter Oracle8i scheinen die Ausführungspfade der beiden gleich zu sein:

Ineffizient:

WÄHLEN…. VOM STANDORT WO LOC_ID = 10 ODER LOC_ID = 20 ODER LOC_ID = 30

Effizient:

SELECT… FROM LOCATION WHERE LOC_IN IN (10,20,30);

(26) Vermeiden Sie die Verwendung von IS NULL und IS NOT NULL für indizierte Spalten:

Vermeiden Sie die Verwendung von Spalten, die NULL-Werte zulassen, im Index. Oracle kann den Index sonst nicht verwenden. Wenn bei einem einspaltigen Index die Spalte einen Nullwert enthält, ist der Datensatz nicht im Index vorhanden. Wenn bei zusammengesetzten Indizes jede Spalte leer ist, ist der Datensatz auch nicht im Index vorhanden. Ein Datensatz ist im Index vorhanden, wenn mindestens eine Spalte nicht null ist. Beispiel: Wenn der eindeutige Index auf den Spalten A und B der Tabelle basiert und in der Tabelle ein Datensatz mit A- und B-Werten (123, null) vorhanden ist, akzeptiert Oracle den nächsten Datensatz mit demselben A nicht und B-Werte (123, null) Datensätze (einfügen). Wenn jedoch alle Indexspalten leer sind, betrachtet Oracle den gesamten Schlüsselwert als leer und leer ist nicht gleich leer. Sie können also 1000 Datensätze mit demselben Schlüsselwert einfügen, und natürlich sind sie alle leer! Da der Nullwert in der Indexspalte nicht vorhanden ist, führt ein Nullvergleich der Indexspalte in der WHERE-Klausel dazu, dass ORACLE den Index deaktiviert .

Ineffizient: (Indexungültigmachung)

SELECT … FROM DEPARTMENT WHERE DEPT_CODE NOT NULL;

Effizient: (Index funktioniert)

SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;

(27) Verwenden Sie immer die erste Spalte des Index:

Wenn der Index auf mehreren Spalten aufgebaut ist, verwendet der Optimierer den Index nur dann, wenn seine erste Spalte (führende Spalte) durch die where-Klausel referenziert wird. Dies ist ebenfalls eine einfache, aber wichtige Regel: Wenn nur auf die zweite Spalte des Index verwiesen wird, verwendet der Optimierer einen vollständigen Tabellenscan und ignoriert den Index.

(28) Ersetzen Sie UNION durch UNION-ALL (falls möglich):

Wenn eine SQL-Anweisung zwei Abfrageergebnismengen mit UNION verbinden muss, werden die beiden Ergebnismengen auf UNION-ALL-Art kombiniert und dann sortiert, bevor das Endergebnis ausgegeben wird. Wenn UNION ALL anstelle von UNION verwendet wird, ist eine Sortierung nicht erforderlich. Die Effizienz wird dadurch verbessert. Es ist zu beachten, dass UNION ALL wiederholt dieselben Datensätze in den beiden Ergebnismengen ausgibt. Daher müssen Sie noch die Machbarkeit der Verwendung von UNION ALL aus Sicht der Geschäftsanforderungen analysieren. UNION sortiert die Ergebnismenge und dieser Vorgang verwendet SORT_AREA_SIZE-Speicher. Auch die Optimierung dieses Speichers ist sehr wichtig. Zur Abfrage des Sortierverbrauchs kann das folgende SQL verwendet werden:

Beispiel: SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95' UNION SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95' Schritt: SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSAC TIONS WHERE TRAN_DATE = '31- DEC-95' UNION ALL SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95'

(29) Ersetzen Sie ORDER BY durch WHERE:

Die ORDER BY-Klausel verwendet Indizes nur unter zwei strengen Bedingungen.

Alle Spalten in ORDER BY müssen im selben Index enthalten sein und die Sortierreihenfolge im Index beibehalten.

Alle Spalten in ORDER BY müssen als ungleich Null definiert sein.

Der in der WHERE-Klausel verwendete Index und der in der ORDER BY-Klausel verwendete Index dürfen nicht parallel sein.

Beispiel: Die Tabelle DEPT enthält folgende Spalten:

DEPT_CODE PK NICHT NULL

DEPT_DESC NICHT NULL

DEPT_TYPE NULL

Ineffizient: (Index nicht verwendet)

WÄHLEN SIE DEPT_CODE AUS DEPT ORDER NACH DEPT_TYPE AUS

Effizient: (mit Indizes)

WÄHLEN SIE DEPT_CODE AUS DEPT, WO DEPT_TYPE > 0

(30) Vermeiden Sie es, den Typ der Indexspalte zu ändern:

Beim Vergleich von Daten unterschiedlicher Datentypen führt ORACLE automatisch einfache Typkonvertierungen für Spalten durch. Angenommen, EMPNO ist eine Indexspalte vom numerischen Typ: SELECT ... FROM EMP WHERE EMPNO = '123'. Tatsächlich wird die Anweisung nach der Oracle-Typkonvertierung wie folgt umgewandelt: SELECT ... FROM EMP WHERE EMPNO = TO_NUMBER('123') .

Glücklicherweise findet in der Indexspalte keine Typkonvertierung statt, der Zweck des Index wurde nicht geändert. Angenommen, EMP_TYPE ist eine Indexspalte des Zeichentyps: SELECT ... FROM EMP WHERE EMP_TYPE = 123 .

Diese Anweisung wird von Oracle konvertiert: SELECT ... FROM EMP WHERETO_NUMBER(EMP_TYPE)=123. Aufgrund der internen Typkonvertierung wird dieser Index nicht verwendet! Um die implizite Typkonvertierung von Oracle für Ihr SQL zu vermeiden, ist es am besten, die Typkonvertierung explizit auszudrücken. Beachten Sie, dass Oracle beim Vergleich von Zeichen und Zahlen zuerst numerische Typen in Zeichentypen konvertiert.

(31) WHERE-Klauseln, die vorsichtig sein müssen:

Einige WHERE-Klauseln in SELECT-Anweisungen verwenden keine Indizes. Hier sind einige Beispiele:

(1) '!=' verwendet den Index nicht. Denken Sie daran, dass Indizes Ihnen nur sagen können, was in der Tabelle vorhanden ist, nicht aber, was nicht in der Tabelle vorhanden ist.

(2) '||' ist eine Zeichenverbindungsfunktion. Wie andere Funktionen ist auch die Indizierung deaktiviert.

(3) „+“ ist eine mathematische Funktion. Wie andere mathematische Funktionen ist auch die Indizierung deaktiviert.

(4) Dieselben Indexspalten können nicht miteinander verglichen werden, wodurch ein vollständiger Tabellenscan möglich ist.

(32) a. Wenn die Menge der abgerufenen Daten 30 % der Anzahl der Datensätze in der Tabelle übersteigt, wird die Verwendung von Indizes die Effizienz nicht wesentlich verbessern.

b. In bestimmten Fällen kann die Verwendung eines Index langsamer sein als ein vollständiger Tabellenscan, es handelt sich jedoch um einen Unterschied in der gleichen Größenordnung. Unter normalen Umständen ist die Verwendung eines Indexes um ein Vielfaches oder sogar Tausende Male schneller als ein vollständiger Tabellenscan!

(33) Vermeiden Sie ressourcenintensive Vorgänge:

SQL-Anweisungen mit DISTINCT, UNION, MINUS, INTERSECT, ORDER BY starten die SQL-Engine, um ressourcenintensive Sortierfunktionen (SORT) auszuführen. DISTINCT erfordert eine Sortieroperation, während die anderen mindestens zwei Sortierungen erfordern. Im Allgemeinen können SQL-Anweisungen mit UNION, MINUS, INTERSECT alle auf andere Weise umgeschrieben werden. Wenn die SORT_AREA_SIZE Ihrer Datenbank gut angepasst ist. Auch die Verwendung von UNION, MINUS, INTERSECT kann in Betracht gezogen werden, schließlich sind sie sehr gut lesbar.

(34) GRUPPIEREN NACH optimieren:

Um die Effizienz der GROUP BY-Anweisung zu verbessern, können Sie unnötige Datensätze vor der GROUP BY-Anweisung herausfiltern. Die folgenden beiden Abfragen liefern die gleichen Ergebnisse, die zweite ist jedoch deutlich schneller.

Beispiel: SELECT JOB , AVG(SAL) FROM EMP GROUP JOB HAVING JOB = 'PRÄSIDENT' OR JOB = 'MANAGER' Option: SELECT JOB , AVG(SAL) FROM EMP WHERE JOB = 'PRÄSIDENT' OR JOB = 'MANAGER' GROUP ARBEIT

Supongo que te gusta

Origin blog.csdn.net/xiaoyaoACi/article/details/130933951
Recomendado
Clasificación