1. Start
  2. Unternehmen
  3. Blog
  4. SQLcl, das bessere SQL*Plus

SQLcl, das bessere SQL*Plus

Einrichtung und Anmeldung

Um mit einer Oracle Datenbank zu interagieren, ist seit Jahrzehnten das SQL*Plus das erste Werkzeug der Wahl. Seit einigen Jahren hat es nun Gesellschaft bekommen, das SQLcl. Das SQLcl ist ebenso ein kommandozeilenbasiertes Werkzeug und orientiert sich mit seiner Syntax stark am SQL*Plus um den Umstieg einfach zu gestalten. Aber es bietet darüber hinaus neue und teils sehr nützliche zusätzliche Funktionen, von denen wir hier einige umreißen wollen. Aber das Wichtigste zuerst, das SQLcl wird von Oracle kostenfrei zur Verfügung gestellt, ähnlich wie der SQL Developer. Das mag unter anderem daran liegen, dass das Werkzeug vom gleichen Team entwickelt wird und das gleiche Framework verwendet. Herunterladen kann man SQLcl auf den Downloadseiten von Oracle.

Nachdem das Paket heruntergeladen und am gewünschten Zielort entpackt wurde, kann es direkt losgehen. Die erste Aufgabe ist natürlich, eine Verbindung mit einer Oracle Datenbank herzustellen. SQLcl verwendet dazu standardmäßig den JDBC-Thin-Driver, es ist also keine separate Client-Installation erforderlich. Welcher Treiber verwendet wird, sieht man, wenn ein Anmeldeversuch fehlschlägt:

 

C:\Users\marco.mischke>set PATH=c:\Oracle\sqlcl\bin;%PATH%

C:\Users\marco.mischke>sql


SQLcl: Release 21.4 Production auf Mo Feb 14 13:56:55 2022

Copyright (c) 1982, 2022, Oracle. All rights reserved. Alle Rechte vorbehalten.

Benutzername? (''?) system@vm121:1521/ml19a
Kennwort? (**********?) ******
  USER          = system
  URL           = jdbc:oracle:thin:@vm121:1521/ml19a
  Fehlermeldung = I/O-Fehler: The Network Adapter could not establish the connection (CONNECTION_ID=1VPsvGAxRKqclf6bpN3Icw==)
Benutzername? (RETRYING) ('system/*********@vm121:1521/ml19a'?) 

 

 Hier sieht man, wie aus dem EZConnect Text die URL generiert wurde, die den JDBC-Thin-Driver beinhaltet. Besser ist es natürlich, wenn die Anmeldung funktioniert. In diesem Fall muss der Hostname vollqualifiziert angegeben werden, damit es funktioniert:

 

C:\Users\marco.mischke>sql system@vm121.support.robotron.de:1521/ml19a


SQLcl: Release 21.4 Production auf Mo Feb 14 14:01:11 2022

Copyright (c) 1982, 2022, Oracle. All rights reserved. Alle Rechte vorbehalten.

Kennwort? (**********?) ******
Last Successful login time: Mo Feb 14 2022 14:01:15 +01:00

Verbunden mit:
Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Version 19.13.0.0.0

SQL> show connection
CONNECTION:
 SYSTEM@jdbc:oracle:thin:@vm121.support.robotron.de:1521/ml19a
CONNECTION_IDENTIFIER:
 vm121.support.robotron.de:1521/ml19a
CONNECTION_DB_VERSION:
 Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
 Version 19.13.0.0.0
NOLOG:
 false
PRELIMAUTH:
 false

 

Nach einer erfolgreichen Anmeldung erfährt man erst einmal nicht, wie die Verbindung aufgebaut wurde. Der Befehl "show connection" schaftt da Klarheit.

Aber was, wenn bereits ein Oracle Client installiert ist, kann SQLcl diesen dann auch verwenden? Die Antwort ist nicht ganz einfach. In unserem Fall ist ein Oracle Client 19.3 installiert. Das SQLcl kann den OCI Treiber verwenden, wenn man es mit der Option "-oci" startet. Dabei passiert nun folgendes:

 

C:\Users\marco.mischke>set TNS_ADMIN=c:\Oracle\Ora19c32\network\admin

C:\Users\marco.mischke>sql -oci hr@ml19a


SQLcl: Release 21.4 Production auf Mo Feb 14 14:05:08 2022

