word image
Mitschrift (Lernskript)

Programmieren: PL, SQL und MFC

4.060 / ~32 sternsternsternsternstern_0.5 Adam M. . 2008
<
>
Download

Mitschrift
Informatik

HTL Villach

1997

Adam M. ©
6.00

0.19 Mb
sternsternsternsternstern_0.5
ID# 273







PL/SQL


SQL…structured query language

4 GL – Sprache für relationale Datenbanken

DELETE FROM Mitarbeiter WHERE abt_nr=30;

Löscht alle Mitarbeiter der Abteilung 30 wie Server das macht bleibt verborgen


PL/SQL…procedural language

3 GL Sprache mit sequentiell ablaufenden Algorithmen


Aufbau eines PL/SQL Blocks

DECLARE…declarative section

Variable, Typen, Cursor, lokale Unterprogramme

BEGIN…executable section

PL-Anweisungen, SQL Statements

EXCEPTION…exception handling section

END;


Anonyme Blöcke

Benannte Blöcke dynamisch erzeugt, nur 1 mal ausgeführt

Unterprogramme procedure, function, package

Werden in der DB gespeichert.

Trigger… benannte Blöcke, die gespeichert werden.


Bsp. Mitarbeiter Abteilung


Abteilung 30 löschen, aber Mitarbeiter sollen bleiben und auf 0 gesetzt werden.


DECLARE

Abt_nr_v abteilung.abt_nr%TYPE:=30; //Datentyp wird übernommen

Anz_rec_v NUMBER(5);

a EXCEPTION;

BEGIN

SELECT COUNT(*) INTO anz_rec_v FROM mitarbeiter

WHERE abt_nr=abt_nr_v;

IF anz_rec_v > 0 THEN

UPDATE mitarbeiter SET abt.nr = NULL

WHERE abt_nr=abt_nr_v;

END-IF;

DELETE FROM abteilung WHERE abt_nr=abt_nr_v;

IF SQLERR !=0 THEN

RAISE a

END-IF;

COMMIT;

EXCEPTION

WHEN a THEN

INSERT INTO LOG_TABEL…

END;


Daten Deklaration


SYNTAX:

Name type[CONSTANT][NOT NULL][:=value];

PL/SQL-Datentypen



Scalare DT

Numerisch

Character

Raw

Date

Vowid

Boolean

Zusammengesetzte DT

Record

Table


Numerisch

NUMBER(p,s)…wie DB-Typ

P…precission, Anzahl der Ziffer, max 38

S…scale, Nachkommastellen

Für integer und float

BINARY-INTEGER…4Byte

Für schnelle Berechnungen im Programm

(Schleifenzähler)


Character

VARCHAR2(L)…char-String variabler Länge

CHAR(L)…char-String fixer Länge, blank padded

LONG…wie VARCHAR2


Raw

RAW(L)…wie char, jedoch für binäre Daten, keine Konvertierung zw. Char-Sets

LONGRAW(L)…wie Long aber für Binäre Daten


Gegenüberstellung PL/SQL Datentypen und Database DT



PL/SQL

MAXLENGTH

Database

MAXLENGTH

CHAR

32767

255

VARCHAR2

32767

2000

LONG

32767

2.147.483.647

RAW

32767

255

LONGRAW

32767

2.147.483.647

date

DATE…Datum/Zeit 7Byte

Century/year/month/day/hour/minute/second

Funktionen: TO_DATE

TO_CHAR


Rowid

ROWID (DB) Pseudocolumn ROWID)

BBBBBBBB.RRRR.FFFF eindeutige Nr innerhalb der DB

DB Block File NR

Reihe im block

0000001E.00FF.0001

30 Block, 255 Reihe, in File 1


Boolean

BOOLEAN…kann Werte TRUE,FALSE,NULL annehmen


Verwendung von %TYPE

var_name table.column%TYPE[:=value]

abt_nr_v abteilung.abt_nr%TYPE:=30

nimmt Datentyp von abt_nr aus Tabelle abteilung an.


Konvertierungen:

Explizit: TO_CHAR

TO_DATE

TO_NUMBER

RAWTOHEX

HEXTORAW

CHARTOROWID

ROWIDTOCHAR


Implizit character u. number

character u date


Ausdrücke und Operatoren

Zuweisung:

var_name:=expression;

Operatoren:

**,Not Exponent,Negation

+,- unär

*,/

+,-,|| string concatenation

=, !=, <,>,<=,>=

IS NULL, LIKE

BETWEEN, IN

AND

OR


Kontroll-Strukturen

IF-THEN-ELSE

IF condition THEN

Statements;

[ELSIF condition THEN

statements;]

[ELSE

statements;]

END IF;

LOOP’s

LOOP

Statements

[EXIT [WHEN condition];]

END LOOP


WHILE condition LOOP

Statements;

END LOOP;


FOR loop_counter IN [REVERSE] low_bound high_bound LOOP

Statement

END LOOP


FOR Z IN 1 10 LOOP


Implizit deklariert


Kommentar

-- Kommentarzeile


Records


TYPE record_type IS Record (

Field1 type 1 [NOT NULL][:=value],

Field2 type 2 [NOT NULL][:=value],

Fieldn type n[NOT NULL][:=value]);


Recorddeklaration:

