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