Copyright (c) 1982, 2022, Oracle. All rights reserved. Alle Rechte vorbehalten.

Kennwort? (**********?) ***
  USER          = hr
  URL           = jdbc:oracle:oci8:@ml19a
  Fehlermeldung = no ocijdbc21 in java.library.path   <== !!!!!!!!!!!!!!
  USER          = hr
  URL           = jdbc:oracle:thin:@ml19a
  Fehlermeldung = I/O-Fehler: The Network Adapter could not establish the connection (CONNECTION_ID=L+94qF9XSAKRcvu58HRM/Q==)
  USER          = hr
  URL           = jdbc:oracle:thin:@ml19a:1521/ml19a
  Fehlermeldung = I/O-Fehler: The Network Adapter could not establish the connection (CONNECTION_ID=ny3gaftTQTaMd5SDUIpLRw==)

 

Hier sieht man nun zwei Dinge. Zum Einen den fehlgeschlagenen Anmeldeversuch mit dem OCI-Treiber, offenbar wird ein Client der Version 21 erwartet, und zum anderen zwei weitere Anmeldeversuche, wo SQLcl versucht, einen passenden Connect-String zu generieren.

Um den OCI-Treiber doch noch verwenden zu können, haben wir den entsprechenden Client für Windows heruntergeladen und installiert. Ein erneuter Anmeldeversuch endet aber ebenfalls in einem Fehler:

 

C:\Users\marco.mischke>set ORACLE_HOME=c:\Oracle\client21

C:\Users\marco.mischke>sql -oci hr@ml19a


SQLcl: Release 21.4 Production auf Mo Feb 14 14:49:56 2022

Copyright (c) 1982, 2022, Oracle. All rights reserved. Alle Rechte vorbehalten.

Kennwort? (**********?) ***
  USER          = hr
  URL           = jdbc:oracle:oci8:@ml19a
  Fehlermeldung = Incompatible version of libocijdbc[Jdbc:214000, Jdbc-OCI:213000  

 

Offenbar erwartet das SQLcl die Version 21.4, unser Client hat jedoch die Version 21.3. Leider gibt es keinen Patch für 21.4, vermutlich weil dieser am 19.10.2021, 11 Tage nach Veröffentlichung der Windows-Downloads, bereitgestellt wurde. Auch die Version 21.5 vom Januar CPU Update wird erst am 22.02.2022 bereitgestellt werden, ist also Stand heute noch nicht verfügbar. Bleiben wir also beim JDBC-Thin-Driver.

Um nun trotzdem den Connect-String aus einer TNSNAMES.ORA öder ähnlichem zu verwenden, kann man sich eines einfachen Trocls bemühen. Der Connect-String wird mittels "tnsping" ermittelt und dann als Connect-Alias im SQLcl gespeichert. Das funktioniert so. Das SQLcl wird ohne Anmeldung gestartet, tnsping wird mittels Host-Befehl ausgeführt und die zurückgelieferte Beschreibung wird mit dem "net"-Befehl gespeichert. Der Alias kann dann für den Aufbau einer Verbindung benutzt werden:

 

C:\Users\marco.mischke>sql /nolog


SQLcl: Release 21.4 Production auf Mo Feb 14 14:22:27 2022

Copyright (c) 1982, 2022, Oracle. All rights reserved. Alle Rechte vorbehalten.

SQL> host tnsping ml19a

TNS Ping Utility for 32-bit Windows: Version 19.0.0.0.0 - Production on 14-FEB-2022 14:22:36

Copyright (c) 1997, 2019, Oracle.  All rights reserved.

Parameterdateien verwendet:
c:\Oracle\Ora19c32\network\admin\sqlnet.ora

Adapter LDAP zur Auflösung des Alias verwendet
Verbindungsversuch mit (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=vm121.support.robotron.de)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=ml19a)))
OK (240 ms)

SQL> net ml19a=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=vm121.support.robotron.de)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=ml19a)));
SQL> connect hr/hr@ml19a
Angemeldet.
SQL>

Benutzung

Nachdem nun eine Verbindung zu einer Datenbank hergestellt werden konnte, können wir uns einige der neuen Funktionen ansehen. Das Abspeichern von Aliasen für Datenbankverbindungen haben wir ja nun bereits kennengelernt. Eine weitere nützliche Funktion ist die Weiterentwicklung der DESCRIBE-Funktion. Mit "INFO <Objektname>" erhält man weitere zusätzliche Informationen.

 