Record_name record_type;

Zugriff:

Recordname.field_name;

%ROWTYPE

recordname tablename%ROWTYPE;

Struktur der Tabelle wird übernommen


Verwendung von SQL in PL/SQL


SELECT select_list INTO PL/SQL.data FROM …

DECLARE

Mitarbeiter_rec mitarbeiter%ROWTYPE;

BEGIN

SELECT * INTO mitarbeiter_rec FROM mitarbeiter

WHERE m_nr=1;

SELECT v_name,n_name INTO mitarbeiter_rec.v_name …

END;


Aufgabe:



Patient Warteliste


Aufnahme Station


Station

zuordnung


Patient(P_NR,Name)

Warteliste(P_NR,E_datum,E_grund)

Aufnahme(Nr, P_NR,E_datum,E_grund,st_bez)

Station(st_bez,betten_anz)

Stationszuordnung(st_bez,e_grund)


SQL innerhalb von PL/SQL Blöcken


SQL-Statements:

DML: Select, Insert, Update, Delete

DDL: Create, Drop, Alter, Grant, Revoke

DCL: Transaction Control TC: Commit, Rollback, Savepoint

Session Control: Alter Session, Set Role …

System Control: Alter System, …

Embedded SQL: OCI Oracle Call Interface

In PL/SQL sind nur DML und TC Statements erlaubt.

Grund: Early binding von Objketen zur Compile Zeit

Identifizierung des Speicherplatzes

Überprüfung der Zugriffsrechte

BEGIN

Create Table my_tab(…)

END;

Create Table ist nicht erlaubt in PL/SQL da sich die Zugriffsrecht ändern können und ein Create nicht mehr erlaubt sein kann.

DML und TC sind die einzigen die die Zugriffsrechte auf Datenbankobjekte nicht veränden.


DML – Statements

WHERE – Klausel


<<Blockname>> -- wenn erwünscht

DECLARE

department CHAR(3);

BEGIN

v_department:=‛cs‛;

DELETE FROM dept WHERE department = bockname.department;

END;

Character - Vergleich


Arten:1 blank padded

‚abc‛=‛abc‛

‚abc ‚=‛abc‛ -- bei non blank padded nicht so

Blank padded wird verendet wenn beide Operanden fixed lenght sind: CHAR

Non blank padded: Wenn einer oder beide variable length sind: VARCHAR2

‚Literal‛…fixed length.


Department … VARCHAR2(3)

DECLARE

V_dept CHAR(3)

BEGIN

DELETE FROM dept WHERE department=v_Dept;

END;

Bei unterschiedlichem Datentyp wird nichts gelöscht.


Transaction Control

Zusammenfassung von SQL Statements die entweder alle Vollständig oder gar nicht ausgeführt werden.

TA beginnt mit dem 1. Statement nach einem COMMIT (od. Rollback) oder nach CONNECT TO DB.

COMMIT…Änderungen in Tabellen fixieren.

LOCKS aufheben.

ROLLBACK…Alle Änderungen bis zum letzten COMMIT rückgängig machen.

SAVEPOINT name…

ROLLBACK TO SAVEPOINT name

Autocommit – option: COMMIT nach jedem SQL – Statement.


Transaktion u. PL/SQL – Block

Block ist kein TA – Beginn


INSERT INTO tab Values (…)

BEGIN

DELETE FROM tab…

ROLLBACK; macht auch INSERT rückgängig

END;


CURSOR


Select …INTO…

Wenn Abfrage nur 1 Reihe als Ergebnis liefert

Cursortechnik, wenn Abfrage mehrere Reihen liefert

Bei Abarbeitung eines SQL Statements wird von der Datenbank Speicherplatz allokiert (Context Area) Sie enthält geparstes(überprüftes) SQL Statement. Und nach Ausführung der Abfrage (OPEN) die Ergebnisse.

Cursor ist ein Zeiger auf Ergebnisreihen (nach open auf 1.Reihe)


Expliziter Cursor:

Schritte:

1.                  DECLARE Cursor

2.                  OPEN Cursor

3.                  FETCH

4.                  CLOSE


1.                  Cursor deklarieren, in DECLARE Section
CURSOR cursor_name IS SELECT_Statement (ohne INTO);
in WHERE Clausel können PL/SQL Variablen verwendet werden: bind variables à müssen vor CURSOR deklariert werden !.

2.                  Cursor öffnen (in Begin Section)
Open cursor_name;
Wirkung: Werte der Bindvariablen werden in SQL-Statement übertragen.
(nur zur Cursor – Open – Zeit)
SQL – Statement liefert Ergebnisreihen
Cursor wird auf 1 Satz positioniert.

3.                  Fetching:
FETCH cursor_name INTO list_of_variables;
FETCH cursor_name INTO PL/SQL – record;
Nach jedem Fetch wird der Pointer auf die nächste Reihe positioniert.
%NOTFOUND tritt am Ende nach letzten gültigen Satz ein. à Output Daten werden auf 0 gesetzt.

4.                  Cursor schließen
CURSOR cursor_name;
Gibt die vom Cursor belegten Ressourcen wieder frei.

Cursor – Attribute:

%FOUND… True, wenn vorhergehendes FETCH eine Reihe geliefert hat.

