Der Kurs „MySQL für Datenbankadministratoren“ richtet sich an MySQL-Datenbankadministratoren und andere Spezialisten, die MySQL-Server installieren und optimieren, Replikation und Sicherheit einrichten, Datenbankbackups und Leistungsoptimierung durchführen sowie MySQL-Datenbanken schützen möchten.
Learn Oracle from Oracle - Original Oracle University Seminar
Dieser Kurs zur Datenbankprogrammierung mit PL/SQL vermittelt zunächst eine Einführung zu PL/SQL und untersucht anschließend die Vorteile dieser leistungsstarken Programmiersprache. Im Rahmen praktischer Übungen machen Sie sich unter Anleitung qualifizierter Oracle-Dozenten mit der Entwicklung von Stored Procedures, Stored Functions, Packages usw. vertraut.
Learn Oracle from Oracle - Original Oracle University Seminar
Mit dem vorliegenden Kurs Oracle Database: Introduction to SQL werden Ihnen Kenntnisse zum Erstellen von Unterabfragen, zum Zusammenfassen mehrerer Abragen mit einem Mengenoperator zu einer einzelnen Abfrage und zum Erstellen von Berichten aus aggregierten Daten mithilfe von Gruppenfunktionen vermittelt. Diese und weitere Kenntnisse werden mithilfe praktischer Übungen vertieft.
Learn Oracle from Oracle - Original Oracle University Seminar
Im Kurs "Oracle Database: SQL Tuning for Developers" lernen die Teilnehmer Oracle SQL-Tuning kennen und erfahren, wie sie die Tuningverfahren auf ihren SQL-Code anwenden. Die Teilnehmer lernen die verschiedenen Möglichkeiten kennen, mit denen sie effizient auf Daten zugreifen können.
In Oracle 11g können nun Sequencen ihre Werte über eine ausführbare Anweisungen zurückgeben und müssen nicht mehr in einer Select-Anweisung verarbeitet werden.
Vor Oracle 11g:
SELECT TEST1_SEQ.CURRVAL
INTO L_VALUE
FROM DUAL;
Ab Oracle 11g:
L_VALUE := TEST1_SEQ.CURRVAL;
Bei Performanceproblemen eines Upgrade-Skripts einer Datenbankanwendung stieß ich auf folgende interessante Problematik von Optimizer-Statistiken.
Ein Upgrade-Skript sollte Datensätze innerhalt einer Tabelle mit mehr als 4 Millionen Zeilen konvertieren. Hierfür wurde auf eine Tabelle TAB1 eine SELECT-Anweisung ausgeführt, die Zeilen über eine Spalte S4 filtern sollte. Die Werte der Spalte S4 hatten allerdings die Eigenart, dass bei allen 4 Millionen Zeilen die ersten 45 Zeichen der Werte dieser Spalte identisch waren. Erst ab diesen Zeichen unterscheiden sie sich. Da diese Anweisung mehrere tausendmal auf die Tabelle ausgeführt wurde, aber in Abhängigkeit des Suchwertes der Spalte S4 nur 10 bis 20 Zeilen zurückkommen sollten, wurde ein Index auf diese Spalte erstellt und Optimizer-Statistiken gesammelt.
Interessanterweise ignorierte der Optimizer diesen Index und führte einen Full-Table-Scan aus, was das Upgrade-Skript sehr stark verlangsamte.
SQL> SELECT s1, s2, s3
2 FROM MEINUSER.TAB1
3 WHERE s4 = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1234' AND
4 s5 = '0'
5 ORDER BY s1, s2;
Ausführungsplan
----------------------------------------------------------
Plan hash value: 915916058
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4374K| 471M| | 130K (3)| 00:01:48 |
| 1 | SORT ORDER BY | | 4374K| 471M| 560M| 130K (3)| 00:01:48 |
|* 2 | TABLE ACCESS FULL| TAB1 | 4374K| 471M| | 24299 (5)| 00:00:21 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("S4" = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1234'
AND "S5" = '0')
Statistiken
----------------------------------------------------------
0 recursive calls
1 db block gets
80499 consistent gets
0 physical reads
0 redo size
487 bytes sent via SQL*Net to client
509 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
15 rows processed
Auch das erneute Sammeln der Optimizer-Statistiken brachte kein Erfolg.
SQL> exec dbms_stats.gather_table_stats('MEINUSER','TAB1',cascade=>true)
PL/SQL-Prozedur erfolgreich abgeschlossen.
SQL> SELECT s1, s2, s3
2 FROM MEINUSER.TAB1
3 WHERE s4 = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1234' AND
4 s5 = '0'
5 ORDER BY s1, s2;
15 Zeilen ausgewählt.
Ausführungsplan
----------------------------------------------------------
Plan hash value: 915916058
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4416K| 475M| | 131K (3)| 00:01:49 |
| 1 | SORT ORDER BY | | 4416K| 475M| 565M| 131K (3)| 00:01:49 |
|* 2 | TABLE ACCESS FULL| TAB1 | 4416K| 475M| | 24304 (5)| 00:00:21 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("S4" = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1234'
AND "S5" = '0')
Statistiken
----------------------------------------------------------
0 recursive calls
1 db block gets
80499 consistent gets
0 physical reads
0 redo size
1134 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
15 rows processed
Aus diesem Grund entschloss ich mich dediziert ein Histogramm für die Spalte S4 zu erstellen, welches aber ebenfalls kein Erfolg brachte (Ich experimentierte mit den Histogrammen und erstellte sie auf unterschiedlicher Art und Weise).
SQL> BEGIN
2 DBMS_STATS.GATHER_TABLE_STATS(
3 OWNNAME=> 'MEINUSER',
4 TABNAME=> 'TAB1' ,
5 ESTIMATE_PERCENT=> NULL,
6 CASCADE=> DBMS_STATS.AUTO_CASCADE,
7 DEGREE=> NULL,
8 NO_INVALIDATE=> DBMS_STATS.AUTO_INVALIDATE,
9 GRANULARITY=> 'AUTO',
10 METHOD_OPT=> 'FOR ALL COLUMNS SIZE AUTO FOR COLUMNS S4 SIZE 120');
11 END;
12 /
PL/SQL-Prozedur erfolgreich abgeschlossen.
SQL> SELECT s1, s2, s3
2 FROM MEINUSER.TAB1
3 WHERE s4 = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1234' AND
4 s5 = '0'
5 ORDER BY s1, s2;
15 Zeilen ausgewählt.
Ausführungsplan
----------------------------------------------------------
Plan hash value: 915916058
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4374K| 471M| | 130K (3)| 00:01:48 |
| 1 | SORT ORDER BY | | 4374K| 471M| 560M| 130K (3)| 00:01:48 |
|* 2 | TABLE ACCESS FULL| TAB1 | 4374K| 471M| | 24299 (5)| 00:00:21 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("S4" = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1234'
AND "S5" = '0')
Statistiken
----------------------------------------------------------
0 recursive calls
1 db block gets
80499 consistent gets
0 physical reads
0 redo size
487 bytes sent via SQL*Net to client
509 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
15 rows processed
Im nächsten Schritt entschloss ich mich den Optimizer zur Verwendung des Index zu zwingen und erhielt ein interessantes Ergebnis:
Die Kosten für die Verwendung des Index schienen noch einmal zusätzlich angestiegen zu sein. Aber die Ausführungsstatistiken zeigten, dass anstatt 80499 nur noch 6 Blöcke gelesen wurden. Zudem wurde diese Anweisung mit dem Hint für die Verwendung des Index um ein Vielfaches schneller ausgeführt. Also gab es in der Tat ein Problem mit den Statistiken. Meine Vermutung war, dass Oracle beim Sammeln der Statistiken die Histogramme aufgrund der ersten 45 gleichen Zeichen für jeden Datensatz der Spalte S4 nicht richtig erzeugte.
SQL> SELECT /*+ INDEX(TAB1 IDX_S4) */ s1, s2, s3
2 FROM MEINUSER.TAB1
3 WHERE s4 = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1234' AND
4 s5 = '0'
5 ORDER BY s1, s2;
15 Zeilen ausgewählt.
Ausführungsplan
----------------------------------------------------------
Plan hash value: 2461020050
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)|Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4374K| 471M| | 631K (1)|00:08:42 |
| 1 | SORT ORDER BY | | 4374K| 471M| 560M| 631K (1)|00:08:42 |
|* 2 | TABLE ACCESS BY INDEX ROWID| TAB1 | 4374K| 471M| | 525K (1)|00:07:15 |
|* 3 | INDEX RANGE SCAN | IDX_S4 | 4516K| | | 44711 (1)|00:00:37 |
------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("S5" ='0')
3 - access("S4" = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1234')
Statistiken
----------------------------------------------------------
0 recursive calls
0 db block gets
6 consistent gets
0 physical reads
0 redo size
853 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
15 rows processed
Aus diesem Grund entschied ich mich nun die Statistiken der Tabelle TAB1 zu löschen, um auf das Dynamic Sampling der Statistiken zu schwenken. Nach erneuter Ausführung der Anweisung verwendete Oracle nun auf einmal den Index. Ein Vergleich der Kosten zeigte, dass der Optimizer sie anhand der Statistiken nicht richtig berechnete, denn sie sanken nun von 631000 auf 3!!.
SQL> exec dbms_stats.delete_table_stats('MEINUSER','TAB1')
PL/SQL-Prozedur erfolgreich abgeschlossen.
SQL> SELECT s1, s2, s3
2 FROM MEINUSER.TAB1
3 WHERE s4 = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1234' AND
4 s5 = '0'
5 ORDER BY s1, s2;
15 Zeilen ausgewählt.
Ausführungsplan
----------------------------------------------------------
Plan hash value: 3167567956
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 542 | 135K| 3 (34)| 00:00:01 |
| 1 | SORT ORDER BY | | 542 | 135K| 3 (34)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| TAB1 | 542 | 135K| 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | IDX_S4 | 87 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("S5"='0' AND "S4" = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1234')
Note
-----
- dynamic sampling used for this statement (level=2)
Statistiken
----------------------------------------------------------
1 recursive calls
0 db block gets
6 consistent gets
0 physical reads
0 redo size
853 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
15 rows processed
Ab Oracle 11gR2 wurde Automatic Degree of Parallelism (ADOP) eingeführt, um Oracle die Entscheidung des Parallelitätsgrad für die Ausführung von SQL-Anweisungen bestimmen zu lassen. In vorherigen Versionen von Oracle musste der Parallelitätsgrad über das Hint PARALLEL in der SQL-Anweisung, oder über den Parallelitätsgrad der Tabelle festgelegt werden.
SQL> select count(*) from testtab2;
COUNT(*)
----------
100000
1 Zeile wurde ausgewählt.
SQL> set autotrace traceonly
SQL> select count(*) from testtab2;
1 Zeile wurde ausgewählt.
Ausführungsplan
----------------------------------------------------------
Plan hash value: 103376238
-----------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 206 (1)| 00:00:03 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| TESTTAB2 | 100K| 206 (1)| 00:00:03 |
-----------------------------------------------------------------------
Statistiken
----------------------------------------------------------
0 recursive calls
0 db block gets
678 consistent gets
670 physical reads
0 redo size
429 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select /*+parallel 2 */ count(*) from testtab2;
1 Zeile wurde ausgewählt.
Ausführungsplan
----------------------------------------------------------
Plan hash value: 2843183767
--------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 114 (1)| 00:00:02 | | | |
| 1 | SORT AGGREGATE | | 1 | | | | | |
| 2 | PX COORDINATOR | | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10000 | 1 | | | Q1,00 | P->S | QC (RAND) |
| 4 | SORT AGGREGATE | | 1 | | | Q1,00 | PCWP | |
| 5 | PX BLOCK ITERATOR | | 100K| 114 (1)| 00:00:02 | Q1,00 | PCWC | |
| 6 | TABLE ACCESS FULL| TESTTAB2 | 100K| 114 (1)| 00:00:02 | Q1,00 | PCWP | |
--------------------------------------------------------------------------------------------------------
Note
-----
- automatic DOP: Computed Degree of Parallelism is 2
Statistiken
----------------------------------------------------------
12 recursive calls
4 db block gets
845 consistent gets
670 physical reads
0 redo size
429 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> set autotrace off
In Oracle 11GR2 wurden neue Parameter eingeführt, die die automatische Parallelisierung aktivieren.
SQL> show parameter parallel
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
fast_start_parallel_rollback string LOW
parallel_adaptive_multi_user boolean TRUE
parallel_automatic_tuning boolean FALSE
parallel_degree_limit string CPU
parallel_degree_policy string MANUAL
parallel_execution_message_size integer 16384
parallel_force_local boolean FALSE
parallel_instance_group string
parallel_io_cap_enabled boolean FALSE
parallel_max_servers integer 20
parallel_min_percent integer 0
parallel_min_servers integer 0
parallel_min_time_threshold string AUTO
parallel_server boolean FALSE
parallel_server_instances integer 1
parallel_servers_target integer 8
parallel_threads_per_cpu integer 2
recovery_parallelism integer 0
Hierbei sind die Parameter prallel_degree_policy und parallel_min_time_treshold von besonderer Bedeutung. Der Parameter parallel_degree_policy aktiviert ADOP, wenn er auf AUTO gesetzt wird. Der Parameter parallel_min_time_threshold bestimmt den zeitlichen Schwellwert, den ein serieller Plan in seiner Abarbeitung überschreiten muss, ehe der Optimizer versucht einen adäquaten parallelen Plan zu erstellen. Der Standard dieses Parameters liegt bei 30 Sekunden. Dieses bedeutet, überschreitet die geschätzte Laufzeit des seriellen Plans diesen Schwellwert, entwickelt der Optimizer einen alternativen parallelen Plan und vergleicht die Laufzeit dieses Plans mit dem seriellen. Ist der parallele Plan schneller in seiner Abarbeitung, als der serielle, so wird der parallele Plan verwendet, ansonsten der serielle.
SQL> alter session set parallel_degree_policy='AUTO';
Session wurde geändert.
SQL> select count(*) from testtab2;
COUNT(*)
----------
100000
1 Zeile wurde ausgewählt.
SQL> set autotrace traceonly
SQL> select count(*) from testtab2;
1 Zeile wurde ausgewählt.
Ausführungsplan
----------------------------------------------------------
Plan hash value: 103376238
-----------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 206 (1)| 00:00:03 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| TESTTAB2 | 100K| 206 (1)| 00:00:03 |
-----------------------------------------------------------------------
Note
-----
- automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold
Statistiken
----------------------------------------------------------
0 recursive calls
0 db block gets
678 consistent gets
0 physical reads
0 redo size
429 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
In der vorhergehenden Anweisung entschied sich der Optimizer zur Verwendung eines seriellen Ausführungsplans, da der zeitliche Schwellwert nicht überschritten wurde.
Im nächsten Beispiel wird der Parameter parallel_min_time_threshold drastisch zu Demonstrartionszwecken verkleinert, wodurch die Entscheidung auf einen parallen Plan fällt.
SQL> alter session set parallel_min_time_threshold=1;
Session wurde geändert.
SQL> select count(*) from testtab2;
1 Zeile wurde ausgewählt.
Ausführungsplan
----------------------------------------------------------
Plan hash value: 2843183767
--------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 114 (1)| 00:00:02 | | | |
| 1 | SORT AGGREGATE | | 1 | | | | | |
| 2 | PX COORDINATOR | | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10000 | 1 | | | Q1,00 | P->S | QC (RAND) |
| 4 | SORT AGGREGATE | | 1 | | | Q1,00 | PCWP | |
| 5 | PX BLOCK ITERATOR | | 100K| 114 (1)| 00:00:02 | Q1,00 | PCWC | |
| 6 | TABLE ACCESS FULL| TESTTAB2 | 100K| 114 (1)| 00:00:02 | Q1,00 | PCWP | |
--------------------------------------------------------------------------------------------------------
Note
-----
- automatic DOP: Computed Degree of Parallelism is 2
Statistiken
----------------------------------------------------------
53 recursive calls
8 db block gets
905 consistent gets
0 physical reads
0 redo size
429 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
Standardmäßig wird die Oberfläche des SQL-Developers in der Sprache des Betriebssystems wiedergegeben.
Soll nun aber eine Sprache abweichend vom Betriebssystem verwendet werden, so muss dieses über die Konfigurationsdatei $SQLDEVELOPER_INST/sqldeveloper/bin/sqldeveloper.conf angepasst werden, indem der Eintrag AddVMOption -Duser.language=<Sprache> hinzugefügt wird.
Für Englisch hätte diese Datei dann den Inhalt:
IncludeConfFile ../../ide/bin/ide.conf
SetJavaHome ../../jdk
AddVMOption -Doracle.ide.util.AddinPolicyUtils.OVERRIDE_FLAG=true
AddVMOption -Dsun.java2d.ddoffscreen=false
AddVMOption -Dwindows.shell.font.languages=
AddVMOption -XX:MaxPermSize=128M
AddVMOption -Doracle.jdbc.mapDateToTimestamp=false
AddVMOption -Duser.language=en
IncludeConfFile sqldeveloper-nondebug.conf
Für Französisch hätte diese Datei dann den Inhalt:
IncludeConfFile ../../ide/bin/ide.conf
SetJavaHome ../../jdk
AddVMOption -Doracle.ide.util.AddinPolicyUtils.OVERRIDE_FLAG=true
AddVMOption -Dsun.java2d.ddoffscreen=false
AddVMOption -Dwindows.shell.font.languages=
AddVMOption -XX:MaxPermSize=128M
AddVMOption -Doracle.jdbc.mapDateToTimestamp=false
AddVMOption -Duser.language=fr
IncludeConfFile sqldeveloper-nondebug.conf
In Oracle 10g und 11g können die Werte der Bind-Variablen mit der View V$SQL_BIND_CAPTURE für SQL-Anweisungen ermittelt werden. Dafür kann folgendes Skript verwendet werden:
SELECT /*SQLBINDS*/
VS.SQL_TEXT SQL_TEXT,
VSBC.NAME BIND_NAME,
VSBC.VALUE_STRING BIND_STRING
FROM V$SQL VS
JOIN V$SQL_BIND_CAPTURE VSBC
ON VS.SQL_ID=VSBC.SQL_ID
WHERE VSBC.VALUE_STRING IS NOT NULL
AND VS.SQL_TEXT LIKE '%&SEARCHSTRING%'
AND VS.SQL_TEXT NOT LIKE '%SQLBINDS%'
/
Dieses Skript sucht nach einer SQL-Anweisung über eine angegebene Zeichenkette.
In einem Beispiel könnte dieses so aussehen:
SQL> col sql_text format a30
SQL> col bind_name format a10
SQL> col bind_string format a10
SQL> var p_numm number
SQL> exec :p_numm:=100
PL/SQL procedure successfully completed.
SQL> select last_name from hr.employees where employee_id=:p_numm;
LAST_NAME
-------------------------
King
SQL> SELECT /*SQLBINDS*/
2 VS.SQL_TEXT SQL_TEXT,
3 VSBC.NAME BIND_NAME,
4 VSBC.VALUE_STRING BIND_STRING
5 FROM
6 V$SQL VS
7 JOIN V$SQL_BIND_CAPTURE VSBC
8 ON VS.SQL_ID=vsbc.SQL_ID
9 WHERE
10 VSBC.VALUE_STRING IS NOT NULL
11 AND VS.SQL_TEXT LIKE '%&SEARCHSTRING%'
12* AND VS.SQL_TEXT NOT LIKE '%SQLBINDS%'
Enter value for searchstring: employees
old 11: AND VS.SQL_TEXT like '%&SEARCHSTRING%'
new 11: AND VS.SQL_TEXT like '%employees%'
SQL_TEXT BIND_NAME BIND_STRIN
------------------------------ ---------- ----------
select last_name from hr.emplo :P_NUMM 100
yees where employee_id=:p_numm
Oracle bietet nun die Möglichkeit Pivoting durchzuführen, ohne die DECODE-Funktion zu verwenden.
CONN HR/hr
SET ECHO ON
SET LINESIZE 400
CL SCR
SELECT *
FROM (SELECT DEPARTMENT_ID, SALARY FROM EMPLOYEES)
PIVOT(SUM(SALARY) AS SUM_SALARY FOR (DEPARTMENT_ID) IN (10 AS "10",20 AS "20",30 AS "30"));