SQL> describe employees

             Name       Null?             Typ
_________________ ___________ _______________
EMPLOYEE_ID       NOT NULL    NUMBER(6)
FIRST_NAME                    VARCHAR2(20)
LAST_NAME         NOT NULL    VARCHAR2(25)
EMAIL             NOT NULL    VARCHAR2(25)
PHONE_NUMBER                  VARCHAR2(20)
HIRE_DATE         NOT NULL    DATE
JOB_ID            NOT NULL    VARCHAR2(10)
SALARY                        NUMBER(8,2)
COMMISSION_PCT                NUMBER(2,2)
MANAGER_ID                    NUMBER(6)
DEPARTMENT_ID                 NUMBER(4)

SQL> info employees
TABLE: EMPLOYEES
         LAST ANALYZED:2022-02-15 07:20:01.0
         ROWS         :107
         SAMPLE SIZE  :107
         INMEMORY     :DISABLED
         COMMENTS     :employees table. Contains 107 rows. References with departments,
                       jobs, job_history tables. Contains a self reference.

Columns
NAME             DATA TYPE           NULL  DEFAULT    COMMENTS
*EMPLOYEE_ID     NUMBER(6,0)         No               Primary key of employees table.
 FIRST_NAME      VARCHAR2(20 BYTE)   Yes              First name of the employee. A not null column.
 LAST_NAME       VARCHAR2(25 BYTE)   No               Last name of the employee. A not null column.
 EMAIL           VARCHAR2(25 BYTE)   No               Email id of the employee
 PHONE_NUMBER    VARCHAR2(20 BYTE)   Yes              Phone number of the employee; includes country
                                                      code and area code
 HIRE_DATE       DATE                No               Date when the employee started on this job. A not
                                                      null column.
 JOB_ID          VARCHAR2(10 BYTE)   No               Current job of the employee; foreign key to job_id
                                                      column of thejobs table. A not null column.
 SALARY          NUMBER(8,2)         Yes              Monthly salary of the employee. Must be
                                                      greaterthan zero (enforced by constraint
                                                      emp_salary_min)
 COMMISSION_PCT  NUMBER(2,2)         Yes              Commission percentage of the employee; Only
                                                      employees in salesdepartment elgible for
                                                      commission percentage
 MANAGER_ID      NUMBER(6,0)         Yes              Manager id of the employee; has same domain as
                                                      manager_id indepartments table. Foreign key to
                                                      employee_id column of employees table.(useful for
                                                      reflexive joins and CONNECT BY query)
 DEPARTMENT_ID   NUMBER(4,0)         Yes              Department id where employee works; foreign key to
                                                      department_idcolumn of the departments table

Indexes
             INDEX_NAME    UNIQUENESS    STATUS    FUNCIDX_STATUS                  COLUMNS
_______________________ _____________ _________ _________________ ________________________
HR.EMP_JOB_IX           NONUNIQUE     VALID                       JOB_ID
HR.EMP_NAME_IX          NONUNIQUE     VALID                       LAST_NAME, FIRST_NAME
HR.EMP_EMAIL_UK         UNIQUE        VALID                       EMAIL
HR.EMP_EMP_ID_PK        UNIQUE        VALID                       EMPLOYEE_ID
HR.EMP_MANAGER_IX       NONUNIQUE     VALID                       MANAGER_ID
HR.EMP_DEPARTMENT_IX    NONUNIQUE     VALID                       DEPARTMENT_ID


References
    TABLE_NAME    CONSTRAINT_NAME    DELETE_RULE     STATUS        DEFERRABLE    VALIDATED    GENERATED
______________ __________________ ______________ __________ _________________ ____________ ____________
DEPARTMENTS    DEPT_MGR_FK        NO ACTION      ENABLED    NOT DEFERRABLE    VALIDATED    USER NAME
EMPLOYEES      EMP_MANAGER_FK     NO ACTION      ENABLED    NOT DEFERRABLE    VALIDATED    USER NAME
JOB_HISTORY    JHIST_EMP_FK       NO ACTION      ENABLED    NOT DEFERRABLE    VALIDATED    USER NAME

 