%NOTFOUND…True, -- „ -- --„-- keine Reihe

%ISOPEN…True, wenn CURSOR bereits geöffnet.

%ROWCOUNT…aktuelle Anzahl der ‚gefetchten‛ Reihen.


CURSOR-FETCH-LOOPSv

v_abt_bez VARCHAR2(10);

CURSOR C1 IS

SELECT * FROM Mitarbeiter

WHERE abt_Bez = v_abt_Bez

ORDER by m_name;

C1_rec C1%ROWTYPE; -- Deklaration auf Basis der Cursor-Definition.

Rec_anz NUMBER(5);

BEGIN

v_Abt_Bez:=‛EDV‛;

OPEN C1;

LOOP

FETCH C1 INTO C1_rec;

Exit when C1%NOTFOUND;

END LOOP;

Rec_anz:=C1%ROWCOUNT;

CLOSE C1;

END;


WHILE-LOOPS


Open C1;

FETCH C1 into C1_rec;

While C1%FOUND LOOP

Insert Into …;

FETCH C1 into C1_rec;

END LOOP;

Close C1;

Commit;

End;


Cursor For Loops


For C1_rec in C1 Loop }Führt implizit ein Open C1 und Fetch C1 into C1_rec %Found durch

Wird impliziert deklariert (nicht in Declare Section, nur in Schleife gültig)

Hat den Typ C1%ROWTYPE

Verarbeitung


End Loop; } Close C1


Select …For Update Cursor


Select …From…

For Update [of column] [Nowait];


Setzt nach Open Cursor ein Exclusiv ROW LOCK auf jede ausgewählte Reihe für ein nachfolgendes Update.

Sind Reihen durch einen anderen Prozeß gesperrt, dann wird auf die Freigabe gewartet, außer der NOWAIT Zusatz ist angegeben.


Where Current of Cursor

In Update u. Delete


Für Zugriff auf die Reihe die durch den Cursor im vorhergehenden Fetch ausgewählt wurde.


Stunden Mittel

Mitarbeiter Arbeiten Projekt


Abteilung Prozent

Mittel der Projekte der EDV-Abteilung, die gerade bearbeitet werden, um Prozentsatz erhöhen.


Declare

Cursor Help IS Select


For Help_rec in Help Loop

Where Current of Help;


Error Handling


Exception: Werden bei Auftreten eines Runtime Errors ausgelöst

SQL - Fehler

Fehler

Prozeduraler Errorl


-         userdefinierte Exceptions

-         vordefinierte Exceptions


DECLARE

TooManyPersons: EXCEPTION; -- userdefiniert

Current_persons NUMBER(4);

BEGIN

SELECT count(*) into current_person FROM persons;

IF current_persons > 10 THEN

RAISE TooManyPersons;

END IF;

EXCEPTION

WHEN TooManyPersons THEN

INSERT into Log_Table values(…)

END;


Raising Exceptions


-         implizit bei vordefinierten Exceptions.

-         Explizit durch RAISE bei userdefinierten Exceptions

Bzw. auch bei Vordefinierten

BEGIN

INSERT into Person (id, name, ) values (100,‛Walter‛);

INSERT into person (id, name) values (100,‛Eva‛);

END;

ORA-00001: unique constraint violated


Handling Exceptions

EXCEPTION

WHEN exc_name1 THEN

Statement 1;

WHEN exc_name2 THEN

Statement 2;

WHEN OTHERS THEN

Statement n;

SQLCODE u. SQLERRM


SQL – built in functions:

Um WHEN OTHER FEHLER zu identifizieren

SQLCODE… liefert aktuellen Errorcode

SQLERRM… liefert aktuelle Errog Message


DECLARE

ErrorCode NUMBER;

ErrorMSg VARCHAR2(200)

BEGIN


EXCEPTION

WHEN OTHERS THEN

ErrorCode:=SQLCODE;

ErrorMSg:=SUBSTR(SQLERRM,1,200);

Insert into Log_Tab values(ErrorCode,ErrorMSg,‛OracleError‛);

END;


SQLERRM mit 1 Argument

SQLERRM(100) ß SQLCODE liefert ORA-001403: no data found

SQLCODE ist immer negativ, außer 100

SQLERRM(-1)


Eigene Fehlertexte definieren:

RAISE_APPLICATION_ERROR (error_nr, error_text)

Errorn … -20000 bis –20999


Error-Message max 512 Bytes


Exception Propagation


Exceptions in Executable Section

Blockstrukture


DECLARE


BEGIN

DECLARE


BEGIN innerer Block


END;


END;


Wenn der aktuelle Block einen Handler für die exception besitzt wird dieser Handler ausgeführt und der Block beendet.

Wenn kein Handler vorhanden ist wird die Exception dem äußerem Block weitergegeben.


Beispiel 1:


DECLARE

A EXCEPTION;

BEGIN

BEGIN

RAISE A;

EXCEPTION A;

WHEN A THEN


END;


END;


Bsp.: 2

DECLARE

A Exception;

B Exception;

BEGIN

BEGIN

RAISE B;

EXCEPTION

WHEN A THEN


END;

Exception

WHEN B THEN


END;


Bsp.: 3

DECLARE

A EXCEPTION

B EXCEPTION

BEGIN

BEGIN

RAISE A

RAISE B

