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.

 OAEC1oracle ptnr clr rgb

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.

  OAEC1oracle ptnr clr rgb

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.

  OAEC1oracle ptnr clr rgb

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|     (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

Developer in englisch


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

Developer in französisch

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"));

Seite 1 von 2