Alternativ können mit "INFO+" auch die Statistiken mit angezeigt werden:

 

SQL> info+ employees
TABLE: EMPLOYEES
         LAST ANALYZED:2022-02-15 07:20:01.0
         ROWS         :107
         SAMPLE SIZE  :107
         INMEMORY     :DISABLED
         COMMENTS     :employees table. Contains 107 rows. References with departments,
                       jobs, job_history tables. Contains a self reference.

Columns
NAME             DATA TYPE           NULL  DEFAULT    LOW_VALUE             HIGH_VALUE            NUM_DISTINCT   HISTOGRAM
*EMPLOYEE_ID     NUMBER(6,0)         No                   100                   206                   107            NONE
 FIRST_NAME      VARCHAR2(20 BYTE)   Yes                  Adam                  Winston               91             NONE
 LAST_NAME       VARCHAR2(25 BYTE)   No                   Abel                  Zlotkey               102            NONE
 EMAIL           VARCHAR2(25 BYTE)   No                   ABANDA                WTAYLOR               107            NONE
 PHONE_NUMBER    VARCHAR2(20 BYTE)   Yes                  011.44.1343.329268    650.509.4876          107            NONE
 HIRE_DATE       DATE                No                   2001.01.13.00.00.00   2008.04.21.00.00.00   98             NONE
 JOB_ID          VARCHAR2(10 BYTE)   No                   AC_ACCOUNT            ST_MAN                19             FREQUENCY
 SALARY          NUMBER(8,2)         Yes                  2100                  24000                 58             NONE
 COMMISSION_PCT  NUMBER(2,2)         Yes                  ,1                    ,4                    7              NONE
 MANAGER_ID      NUMBER(6,0)         Yes                  100                   205                   18             FREQUENCY
 DEPARTMENT_ID   NUMBER(4,0)         Yes                  10                    110                   11             FREQUENCY

Indexes
             INDEX_NAME    UNIQUENESS    STATUS    FUNCIDX_STATUS                  COLUMNS
_______________________ _____________ _________ _________________ ________________________
HR.EMP_JOB_IX           NONUNIQUE     VALID                       JOB_ID
HR.EMP_NAME_IX          NONUNIQUE     VALID                       LAST_NAME, FIRST_NAME
HR.EMP_EMAIL_UK         UNIQUE        VALID                       EMAIL
HR.EMP_EMP_ID_PK        UNIQUE        VALID                       EMPLOYEE_ID
HR.EMP_MANAGER_IX       NONUNIQUE     VALID                       MANAGER_ID
HR.EMP_DEPARTMENT_IX    NONUNIQUE     VALID                       DEPARTMENT_ID


References
    TABLE_NAME    CONSTRAINT_NAME    DELETE_RULE     STATUS        DEFERRABLE    VALIDATED    GENERATED
______________ __________________ ______________ __________ _________________ ____________ ____________
DEPARTMENTS    DEPT_MGR_FK        NO ACTION      ENABLED    NOT DEFERRABLE    VALIDATED    USER NAME
EMPLOYEES      EMP_MANAGER_FK     NO ACTION      ENABLED    NOT DEFERRABLE    VALIDATED    USER NAME
JOB_HISTORY    JHIST_EMP_FK       NO ACTION      ENABLED    NOT DEFERRABLE    VALIDATED    USER NAME

 

Mit "DDL <Objektname" kann man die Kommandos zum Anlegen eines Objektes generieren und optional direkt in eine Datei speichern.

 

SQL> help ddl
DDL
---

DDL generiert den Code zum Wiederherstellen des aufgelisteten Objekts. Verwenden Sie die Option "type"
f³r Materialized Views. Verwenden Sie die save-Optionen, um die DDL in eine Datei zu speichern.