EXCEPTION

WHEN A THEN

RAISE;

WHEN B THEN

RAISE A;

END;

EXCEPTION

WHEN A THEN


END;


Exceptions in Declarative Section


Werden immer an den übergeordneten Block weitergeleitet.

DECLARE

Val NUMBER(3):=‛ABC‛;

Value_Error

BEGIN


EXCEPTION

WHEN OTHERS THEN


END;


EXCEPTIONS in der Exception-Section

Werden an den übergeordneten Block weitergeleitet, da nur 1 Exception aktiv sein kann.


Transaktion Wiederholen.


For i in 1 10 LOOP


Begin

SAVEPOINT SP;

(SQL-Statemets)

COMMIT;

EXIT;

Exception

WHEN … THEN

ROLLBACK TO SP

END;

END;


Prozeduren


Create [OR Replace] Procedure procedure_name

[(argument[{IN|OUT|IN OUT}] type,

argument [{IN|OUT|IN OUT}]type)] AS

procedure body


Procedure Body

[Declaration Section] (ohne DECLARE)

BEGIN

Executable Section

[EXCEPTION

Exception Section]

END procedure_name;


Create or replace procedure test

( in_Par IN NUMBER

out_Par OUT NUMBER

inout_Par IN OUT NUMBER) AS

local_var NUMBER;

BEGIN

Loca_var:=in_Par; ü

In_Par:=7; --Error

Out_Par:=7; ü

Local_Par:=Out_Par; --Error

Local_var:=inout_Par; ü

Inout_Par:=7; ü

END TEST;


Declare

Var1 NUMBER:=10;

Var2 NUMBER;

Var3 NUMBER;

BEGIN

TEST(var1,var2,var3);

END;


Prozeduren sind kompilierte Datenbankobjekte.


Funktionen


Create [OR REPLACE] Function function_name

[(…Arguments)]

Return return_type AS

Function body


Returnstatement:

RETURN expression;


Create or Replace function get_name

(v_m_nr IN NUMBER)

Return VARCHAR2(20) AS

Help_name VARCHAR(20);

BEGIN

SELECT m_name INTO Help_Name

FROM personal p where

p.m_nr=v_m_nr;

Return help_name;

END;


Löschen von Prozeduren und Funktionen


DROP PROCEDURE procedure_name

DROP FUNCTION function_name


Prozeduren und Funktionen sind Datenbankobjekte: Sie befinden sich in versch. Tabellen.

User_objects

User_source System-View

User_errors

SELECT object_name, object_type, STATUS FROM user_objects where object_name=‛GET_NAME‛;


SELECT * FROM User_errors;


Lokale Unterprogramme


DECLARE

- - Prototyp

PROCEDURE A ();

- - Definition

Procedure A AS in declare Section

BEGIN

END A;

BEGIN

A ( );

END;


Lokale Unterprogramme sind nicht vorcompilierte Datenbankobjekte.


Abhängigkeiten von Unterprogrammen



Schüler


Klasse getFreePlaces


Log_Table Log_Function


Status von GetFreePlaces u. Log_function sei nach Übersetzung VALID

Wird eine DDL Operation auf ein abhängiges Objekt angewandt, dann wird der Status der UP Invalid.

ALTER TABLE Klassen ADD (notendurchschnitt NUMBER(3.2));

GetFreePlaces und Log_Function à Status INVALID


Trigger


CREATE [OR REPLACE] TRIGGER trigger_name

{BEFORE | AFTER } trigger_event ON table_name

[FOR EACH ROW [WHEN trigger_condition]]

trigger_body;


Trigger Typen: Unterscheidung nach Statement, Timing, Level,

Statement: INSERT, UPDATE, DELETE

Timing: BEFORE, AFTER

LEVEL:ROW, STATEMENTà Trigger wird nur 1 mal für das auslösende

Statement ausgeführt

For Each Row, Trigger wird für jede Reihe ausgeführt die durch das auslösende Statement betroffen ist.


12 mögliche Arten 3*2*2

Before Update statement level

After Insert or Delete row level


Trigger_event INSERT, UPDATE, DELETE

oder Kombination

trigger_body: PL/SQL – Block mit Ausnahme von TC Statements (COMMIT, ROLLBACK,SAVEPOINT)

Trigger befindet sich in der selben Transaktion wie das ihn auslösende SQL Statement.


Data Dictionary View: User_triggers …Trigger Info

Trigger Löschen:

DROP TRIGGER t_name

Ändern

ALTER TRIGGER t_name {DISABLE | ENABLE};


Reihenfolge der Triggerabfeuerung

Auslösendes Ereignis: DML – Statement

1.                  before Statement trigger

2.                  Für jede betroffene Reihe
a) before row trigger
b) DML – Statement
c) after row trigger

3.                  After statement trigger


Die Reihenfolge von Triggern des selben Typs ist nicht definiert.


Verwendung von: old und; new in rowlevel triggern

: old,:new sind Pseudorecords des Types table_name%Rowtype

Zugriff auf Elemente erfolgt :old.element

My_rec:=:old à Error


:old

:new

Insert

Undefiniert, alle Elemente NULL

Neue Werte

Update

Alte Werte

Neue Werte

Delete

Alte Werte

Undefiniert NULL

