Datentypen Number(4,2) Varchar2(10) Long Date xx,xx round (257,82 , 1) = 257,8 round (257.82 , -2) = 300 Tabelle erstellen Check (nur angegebene Werte möglich) Create table personal ( Personal_nr number(6) NOT NULL, vorname varchar2(15) DEFAULT 'Standardname', constraint PK_Personal primary key (personal_nr), constraint FK_Personal_Abteilung foreign key (abteilung_nr) references abteilung (abteilung_nr) on delete cascade, constraint CK_Personal_Kz_Weiblich check (kz_weiblich in (0,1)) ); Tabelle löschen cascade (alle Fremdschlüssel werden aus den anderen Tabellen gelöscht) Drop table personal cascade constraints; Spalten hinzufügen alter table personal add ( Kz_Geschlecht ); Datentyp, Feldgröße ändern alter table personal modify ( Kz_Geschlecht ); number(1) Not Null number(2) Not Null Integritätsregeln Nachträglich Hinzufügen alter table personal ( add constraint UQ_personal drop unique (vorname) ); löschen ausschalten disable enable Einfügen von Daten Insert into personal (personal_nr, vorname) values (12, 'Hugo', to_date('09.06.1999' , 'dd.mm.yyyy') ); Daten löschen keinen * verwenden ohne where (alle Zeilen gelöscht) Delete from personal Where personal_nr = 1; Daten der Tabelle löschen Truncate table personal; Daten ändern Update personal Set vorname = 'Hans', Name = 'Meier' Where personal_nr = 5; einschalten Daten Anzeigen distinct (gruppieren) Select distinct personal_nr, count (*) as Anzahl to_char (geburtsdatum, 'dd.mm.yyyy') Geburtsdatum From personal Where Kz_geschlecht = 1 and Geburtsdatum = to_date('01.01.1999' , 'dd.mm.yyyy') or trunc (Geburtsdatum ) = trunc (sysdate) Group by name Having count (*) <= 1 Order by vorname desc, name asc desc = absteigend Where: =,<,>,<>,!=,<=,>=,is null, is not null, like, in, between, not, and, or % = wie Dos *, _ = wie Dos ? like 'M%' between 1 and 5 in (3,5) = nur 3 und 5 Datum: Eingabe: Ausgabe: Abfrage: Format: Runden: Differenz: Letzter Tag: Nächster Tag: to_date ('01.01.1999' , 'dd.mm.yyyy') to_char (sysdate, 'dd.mm.yyyy hh24:mi:ss') trunc (datum) = to_date ('01.01.1999' , 'dd.mm.yyyy') 'dd.mm.yyyy hh24:mi:ss' to_char (round (to_date ('01.01.1999' , 'dd.mm.yyyy') , 'year') , 'dd.mm.yyyy') months_between(to_date ('01.01.1999' , 'dd.mm.yyyy') , to_date ('01.01.1999' , 'dd.mm.yyyy')) to_char (last_day (sysdate) , 'dd.mm.yyyy hh24:mi:ss') to_char (next_day (sysdate, 'monday') , 'dd.mm.yyyy hh24:mi:ss') Aggregatfunktionen: count (*/spalte/distinct) Max (spalte), min (spalte) Sum (spalte) Avg (spalte) Nur bei: Nummerisch: = Anzahl = größter Wert / kleinster Wert = Summe = Durchschnitt distinct select count (distinct Einstelldatum) from personal; Special where to_char(datum,'yyyy') = '1999' select name, 6.5 * 2 as Glückszahl distinct da gleich gruppiert werden soll Auf Jahr 1999 abfragen Es wird die Berechnung als Konstante (13) ausgegeben Unterabfragen select name, gehalt from personal where gehalt < (select avg(gehalt) from personal); ... in (select ...); bei 1 Rückgabewert: <, >, =, ... bei mehreren Rückgabewerten syncronisierte Unterabfragen select p1.personal_nr, p1.name from personal p1 where gehalt > (select avg(gehalt) from personal p2 where p2.filiale_nr = p1.filiale_nr); select f.filiale_nr, f.bezeichnung from filiale f where not exists (select * from personal p where p.filiale_nr = f.filiale_nr and p.geschlecht = 'M'); Joins Vorgehensweise select p.personal_nr, f.bezeichnung from personal p, filiale f where p.filiale_nr = f.filiale_nr; Reihenfolge abarbeitung: 1. From select filiale_nr, bezeichnung from filiale where filiale_nr in (select filiale_nr from personal where geschlecht = 'M'); 1. Welche Tabellen 3. Welche Spalten 5. Gruppierung 2. Where 3. Group 2. Verknüpfung d. Tab 4. Einschränkungen (where) 6. Sortierung 4. Having 5. Select Views insert, update, delete möglich Create or replace view v_personal (name, filiale_nr, geburtsdatum) as select p.name, f.filiale_nr, to_char(p.geburtsdatum,'dd.mm.yyyy') from filiale f, personal p where f.personal_nr = p.personal_nr with check option with read only Daten nicht änderbar Spaltenüberschrift (optional + beliebig) kein Order by möglich zum abprüfen der where-Klausel Outer Joins Select f. filiale, f.bezeichnung, p.personal_nr From personal p, filiale f where f.filiale_nr = p.filiale_nr (+); Haupttabelle Nachgeordnete Tabelle (hier sollen alle DS angezeigt werden) (hier stehen nicht alle DS / hier müssten DS hinzugefügt werden) wenn FS keine Not-Null Spalte ist bei 1:n Beziehungen Mengenoperation UNION Vereinigung select filiale_nr, bezeichnung, ort from filiale where Ort = 'München' UNION select filiale_nr, null, null from personal where name = is null order by 1, 2 Doppelte DS nur 1 x angezeigt gleiche Anzahl an Spalten gleicher Datentyp UNION ALL wie oben aber DS doppelt angezeigt INTERSECT Durchschnitt Schnittmenge MINUS A1 Restmenge A2 DS die in A1 aber nicht in A2 vorkommen Rechnen mit Tabellenspalten (+ - * /) Wenn Spalte Null Ergebnis auch Null Lösung: NVL(Gehalt, 1000) falls Gehalt NULL, dann Ersatzwert 1000 verwenden select sum(nvl(Kaufpreis,0)) from fahrzeug; PL/SQL kein Create, alter Zahl2 constant number(2) := 13; Konstante Name varchar2(20) default substr(vorname,1,20); Name2 varchar2(20) not null default 'Buchung'; initialisierung nie auf null If Bed1 then Elseif Bed2 then Else End if wie case default Loop I:= i+1 If i > 100 then Exit; End if; End loop; oder Exit when i > 100 For i in reverse 1..100 loop ...; end loop; nicht 1000..1 for i in 5..50 loop if mod(i,5) = 0 then ...; end if; end loop; loop while Bed loop ...; end loop; if Bed Exit; End if; End loop; Cursor %Notfound kein DS gefunden Null, False, True %found DS gefunden Null, False, True %Rowcount anzahl eingelesener DS 0, 1, ... %Isopen Cursor geöffnet False, True Open c_personal; Fetch c_personal into l_personal_nr, l_gehalt; Struktur rec_personal c_personal%Rowtype; Close c_personal; Fetch c_personal into rec_personal; DECLARE Cursor c_filiale is Select filiale_nr, bezeichnung From filiale Order by filiale_nr; Cursor c_personal (p_filiale_nr number, p_gehalt number := 3500) is Defaultwert 3500 Select personal_nr, name, vorname, gehalt From personal Where filiale_nr = p_filiale_nr And gehalt = p_gehalt; L_min_gehalt personal_gehalt%type; BEGIN For rec_filiale in c_filiale loop Dbms_output.put_line(to_char(rec_filiale.filiale_nr) || ' ' || rec_filiale.bezeichnung); Select min(gehalt) Into l_min_gehalt Ergebnis darf nur 1 DS zurückliefern From personal Where filiale_nr = rec_filiale.filiale_nr; For rec_personal in c_personal (rec_filiale.filiale_nr, L_min_gehlat) loop Dbms_output.put_line(....); If c_personal%Rowcount > = 3 then Exit; End if; End loop; End loop; END; / Fehlerbehandlung Exception when No_Data_Found then Statements; when others then Statements; 1. Too_Many_Rows Einen Namen für eine best. Fehlernummer vergeben filiale_noch_vorhanden exception; pragma exception _init(filiale_noch_vorhanden, -2292); when filiale noch_vorhanden then ... Deklaration "" Exception 2. Selbsterstellte System-Fehlermeldung Werfen when No_Data_Found then raise_application_error(-20001, 'Personal_nr nicht vorhanden'); 3. Selbsterstellte Fehlermeldung erstellen / prüfen ort_pruefung exception; if l-ort = 'New York' then raise ort_prüfung when ort_pruefung then ... SQLERRM SQLCODE SQLERRM(SQLCODE) Deklaration Begin Exception Fehlermeldung des zuletzt aufgetretenen Fehlers Fehlernummer Fehlermeldung zur Fehlernummer Prozeduren Funktionen PROCEDURE maxgehalt(p_filiale_nr IN number) FUNCTION maxgehalt(p_filiale_nr IN number) RETURN number IS IS l_maximum personal.gehalt%type; l_maximum personal.gehalt%type; BEGIN BEGIN select ... select ... return l_maximum; EXCEPTION EXCEPTION when ... when ... return l_maximum; END; END; Werden definiert im Deklarationsteil im PL/SQL Stored Procedures Prozeduren Funktionen wie oben aber: CREATE or replace PROCEDURE .... wie oben aber: CREATE or replace FUNCTION .... show errors PROCEDURE maxgehalt; show errors FUNCTION maxgehalt; Verwendung: es können Funktionen verwendet werden, die Wert zurückliefern u. keinen OUT-Parameter haben. select filiale_nr, max_gehalt(filiale_nr ) from filiale; Parameter Übergabe IN (Default) OUT IN OUT Positional: maxgehalt(5) Namentlich: maxgehalt(p_filiale_nr => 5, ...) Gemischt: maxgehalt(p_filiale_nr => 5,p_personal_nr, ...) Abhängigkeiten select object_name, object_type, status from obj where status = 'INVALID'; Objectstatus prüfen: VALID, INVALID alter procedure/function maxgehalt compile; SEQUENCER create sequence seq_filiale_nr increment by 1 start with 20 nomaxvalue / maxvalue 50 nominvalue / minvalue 10 nocycle / nocycle cache 10 / nocache order / noorder; erste Zahl höchste Zahl kleinste Zahl Neuanfang wenn Max erreicht Nr im Hauptspeicher Reihenfolge der Anforderungen alter sequence seq_filiale_nr ...; Start with steht nicht zur Verfügung drop sequence seq_filiale_nr; select seq_filiale_nr.currval from dual; select seq_filiale_nr.nextval from dual; aktueller Zählerstand nächster Zählerstand für Insert Package create or replace package pack_max is FUNCTION maxgehalt(p_filiale_nr IN number) RETURN number; END pack_max; / show errors package pack_max; create or replace package body pack_max is g_max number; FUNCTION maxgehalt(p_filiale_nr IN number) RETURN number IS l_maximum personal.gehalt%type;END pack_max; BEGIN/ select ... return l_maximum; EXCEPTION when ... return l_maximum; END maxgehalt; BEGIN g_max := 20; END pack_max; / show errors package body pack_max; Globale Variable Trigger nur für Tabellen, nicht für Views create or replace trigger Personal_bar_uid before delete or insert or update on personal for each row declare alter_wert varchar2(30); neuer_wert varchar2(30); begin if deleting then alter_wert := to_char(:old.personal_nr); neuer_wert := null; end if; if inserting then alter_wert := null; neuer_wert := to_char(:new.personal_nr); end if; if updating ('Filiale_nr‘) then alter_wert := to_char(:old.personal_nr); neuer_wert := to_char(:new.personal_nr); end if; insert into protokoll (p_user, datum, alter_wert, neuer_wert) values (user, sysdate, alter_wert, neuer_wert); Z u s at z b ei s pi el before after eachrow update insert delete nur wenn mehrere Ereignisse (delete, insert, update) nur wenn "for each row": :old Wert vor Änderung :new Wert nach Änderung if user != 'SYSTEM‘ then if to_char(sysdate, 'hh24:mi‘) not between ’08:00‘ and ’17:00‘ then raise_application_error(-20001, 'Dateneingabe nur' || 'zwischen 08:00 und 17:00 erlaubt!'); end if; end if; select seq_personal_nr. nextval into l_personal_nr from dual; :new.personal_nr := l_personal_nr; alte Nr = null; neue Nr = z.B. 13, wird in Funktion eingesetzt end; / show errors trigger Personal_bar_uid; Datenbanksperren lock table personal in row share/exclusive mode; Sicherheit Objekt-Privilegien (Kaskadenförmig) System-Privilegien (nicht Kaskadenförmig) Grant select, update(personal_nr), ... / Grant all on personal to wenz with grant option; Grant create session / Grant any privilege to wenz with admin option; Revoke select / Revoke all on personal from wenz; Revoke create session from wenz; create role app_dba identified by passwort; grant select, update on wenz to app_user grant create session, app_user to app_dba grant app_dba to wenz;