DDL [<object_name> [<type>] [SAVE <filename>]]
SQL> ddl employees

  CREATE TABLE "HR"."EMPLOYEES"
   (    "EMPLOYEE_ID" NUMBER(6,0),
        "FIRST_NAME" VARCHAR2(20),
        "LAST_NAME" VARCHAR2(25) CONSTRAINT "EMP_LAST_NAME_NN" NOT NULL ENABLE,
        "EMAIL" VARCHAR2(25) CONSTRAINT "EMP_EMAIL_NN" NOT NULL ENABLE,
        "PHONE_NUMBER" VARCHAR2(20),
        "HIRE_DATE" DATE CONSTRAINT "EMP_HIRE_DATE_NN" NOT NULL ENABLE,
        "JOB_ID" VARCHAR2(10) CONSTRAINT "EMP_JOB_NN" NOT NULL ENABLE,
        "SALARY" NUMBER(8,2),
        "COMMISSION_PCT" NUMBER(2,2),
        "MANAGER_ID" NUMBER(6,0),
        "DEPARTMENT_ID" NUMBER(4,0),
         CONSTRAINT "EMP_SALARY_MIN" CHECK (salary > 0) ENABLE,
         CONSTRAINT "EMP_EMAIL_UK" UNIQUE ("EMAIL")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS"  ENABLE,
         CONSTRAINT "EMP_DEPT_FK" FOREIGN KEY ("DEPARTMENT_ID")
          REFERENCES "HR"."DEPARTMENTS" ("DEPARTMENT_ID") ENABLE,
         CONSTRAINT "EMP_JOB_FK" FOREIGN KEY ("JOB_ID")
          REFERENCES "HR"."JOBS" ("JOB_ID") ENABLE,
         CONSTRAINT "EMP_MANAGER_FK" FOREIGN KEY ("MANAGER_ID")
          REFERENCES "HR"."EMPLOYEES" ("EMPLOYEE_ID") ENABLE
   ) SEGMENT CREATION IMMEDIATE
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" ;
  CREATE UNIQUE INDEX "HR"."EMP_EMP_ID_PK" ON "HR"."EMPLOYEES" ("EMPLOYEE_ID")
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" ;
ALTER TABLE "HR"."EMPLOYEES" ADD CONSTRAINT "EMP_EMP_ID_PK" PRIMARY KEY ("EMPLOYEE_ID")
  USING INDEX "HR"."EMP_EMP_ID_PK"  ENABLE;

   COMMENT ON COLUMN "HR"."EMPLOYEES"."EMPLOYEE_ID" IS 'Primary key of employees table.';
   COMMENT ON COLUMN "HR"."EMPLOYEES"."FIRST_NAME" IS 'First name of the employee. A not null column.';
   COMMENT ON COLUMN "HR"."EMPLOYEES"."LAST_NAME" IS 'Last name of the employee. A not null column.';
   COMMENT ON COLUMN "HR"."EMPLOYEES"."EMAIL" IS 'Email id of the employee';
   COMMENT ON COLUMN "HR"."EMPLOYEES"."PHONE_NUMBER" IS 'Phone number of the employee; includes country code and area code';
   COMMENT ON COLUMN "HR"."EMPLOYEES"."HIRE_DATE" IS 'Date when the employee started on this job. A not null column.';
   COMMENT ON COLUMN "HR"."EMPLOYEES"."JOB_ID" IS 'Current job of the employee; foreign key to job_id column of the
jobs table. A not null column.';
   COMMENT ON COLUMN "HR"."EMPLOYEES"."SALARY" IS 'Monthly salary of the employee. Must be greater
than zero (enforced by constraint emp_salary_min)';
   COMMENT ON COLUMN "HR"."EMPLOYEES"."COMMISSION_PCT" IS 'Commission percentage of the employee; Only employees in sales
department elgible for commission percentage';
   COMMENT ON COLUMN "HR"."EMPLOYEES"."MANAGER_ID" IS 'Manager id of the employee; has same domain as manager_id in
departments table. Foreign key to employee_id column of employees table.
(useful for reflexive joins and CONNECT BY query)';
   COMMENT ON COLUMN "HR"."EMPLOYEES"."DEPARTMENT_ID" IS 'Department id where employee works; foreign key to department_id
column of the departments table';
   COMMENT ON TABLE "HR"."EMPLOYEES"  IS 'employees table. Contains 107 rows. References with departments,
jobs, job_history tables. Contains a self reference.';

  CREATE INDEX "HR"."EMP_DEPARTMENT_IX" ON "HR"."EMPLOYEES" ("DEPARTMENT_ID")
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" ;

  CREATE INDEX "HR"."EMP_JOB_IX" ON "HR"."EMPLOYEES" ("JOB_ID")
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" ;

  CREATE INDEX "HR"."EMP_MANAGER_IX" ON "HR"."EMPLOYEES" ("MANAGER_ID")
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" ;

  CREATE INDEX "HR"."EMP_NAME_IX" ON "HR"."EMPLOYEES" ("LAST_NAME", "FIRST_NAME")
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" ;

  CREATE OR REPLACE EDITIONABLE TRIGGER "HR"."SECURE_EMPLOYEES"
  BEFORE INSERT OR UPDATE OR DELETE ON employees