Personen(P_nr,Name,Gehaltst)

INSERT INTO Personen(Name,Gehaltst)

VALUES(‚Maier-Eva‛,1);

P_nr soll ein Trigger ermitteln !


CREATE OR REPLACE TRIGGER create_pnr

BEFORE INSERT ON Personen

FOR EACH ROW

BEGIN

SELECT max(P_nr)+1 INTO :new.p_nr FROM Personen

END create_pnr


New wird nur im Before Row Level Trigger verändert, Old wird nie verändert

New und old können nicht in Statement Level Triggern verwendet werden.


WHEN – Klausel


WHEN condition

Trigger body wird nur für die Reihen durchlaufen, auf die die Bedingung zutrifft.


FOR EACH ROW

WHEN(new.p_nr -> 100)


INSERTING, UPDATING, DELETING


Create Trigger . . . .

Before Insert or Update or Delte in

BEGIN

IF INSERTING THEN

ELSE IF UPDATING

.

END IF;

END .;


Mutating Tables


Es gibt Einschränkungen beim Zugriff auf Tabellen und Spalten.

Mutating, constraining tables

Mutating table: Tabelle die gerade durch ein DDL Statement bearbeitet wird. In Bezug auf einen Trigger ist es die Tabelle für die er definiert wurde. Mutating tables können auch constraint tables sein, die infolge eines Delete Cascade verändert werden.

Constraint Tabel: Eine Tabelle die aufgrund referentiel Integrity constraints gelesen oder verändert wird. Bsp. Create Table Personal(

P_nr NUMBER,

Name VARCHAR2(20),

Anr NUMBer

Foreign Key (Abt_nr) references abteilung(Abt_nr));

Regeln: SQL Statements im Triggerbody dürfen nicht mutating Tables lesen oder

verändern

Primary Key unique oder foreign Key Columes von constraint tables lesen

oder verändern.

Diese Regeln gelten nur für ROW Level Trigger.

INSERT INTO table_name SELECT …

Betrachtet triggering table immer als mutating

INSERT INTO table_name VALUES (…)

Before row trigger

pnr Abtnr

name PERSONAL ABTEILUNG abez

abtnr maxmitar


INSERT INTO Personal values(100,‛Franz‛,5)

Trigger der aktuelle Mitarbeiteranzahl ermittelt.

Für dieses insert ist personal nicht mutating

Insert into personal select * from mitarbeiterneu

Oder

Update personal set Abteilungsnummer=5 where p_nr=100;

Personal ist mutating


Aufgabe:

Eine Person einer anderen Abteilung zuordnen

Personal ist mutating nur für row-level trigger


Lösung:

1 before row level trigger

Schreibt die neue Abteilungsnummer in ein Package.

:new.abtnr wird über Package dem statement level trigger übergebe;

notwendig, da nur row level trigger auf :new Zugriff hat

Ermittelt, ob noch Platz in der neuen Abteilung ist.


Package: zur Speicherung von Globalen Daten


Header.

CREATE [OR REPLACE] PACKAGE packagename

AS

Procedure specification

Function spec

Table declaration

Type declaration

Exception dec

Cursor dec

END package

Packagebody


CREATE [OR REPLACE] PACKAGE BODY

Packagename AS

PROCEDURE…

BEGIN

END

FUNCTION

BEGIN

END

END packagename


Bsp.:

CREATE OR REPLACE PACKAGE trigger_buffer AS

Ab_nr_new personal.abt_nr%TYPE

END trigger_buffer;

CREATE OR REPLACE TRIGGER save_new_Abt_nr

BEFORE UPDATE OF abt_nr ON personal

FOR EACH ROW

BEGIN

Trigger_buffer.abt_nr_new:= :new.abt_nr;

END save_new_Abt_nr;

CREATE OR REPLACE TRIGGER check_count

AFTER UPDATE OF abt_nr ON personal

DECLARE

Actual_Count NUMBER;

Max_count NUMBER;

New_Abt personal.abt_nr%TYPE

BEGIN

New_Abt:=trigger_buffer.abt_nr_new;

SELECT count(*) INTO act_count FROM

Personal WHERE abt_nr=new_abt;

SELECT max_mit_anzahl INTO max_count FROM

Abteilung where abt_nr=new_Abt;

IF act_count + 1 > max_count THEN

RAISE_APPLICATION_ERROR(20000,“Maximale Mitarbeiteranzahl überschritten

in Abteilung“||new_Abt);

END IF;

END check_count;


Mass Insert und Packages


Tabellen


Typendefinition:

Type table-type Is Table of Type

Indexed by Binary-Integer

Variablendefinition:

Var_Name table_type

Zugriff:

Var_Name (Indexed)

Tabellen haben unbeschränkte Länge

Ein Element existiert erst, wenn ein Wert zugewiesen wurde.


Key

Value

0

Harald

-7

Otto

1000

Susi

Tab(1000):=‛Susi‛


Type name_tab is table of varchar2(20) indexed by Binary_Integer;

Namen namen-tab;

Idx Binary_Integer

Begin

Idx:=100;

Namen(idx):=my_name; -- Element mit Key 100 und Wert my_name erzeugt.

END;


%TYPE, %ROWTYPE können als Typ verwendet werden.

TYPE t_rec_person is table of person%ROWTYPE

Indexed by Binary_Integer

Personen_tab t_Rec_person;

SELECT * INTO personen_tab(idx) FROM personen where …


Personen_tab(idx).nach_name:=NULL;


Tabellenattribute


COUNT … aktuelle Anzahl der Tab_Elemente

Liefert NUMBER

Anzahl NUMBER;

Anzahl:=personen_tab.count

EXIST(i)…TRUE, wenn ein Element mit Key i existiert

If person_tab.EXIST(100) then


FIRST, LAST liefert Index des 1 und letzten Tab-El

NEXT, PRIOR nächsten und vorigen Index


DELETE löscht Tab Element

Personen_tab.DELETE,… löscht alle Elemente

Personen.tab.DELETE(1)… löscht Element mit Index 1

Personen.tab.DELETE(5,10)…löscht 5 bis 10


SQL%NOTFOUND

SQL%FOUND


BSP: Mass Insert in Mutating Table mit Trigger


Personal > Mitarbeiter


INSERT INTO personal Select * FROM neue_mitarbeiter


Table ist mutating, trigger before insert


CREATE package buffer

TABLE t_pers_tab is TABLE OF personal%ROWTYPE

INDEXED by Binary_Integer

pers_tab t_pers_tab;

act_count Binary_Integer:=0;

END buffer;


Before Row Trigger für insert into personal :


Buffer.pers_tab(act_count).personal_nr:= :new.p_nr;

Buffer.pers_tab(act_count).personal_name:= :new.p_name;

Buffer.pers_tab(act_count).personal_abtnr:= :new.p_abtnr;

Act_count:=act_count+1;


After Statement Trigger für insert into personal


FOR i in 0 buffer.act_count-1 LOOP

Select count(*) INTO c From personal

where abt_nr=buffer.pers_tab.(i);

RAISE APPLICATION ERROR

END LOOP;

Buffer.act_count:=0;


ENDE


M F C


Klassen

CmainFrame

CP View

CP Doc

CP Application

CP rc

CP About


Funktionen


Überladung

void f(int)

void f(int,int)


Vorgabewerte

void f(int i=0,int j=0)

f(10) à f(10,0);


Pointer auf Funktion

void (*p)(int,int)=f;

p(10,10);

(*p)(10,10);


Klassen à Objekte


Klassenvariablen Objektvariablen

Klassenmethoden Objektmethoden


static


class A{

int i;

int j;

public:

A();

~A();

void f();

};


class B:public A{

int k,l;

public:

B():A();

~B();

};

A a;

B b;

class B: private A { //Schutzstufen von A werden privat

int k,l;

public:

void g(){ f();}

}


Konvertierung Basisklasse- Subklasse


Class a{

Int i;

}

class B:public A{

int j;

};

A a;

B b;

a=b; à Info-Verlust;

b=a; NEIN Info fehlt

B::operator=(A&);


B b;

A *pa=&b; //Zeiger wird automatisch in Zeiger auf abgeleitete Klasse umgewandelt.


Virtuelle Funktionen


Anwendungen

1.)

class A {

Protected:

Int i;

Void f(){g();}

virtual void g(){ cout << i;};

}

class B:public A{

int j;

public:

void g(){cout << i << j;}

};

2.)

class A{

protected:

virtual void f(){cout << i;} // =0 Klassen müssen diese Funktion haben

};

class B:public A{

int j;

public:

void f(){cout << i <<j;}

};

B b;

A *pa=&b

Paà f(); à mit virtual f aus B

Anwendung

Array von Pointern auf Objekte aus verschiedenen vererbten Klassen. Funktionsaufruf wird der richtigen Klasse zugeordnet !!

Pointer auf Sandler

Pointer auf Student


Beide haben eine print Funktion, aber nicht die selbe.

P[0].print() findet die richtige Print Funktion für den Sandler.


LATE BINDING

Class A{

Int a1,a2;

Public:

Void f();

Void g();

Void h();

};

class B:public A{

int b1,b2;

public:

void g();

};

class C:public B{

int c1;

public:

void h();

};

Objekte ohne virtual Objekte mit virtual


A A

A1 A1

A2 A2

B B

A1 A1

A2 A2

B1 vft_ptr à vft virtual functionpointer

B2 B1 A::f table

C B2 B::g

A1 A::h

A2 C

B1 A1

B2 A2

C1 vft_ptr à vft

B1 A::f

B2 B::g

C1 C::h


Microsoft Foundation Classes


MFC – Klassenbibliothek

Vereinfachte Hülle für WIN32 API

Menge von high-level-Abstraktionen (OLE,DAO,…)

Große Auswahl von Quellcode

Hauptkategorien von MFC Klassen: von CObject abgeleitet

·        Application Architecture

·        Windows – Support
FrameWindows
Dialog Boxes
Views
Controls

·        Exceptions

·        File Services

·        Grafik Objects

·        Collections

·        Klassem für ODBC,DAO,Sockets,…


Nicht von Cobject abgeleitete Klassen

Simple Value Type: Cpoint,Crect, Cstring,…

OLE

Typed Template Collections


MFC-Application

1.)               SDI Single Document I

2.)               MDI Multiple Document I

3.)               Dialog Based


Klassen, die vom Application Wizzard erzeugt werden.