BEGIN
  secure_dml;
END secure_employees;
/
ALTER TRIGGER "HR"."SECURE_EMPLOYEES" DISABLE;

  CREATE OR REPLACE EDITIONABLE TRIGGER "HR"."UPDATE_JOB_HISTORY"
  AFTER UPDATE OF job_id, department_id ON employees
  FOR EACH ROW
BEGIN
  add_job_history(:old.employee_id, :old.hire_date, sysdate,
                  :old.job_id, :old.department_id);
END;
/
ALTER TRIGGER "HR"."UPDATE_JOB_HISTORY" ENABLE;

 

 Weiterhin ist es möglich, Statements fest zu hinterlegen und einen Alias dafür zu vergeben. Dieser Alias kann dann einfach zum Ausführen des Statements benutzt werden:

 

SQL> alias actsess=select username, osuser,program, machine, event, state, seconds_in_wait, sql_id from v$session where username is not null and status='ACTIVE';
SQL> actsess

   USERNAME           OSUSER                      PROGRAM        MACHINE                        EVENT                STATE    SECONDS_IN_WAIT           SQL_ID
___________ ________________ ____________________________ ______________ ____________________________ ____________________ __________________ ________________
SYS         oracle           oracle@some-server (OFSD)    some-server    OFS idle                     WAITING                               1
SYSTEM      marco.mischke    SQLcl                        rdspcXXX       SQL*Net message to client    WAITED SHORT TIME                     0 3tcj29b5cjrbf

 

Weiterhin kann das vorangegangene Statement einfach mit einem definierten Interval beliebig oft wiederholt werden:

 

SQL> repeat 3 2
1 von 3 wird um 10:22:46.719 mit einer Verzögerung von 2 s ausgeführt

   USERNAME           OSUSER                      PROGRAM        MACHINE                        EVENT                STATE    SECONDS_IN_WAIT           SQL_ID
___________ ________________ ____________________________ ______________ ____________________________ ____________________ __________________ ________________
SYS         oracle           oracle@some-server (OFSD)    some-server    OFS idle                     WAITING                               2
SYSTEM      marco.mischke    SQLcl                        rdspcXXX       SQL*Net message to client    WAITED SHORT TIME                     0 3tcj29b5cjrbf
2 von 3 wird um 10:22:48.779 mit einer Verzögerung von 2 s ausgeführt

   USERNAME           OSUSER                      PROGRAM        MACHINE                        EVENT                STATE    SECONDS_IN_WAIT           SQL_ID
___________ ________________ ____________________________ ______________ ____________________________ ____________________ __________________ ________________
SYS         oracle           oracle@some-server (OFSD)    some-server    OFS idle                     WAITING                               1
SYSTEM      marco.mischke    SQLcl                        rdspcXXX       SQL*Net message to client    WAITED SHORT TIME                     0 3tcj29b5cjrbf
3 von 3 wird um 10:22:50.827 mit einer Verzögerung von 2 s ausgeführt

   USERNAME           OSUSER                      PROGRAM        MACHINE                        EVENT                STATE    SECONDS_IN_WAIT           SQL_ID
___________ ________________ ____________________________ ______________ ____________________________ ____________________ __________________ ________________
SYS         oracle           oracle@some-server (OFSD)    some-server    OFS idle                     WAITING                               0
SYSTEM      marco.mischke    SQLcl                        rdspcXXX       SQL*Net message to client    WAITED SHORT TIME                     0 3tcj29b5cjrbf

 

Außerdem kann SQLcl die Ausgabe von Abfrageergebnissen in vielen verschiedenen Formaten erfolgen. So lassen sich beispielsweise einfach JSON-Fornate, XMLs oder auch einfach INSERT-Befehle erzeugen:

 

SQL> select * from employees where DEPARTMENT_ID=20;

   EMPLOYEE_ID    FIRST_NAME    LAST_NAME       EMAIL    PHONE_NUMBER    HIRE_DATE    JOB_ID    SALARY    COMMISSION_PCT    MANAGER_ID    DEPARTMENT_ID