CmainFrame 1 )2 )3 ) in MainFrame.h MainFrame.cpp

CChildFrame 2) ChildFrame.h ChildFrame.cpp

Cxx App 1 )2 )3 ) in xx.h xx.cpp

Cxx Doc 1 )2 ) int xxDoc.h xxDoc.cpp

Cxx View 1 )2 ) „ View.h View.cpp

CxxDlg 3 ) „ „

CaboutDlg 1 )2 )3) „ „


Applikation

Projekt erstellen: Initialisierungen werden vorgenommen, die in InitInstance() wieder auftauchen. Je nach Projekttyp werden die oben genannten Klassen erzeugt.

Applications Klasse: CxxApp

Ein Objekt dieser Klasse ist schon ablauffähig.

CxxApp ist von CwinApp abgeleitet.

In xx.h deklariert.

In xx.cpp implementiert.

Element Funktionen: InitInstance()

CappAbout()

1 Applikationsobjekt


Cxx myApp; //Global

Wird vor AfxWinMain() erzeugt


AfxWinMain()

Ruft auf Init Application()

Init Instance

Run(); à Haupnachrichtenschleife der Applikation

(DispatchMessage())


Nachrichtenzuordnung


z.B. Message WM_LBUTTONDOWN

wird an den Anwendungsrahmen geschickt

à OnLButtonDown() wird ausgeführt.

Virtuelle Funktionen kommen als Nachrichtenbearbeiter nicht in Frage.

Nachrichtenbearbeiter können beliebige Namen haben (OnConnect) die die

Übergeordnete Klasse nicht kennt.

Virtual function pointer table wird riesig.

Lösung über Makros

In .h: DECLARE_MESSAGE_MAP();

Deklariert ein Array von Nachrichtentabelleneinträgen.

In .cpp BEGIN_MESSAGE_MAP

END_MESSAGE_MAP

Enthalten Initialisierungen für dieses Array, die individuelle Nachrichten repräsentieren, auf die die Klasse reagieren kann.


Passende Nachrichtenbearbeiter werden in der Reihenfolge gesucht:

SDI

MDI

VIEW

View

Doc

Doc

SDI-MainFrame

MDI-Childframe

Applikation

MDI-MainFrame


Applikation

Document – View – Architecture


Trennung von Daten und deren Darstellung.

Vorteile: Unterschiedliche Darstellung der Daten, Tabellen, Diagramme.

Doc-Object enthält die Daten

View-Object zeigt die Daten und erlaubt das Editieren


SDI Anwendung

Besitzt eine von Cdocument abgeleitete Doc-Klasse, und 1 oder mehrere von Cview abgeleitete Cview-Klassen.

CObject

CCmdTarge

CDocument

CMyDoc



Title Bar

Menu Bar

Tool Bar


Formular

Ressource Controls


Status Bar


CxxView-Object


ClistBox myLB;

Cstring myStrname;


CxxDoc Object


Daten


Inhalt einer Datei


3 Klassen: CmainFrame

CxxView

CxxDoc


Deklaration und Implementierung

CmainFrame:public CframeWnd

In Mainframe.h deklariertCon

Elementvariablen:

m_wndStatusBar

m_wndToolBar

Elementfunktionen: in .cpp

OnCreate( )…erzeugt ToolBar und StatusBar

CxxDoc::public Cdocument

Wichtige Memberfunktionen

DeleteContens()

OnNewDocument()

OnSaveDocument()

Serialze()

Aufrufreihenfolge

Bei Start der SDI Anwendung

1.                  DeleteContens()

2.                  OnNewDocument()

Bei Auswahl der Menuepunktes „New“

1.                  DeleteContens

2.                  OnNewDocument

Bei Speichern, Speichern als, öffnen

1.                  OnSaveDocument

2.                  Serialize


Weitere Funktionen

SetModifiedFlag()

IsModified()

UpdatAllViews() à kann auch am Views Objekt aufgerufen werden

GetDocument()->UpdateAllViews(this); //aktuelles Objekt;


CxxView:: CformView

CrecordView

Cview

ClistView

CeditView

Wichtige Memberfunktionen

GetDocument()…liefert Pointer aufs Dokument

OnInitialUpdate( )

Bei Start der SDI- Anwendung und bei „Neu“ u. „Öffnen“

Achtung: Cview::OnInitialUpdate() muß auch aufgerufen werden

CformView::

OnUpdate( )

Wird von OnInitialUpdate () oder von UpdateAllViews() aufgerufen

Übertragung der Doc-Daten in die Steuerelemente und umgekehrt.


Dialog-Ressource View – Object Zuordnung mit classWizzard


Name Cstring m_strName;

Hello World

Edit Steuerelement über Memberfunktionen

IDC-Name GetDocument()->GetName

Doc Object GetDocument()->SetName

Cstring m_strName_aus_Tab

UpdateData()


ODBC oder Serialize


OnUpdate( )

{

m_strName=GetDocument()àGetName();

UpdateData(FALSE); à neuer Name erscheint im Edit Feld;

}

in .h

//{{AFX_DATA(CxxView)

enum{IDD=IDDxxFORM};

Cstring m_srtName;

//}}AFX_DATA


virtual void DoDataExchange(CDataExchange *pDx);


in .cpp

Constructor:

CxxView::CxxView():CformView(CxxView::IDD)

//{{AFX_DATA_INIT(CxxView)

m_strName = _T(„“);

//}}AFX_DATA_INIT


void CxxView::DoDataExchange(… *)

{

CformView::DoDataExchange(pDx);

//{{ AFX_DATA_MAP (CxxView)

DDX_Text(pDX,IDC_NAME,m_strName)

//}} AFX_DATA_MAP

}


OnDblclkBehandlungen( )

{

ClistBox *plB=

pLBà GetTExt(pLBà GetCurSel( ), m_pSelectData);

Cod01Dlg myDlg(this);

if (myDlg.DoModal()==IDOK)

{ //Daten des Dialoges in Doc übertragen

und ODBC Funktion aufrufen

GetDocument()à StoreData();

}


ODBC und MFC Klassen


Cdatabase

Crecordset


Doc


Cdatabase m_db

Recordset

m_pSet Data


Patienten


Behandlung

Verordnet


Leistung


RFX – Mechanismus


Void DoFieldExchange( CFieldExchange * pFX)

Void SetFieldType( UINT nFieldType)


Objekte à Container à Serialize


Collection-Klasse COb List


Collection, Container, Zusammenfassung von Objekten

à Arrays, Listen, Bäume, Menge…

CobList unterstützt sortierte Listen die Zeiger auf Objekte enthalten die von Cobjekt abgeleitet sind.


Cstudent *pStudent;

CobList myList;

PStudent = new Cstudent(10,“Maier“);

myList.AddTail(pStudent); // am Ende angehängt

While(!myList.IsEmpty())

{ pStudent=(cStudent*)myList.RemoveHead();

pStudent();

delete pStudent; //liefert Pointer aufs Objekt und gibt Knoten frei

} // Student Objekt muß explizit freigegeben werden


POSITION - Parameter

Aktuelle Position in der Liste


Void* GetNext(POSITION pos)

Liefert einen Pointer auf das Objekt das durch den Position Parameter identifiziert wird und positioniert weiter.


POSITION pos;

pos = myList.GetHeadPosition( )

while( pos )

{ pStudent = (Cstudent*)GetNext(pos);
pStudent->print();

}

void *GetAt(Position pos);

//liefert Pointer aufs Position Objekt

class CStudent:public CObject {

char *Name

int Nr
public:
CStudent(int n, char *p){…}

~CStudent();

print();

};


ListBoxen:


View::FillListe()

{

CPatientSet set(…)

Set.Open();

While(!set.IsEOF())

{

int item = m_PatientnListe.AddString(set.m_Name);

m_PatientenListe.setItemData(item,set.m_ID);

}


DBLClick:

{

int item=m_PatientenListe.GetCurSel();

int id=m_PatientenListe.GetItemData(item);

}


Template-bassierte Collection- Klasse


CtypedPtrList

CobList // Collection für gemischte Zeiger

CtypedPtrList // typsicherer Collection

z.B. Collection für Cstudent – zeiger

CtypedPtrList <CObList,CStudent*> m_StudentList;

1 Par: Basisklasse der Collection: CObList

CPtrList( à void*)

2 Parameter: Typ der Parameter und Rückgabewerte der Memberfunktion. (für Objekte die von Cobject abgel. Sind)

typdef CtypePtrList<CobList,Cstudent*>CstudentList;

CstudentList myStudentList;


Template <class Base_Class, class Type>

CtypedPtrList:Base_Class


Serialisierung


Speichern u. Laden von Objekten


Persistentes Objekt

Doc-Objekt


Serialize () Carchive-Objekt Cfile-Objekt


Wird vom Anwendungsrahmen

Bei Datei/öffnen – speichern aufgerufen


Es ist möglich eine direkte File E/A über Cfile durchzuführen:

CreateFile à FileHandle

ReadFile

WriteFile


Gepufferte File E/A über CArchive


Serialisierbare Klassen

Müssen von Cobject abgeleitet sein


Void Cstudent::Serialize(Carchive &ar)

{ if(ar.IsStoring())

ar<<m_strName<<m_nNumber;

else

ar >> m_strName >> m_nNumber;


Patienten geplante Behandlung


Termin für nächsten Tag Objekt x à CTypedPtrList

Vormittag: Elektro

Nachmittag:


Menüpunkt Init à Neu ; Laden, Speichern

Übernehmen à Wünsche in DB speichern TAB:xxx, Wunsch des Vortages
Übernehmen wenn kein Wunsch angegeben


ExecuteSQL(„begin proc() and…


Laufzeitklasseninformation


Runtime Class

RTTI

Makros:

DECLARE_DYNAMIC

IMPLEMENT_DYNAMIC notwendig wenn Laufzeittypinformation benötigt wird.

DECLARE_DYNCREATE

IMPLEMENT_DYNCREATE notwendig wenn neue Objekte angelegt werden


Class person:public Cobject

{ DECLARE_DYNCREATE(person)


}


IMPLEMENT_DYNCREATE (person, CObject)


If (pPerson -> IsKindOf(RUNTIME_CLASS(Person))

CruntimeClass *pRTC = RUNTIME_CLASS(person);

CObject* xyz = pRTC->CreateObject();



| | | | |
Tausche dein Hausarbeiten