______________ _____________ ____________ ___________ _______________ ____________ _________ _________ _________________ _____________ ________________
           201 Michael       Hartstein    MHARTSTE    515.123.5555    17.02.04     MK_MAN        13000                             100               20
           202 Pat           Fay          PFAY        603.123.6666    17.08.05     MK_REP         6000                             201               20

SQL> set sqlformat json
SQL> select * from employees where DEPARTMENT_ID=20;
{"results":[{"columns":[{"name":"EMPLOYEE_ID","type":"NUMBER"},{"name":"FIRST_NAME","type":"VARCHAR2"},{"name":"LAST_NAME","type":"VARCHAR2"},{"name":"EMAIL","type":"VARCHAR2"},{"name":"
PHONE_NUMBER","type":"VARCHAR2"},{"name":"HIRE_DATE","type":"DATE"},{"name":"JOB_ID","type":"VARCHAR2"},{"name":"SALARY","type":"NUMBER"},{"name":"COMMISSION_PCT","type":"NUMBER"},{"name
":"MANAGER_ID","type":"NUMBER"},{"name":"DEPARTMENT_ID","type":"NUMBER"}],"items":
[
{"employee_id":201,"first_name":"Michael","last_name":"Hartstein","email":"MHARTSTE","phone_number":"515.123.5555","hire_date":"17.02.04","job_id":"MK_MAN","salary":13000,"manager_id":10
0,"department_id":20}
,{"employee_id":202,"first_name":"Pat","last_name":"Fay","email":"PFAY","phone_number":"603.123.6666","hire_date":"17.08.05","job_id":"MK_REP","salary":6000,"manager_id":201,"department_
id":20}
]}]}
SQL> set sqlformat json-formatted
SQL> select * from employees where DEPARTMENT_ID=20;
{
  "results" : [
    {
      "columns" : [
        {
          "name" : "EMPLOYEE_ID",
          "type" : "NUMBER"
        },
        {
          "name" : "FIRST_NAME",
          "type" : "VARCHAR2"
        },
        {
          "name" : "LAST_NAME",
          "type" : "VARCHAR2"
        },
        {
          "name" : "EMAIL",
          "type" : "VARCHAR2"
        },
        {
          "name" : "PHONE_NUMBER",
          "type" : "VARCHAR2"
        },
        {
          "name" : "HIRE_DATE",
          "type" : "DATE"
        },
        {
          "name" : "JOB_ID",
          "type" : "VARCHAR2"
        },
        {
          "name" : "SALARY",
          "type" : "NUMBER"
        },
        {
          "name" : "COMMISSION_PCT",
          "type" : "NUMBER"
        },
        {
          "name" : "MANAGER_ID",
          "type" : "NUMBER"
        },
        {
          "name" : "DEPARTMENT_ID",
          "type" : "NUMBER"
        }
      ],
      "items" : [
        {
          "employee_id" : 201,
          "first_name" : "Michael",
          "last_name" : "Hartstein",
          "email" : "MHARTSTE",
          "phone_number" : "515.123.5555",
          "hire_date" : "17.02.04",
          "job_id" : "MK_MAN",
          "salary" : 13000,
          "commission_pct" : "",
          "manager_id" : 100,
          "department_id" : 20
        },
        {
          "employee_id" : 202,
          "first_name" : "Pat",
          "last_name" : "Fay",
          "email" : "PFAY",
          "phone_number" : "603.123.6666",
          "hire_date" : "17.08.05",
          "job_id" : "MK_REP",
          "salary" : 6000,
          "commission_pct" : "",
          "manager_id" : 201,
          "department_id" : 20
        }
      ]
    }
  ]
}
SQL> set sqlformat insert
SQL> select * from employees where DEPARTMENT_ID=20;
REM INSERTING into EMPLOYEES
SET DEFINE OFF;
Insert into EMPLOYEES (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,HIRE_DATE,JOB_ID,SALARY,COMMISSION_PCT,MANAGER_ID,DEPARTMENT_ID) values ('201','Michael','Hartstein','MHARTSTE'
,'515.123.5555',to_timestamp('17.02.04','DD.MM.RR HH24:MI:SSXFF'),'MK_MAN','13000',null,'100','20');
Insert into EMPLOYEES (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,HIRE_DATE,JOB_ID,SALARY,COMMISSION_PCT,MANAGER_ID,DEPARTMENT_ID) values ('202','Pat','Fay','PFAY','603.123.6666
',to_timestamp('17.08.05','DD.MM.RR HH24:MI:SSXFF'),'MK_REP','6000',null,'201','20');

Zusammenfassung

Alles in allem ist SQLcl ein mächtiger Ersatz für das herkömmliche SQL*Plus und man sollte dem Tool definitiv Beachtung schenken. Zuguterletzt sei noch erwähnt, dass sich SQLcl auch bestens eignet, um eine Oracle Cloud Umgebung zu verwalten. Es bietet Schnittstellen zu dem REST-APIs der Oracle Cloud Infrastructure und ermöglicht so auch die Verwaltung der Cloud Umgebung mittels Kommandozeile.

 

SQL> help oci
OCI
___

oci command allows for calling of Oracle Cloud OCI REST APIs

  oci profile:  lists the available profiles.
                An oci configuration file contains the profiles and is typically in ~/.oci/config.
                There are three environment variables that can be used to reference a configuration file.
                The search order is ${OCI_SQLCL_CONFIG_FILE}, ~/.oci/config, ${OCI_CLI_CONFIG_FILE}, ${OCI_CONFIG_FILE}

 oci region list: lists all the regions subscribed to by the tenancy

 oci region <region_name>: selects the region_name if tenancy is subscribed to this region
                           Throws an error if the region_name is not subscribed to by this tenancy

 conn <connection_ocid>: Connects to an Oracle Database as defined by a connection in the DBTools Cloud service.
                           <connection_ocid> is the ocid of the Connection definition.
 conn -rest <connection_ocid>: Connects to an Oracle Database as defined by a connection in the DBTools Cloud service over REST.
                                 <connection_ocid> is the ocid of the Connection definition.

  oci clear: clears the profile, region and connection setting

  Format 1: target specified completely on OCI command
    oci <host> <method> [file-to-send-as-body] <request-target>

  Format 2: target resolved by CLOUDSTORAGE (CS) uri specification and qualifier specified OCI command
    oci <method> [file-to-send-as-body] <qualifier>


Examples Format 1:
  oci profile my-profile
    Sets profile to be used
  oci objectstorage.us-ashburn-1.oraclecloud.com delete /n/abc123/b/testing-bucket/o/my_emp.csv
    Deletes my_emp.csv from testing-bucket
  oci objectstorage.us-ashburn-1.oraclecloud.com get /n/abc123/b/klrice-testing/o/
    Lists contents of testing-bucket
  oci objectstorage.us-ashburn-1.oraclecloud.com put ./my_emp.csv /n/abc123/b/testing-bucket/o/my_emp.csv
    PUTs my_emp.csv into  testing-bucket
  oci objectstorage.us-ashburn-1.oraclecloud.com get /n/abc123/b/testing-bucket/o/my_emp.csv
    GET file my_emp.csv from testing-bucket
  oci identity.us-ashburn-1.oraclecloud.com get /20160918/compartments/?compartmentId=<ID>
    List Compartments

Examples Format 2:
  oci profile my-profile
    Sets profile to be used
  cs objectstorage.us-ashburn-1.oraclecloud.com
  oci delete /n/abc123/b/testing-bucket/o/my_emp.csv
    Deletes my_emp.csv from testing-bucket
  cs objectstorage.us-ashburn-1.oraclecloud.com/n/abc123/b/klrice-testing/o/
  oci get
    Lists contents of testing-bucket
  oci put ./my_emp.csv /o/my_emp.csv
    PUTs my_emp.csv into testing-bucket
  oci get /o/my_emp.csv
    GET file my_emp.csv from testing-bucket
  oci identity.us-ashburn-1.oraclecloud.com get /20160918/compartments/?compartmentId=<ID>
    List Compartments
  cs objectstorage.us-ashburn-1.oraclecloud.com/n/abc123/b/testing-bucket
  cs listo
    Lists contents of testing-bucket (See CS command help)

See OCI API Documentation for REST Details : docs.cloud.oracle.com/en-us/iaas/api/

 

 

Kommentare

Keine Kommentare

Kommentar schreiben

* Diese Felder sind erforderlich