Geschäftslogik in der Datenbank

Werbung
Geschäftslogik in der Datenbank
Architektur und Objektorientierte
PL/SQL-Programmierung
Andriy Terletskyy
Lead Database Architect
Hamburg, 17.06.2010
Geschäftslogik
Geschäftslogik (engl. Business Logic, auch Anwendungslogik) ist
ein abstrakter Begriff in der Softwaretechnik, der eine Abgrenzung der
durch die Aufgabenstellung selbst motivierten Logik eines
Softwaresystems von der technischen Implementierung zum Ziel hat.
Allerdings ist der Begriff unscharf, da eine klare Trennung oft nicht
möglich ist.
• Mehrfache BL-Umsetzung
• Datenbank Abhängigkeit
• Datenverarbeitungs- und
Datenerfassungslogik
Java
FAT-Client
ASP.NET
• Oracle EE ist mehr als eine
Datenbank (Speicherort)
• SQL und PL/SQL Engine
• DBMS-Packages
• Object Types
Cobol
Daten-Import
Datenbank
2
12.06.2012
Geschäftslogik in der Datenbank
• Type Mapping (Java&.NET)
• JPublisher, SQLData,
STRUCT, ODP.NET
Datenbanken Architektur
Makler
FIX
SWIFT
E-Börsen
Data-Warehouse
Handelssystem
Log
log
Log
Log
Log
Log
Transaktionen
Bestandstamm
Log
Ausführung
GattungStamm
KundenStamm
GattungStamm
Log
Bestandstamm
Order
KundenStamm
Transaktionen
Ausführung
Abrechnung
Buchung
Order
Back-Office
Portfolio
Transaktionen
Bestandstamm
GattungStamm
KundenStamm
(Data-HUBs)
Abrechnung
Aufrührung
Reporting
Bestandstamm
Order
Buchung
Buchung
GattungStamm
KundenStamm
3
12.06.2012
Geschäftslogik in der Datenbank
Virtuelle ODBMS auf Basis RDBMS (DOAG Konferenz 2004)
BO-TYPES
OO-ROWTYPES
RDBMS
4
12.06.2012
Geschäftslogik in der Datenbank
Aufbau
• OO-ROWTYPE (ROWTYPE + DML, DEFAULT,
TO_STRING, DBMS_OUTPUT- Methoden, PK/UKKonstruktoren, ROW_LOCK)
• BO-Typen (Vererbung, Aggregation, Assoziation)
Verwendung
• Methoden statt üblicher DML- Anweisungen
• Datennormalisierung über RDBMS
• PK/UK- Konstruktoren - ziehen referenziertes
Objekt über relationale ID (DEREF- Analogon)
Generator
• Java-Class
• PL/SQL-Wrapper
• DDL-Trigger mit asynchroner Queue
Tabelle und OO-Rowtype (Beispiel)
CREATE OR REPLACE TYPE ROW_STATUS UNDER GLOBAL.TYPE_OBJECT
( -- attributes
STATUS_ID
NUMBER(12)
, KURZBEZEICHNUNG
VARCHAR2(50)
, ERSTELLT_ZST
DATE
, ERSTELLT_ID
VARCHAR2(30)
, GEAENDERT_ZST
DATE
, GEAENDERT_ID
NUMBER(12)
, GEAENDERT_ZAEHLER NUMBER(10)
, BEZEICHNUNG
VARCHAR2(200)
CREATE OR REPLACE TRIGGER TBI$STATUS
BEFORE INSERT ON WPH.STATUS FOR EACH ROW
WHEN ( NEW.STATUS_ID IS NULL)
DECLARE
BEGIN
SELECT STATUS_SEQ.NEXTVAL
INTO :NEW.STATUS_ID
FROM DUAL;
END;
--------------------------------------------------------------------------------------------
CREATE OR REPLACE TRIGGER TBU$STATUS
BEFORE UPDATE ON WPH.STATUS FOR EACH ROW
BEGIN
:new.Geaendert_ID
:= SYS_CONTEXT('VPD', 'USERID');
:new.Geaendert_ZST
:= sysdate;
:new.Geaendert_Zaehler := :old.Geaendert_Zaehler + 1;
end;
5
12.06.2012
Geschäftslogik in der Datenbank
-- constructors
, CONSTRUCTOR FUNCTION ROW_STATUS RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION ROW_STATUS(IN_STATUS_ID NUMBER)
RETURN SELF AS RESULT
-- member functions
, MEMBER FUNCTION ROW_EXISTS(IN_STATUS_ID NUMBER) RETURN BOOLEAN
, OVERRIDING MEMBER FUNCTION compare(in_type1 GLOBAL.TYPE_OBJECT
,in_type2 GLOBAL.TYPE_OBJECT)
RETURN INTEGER
-- member procedures
, MEMBER PROCEDURE ROW_INSERT
, MEMBER PROCEDURE ROW_UPDATE
, MEMBER PROCEDURE ROW_MERGE
, MEMBER PROCEDURE ROW_SAVE
, MEMBER PROCEDURE ROW_DELETE
, MEMBER PROCEDURE ROW_SELECT(IN_STATUS_ID NUMBER)
, MEMBER PROCEDURE ROW_DEFAULT
, MEMBER PROCEDURE ROW_LOCK
, MEMBER PROCEDURE ROW_LOCK(IN_STATUS_ID NUMBER)
) NOT FINAL
RETURNING clause (INSERT und UPDATE)
MEMBER PROCEDURE ROW_INSERT
IS
methodenname CONSTANT VARCHAR2(100) := 'WPH.ROW_STATUS.ROW_INSERT';
BEGIN
IF SYS_CONTEXT('TRACE','TRACE_LEVEL') >= GLOBAL.PA_TRACE.TRACE_TRACE THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_TRACE, methodenname, 'Parameters: ');
END IF;
INSERT INTO WPH.STATUS ( STATUS_ID
,KURZBEZEICHNUNG
,BEZEICHNUNG
) VALUES ( SELF.STATUS_ID
,SELF.KURZBEZEICHNUNG
,SELF.BEZEICHNUNG
) RETURNING
STATUS_ID
,KURZBEZEICHNUNG
,ERSTELLT_ZST
,ERSTELLT_ID
,GEAENDERT_ZST
,GEAENDERT_ID
,GEAENDERT_ZAEHLER
,BEZEICHNUNG
INTO
SELF.STATUS_ID
,SELF.KURZBEZEICHNUNG
,SELF.ERSTELLT_ZST
,SELF.ERSTELLT_ID
,SELF.GEAENDERT_ZST
,SELF.GEAENDERT_ID
,SELF.GEAENDERT_ZAEHLER
,SELF.BEZEICHNUNG
;
EXCEPTION
WHEN OTHERS THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_ERROR, methodenname, ' - Exception raised. '
||SELF.TO_STRING()
||', SQLcode=' || to_char(SQLCODE) || ', ' || SQLERRM);
RAISE;
END;
6
12.06.2012
Geschäftslogik in der Datenbank
SAVE und MERGE
MEMBER PROCEDURE ROW_SAVE
IS
methodenname CONSTANT VARCHAR2(100) := 'WPH.ROW_STATUS.ROW_SAVE';
BEGIN
IF SYS_CONTEXT('TRACE','TRACE_LEVEL') >= GLOBAL.PA_TRACE.TRACE_TRACE THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_TRACE, methodenname, 'Parameters: ');
END IF;
IF ROW_EXISTS(IN_STATUS_ID => SELF.STATUS_ID) THEN
SELF.ROW_UPDATE;
ELSE
SELF.ROW_INSERT;
END IF;
EXCEPTION
WHEN OTHERS THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_ERROR, methodenname, ' - Exception raised. '
||SELF.TO_STRING()
||', SQLcode=' || to_char(SQLCODE) || ', ' || SQLERRM);
RAISE;
END;
---------------------------------------------------------------
MEMBER PROCEDURE ROW_MERGE
IS
methodenname CONSTANT VARCHAR2(100) := 'WPH.ROW_STATUS.ROW_MERGE';
BEGIN
IF SYS_CONTEXT('TRACE','TRACE_LEVEL') >= GLOBAL.PA_TRACE.TRACE_TRACE THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_TRACE, methodenname, 'Parameters: ');
END IF;
MERGE INTO WPH.STATUS A
USING ( SELECT SELF.STATUS_ID AS STATUS_ID
,SELF.KURZBEZEICHNUNG AS KURZBEZEICHNUNG
,SELF.BEZEICHNUNG
AS BEZEICHNUNG
FROM DUAL ) B
ON (A.STATUS_ID
= B.STATUS_ID)
WHEN MATCHED THEN UPDATE SET KURZBEZEICHNUNG = B.KURZBEZEICHNUNG
,BEZEICHNUNG
= B.BEZEICHNUNG
WHEN NOT MATCHED THEN INSERT ( STATUS_ID
,KURZBEZEICHNUNG
,BEZEICHNUNG
) VALUES ( B.STATUS_ID
,B.KURZBEZEICHNUNG
,B.BEZEICHNUNG
);
EXCEPTION
WHEN OTHERS THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_ERROR, methodenname, ' - Exception raised. '
||SELF.TO_STRING()
||', SQLcode=' || to_char(SQLCODE) || ', ' || SQLERRM);
RAISE;
END;
7
12.06.2012
Geschäftslogik in der Datenbank
Pessimistisches Locking - Default
MEMBER PROCEDURE ROW_LOCK
IS
methodenname CONSTANT VARCHAR2(100) := 'WPH.ROW_STATUS.ROW_LOCK';
v_lock
NUMBER;
BEGIN
IF SYS_CONTEXT('TRACE','TRACE_LEVEL') >= GLOBAL.PA_TRACE.TRACE_TRACE THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_TRACE, methodenname, 'Parameters: ');
END IF;
SELECT GEAENDERT_ZAEHLER
INTO v_lock
FROM WPH.STATUS
WHERE STATUS_ID
= SELF.STATUS_ID
FOR UPDATE
;
IF SELF.GEAENDERT_ZAEHLER <> v_lock THEN
SELF.ROW_SELECT( IN_STATUS_ID
=> SELF.STATUS_ID);
END IF;
EXCEPTION
WHEN OTHERS THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_ERROR, methodenname, ' - Exception raised. '
||SELF.TO_STRING()
||', SQLcode=' || to_char(SQLCODE) || ', ' || SQLERRM);
RAISE;
END;
declare
i ROW_STATUS;
begin
i := ROW_STATUS(IN_STATUS_ID => 200);
...
i.ROW_LOCK();
end;
8
12.06.2012
Geschäftslogik in der Datenbank
Pessimistisches Locking mit PK oder UK
MEMBER PROCEDURE ROW_LOCK(IN_STATUS_ID NUMBER)
IS
methodenname CONSTANT VARCHAR2(300) := 'WPH.ROW_STATUS.ROW_LOCK(IN_STATUS_ID NUMBER)';
BEGIN
IF SYS_CONTEXT('TRACE','TRACE_LEVEL') >= GLOBAL.PA_TRACE.TRACE_TRACE THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_TRACE, methodenname, 'Parameters: '
||'IN_STATUS_ID = '||IN_STATUS_ID||';'
);
END IF;
SELECT STATUS_ID
,KURZBEZEICHNUNG
,ERSTELLT_ZST
declare
,ERSTELLT_ID
i ROW_STATUS;
,GEAENDERT_ZST
,GEAENDERT_ID
begin
,GEAENDERT_ZAEHLER
,BEZEICHNUNG
i := ROW_STATUS();
INTO SELF.STATUS_ID
,SELF.KURZBEZEICHNUNG
i.ROW_LOCK(IN_STATUS_ID
,SELF.ERSTELLT_ZST
,SELF.ERSTELLT_ID
end;
,SELF.GEAENDERT_ZST
,SELF.GEAENDERT_ID
,SELF.GEAENDERT_ZAEHLER
,SELF.BEZEICHNUNG
FROM WPH.STATUS
WHERE STATUS_ID = IN_STATUS_ID
FOR UPDATE
;
EXCEPTION
WHEN OTHERS THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_ERROR, methodenname, ' - Exception raised. '
||'IN_STATUS_ID = '||IN_STATUS_ID||';'
||', SQLcode=' || to_char(SQLCODE) || ', ' || SQLERRM);
RAISE;
END;
9
12.06.2012
Geschäftslogik in der Datenbank
=> 200);
Optimistisches Locking - UPDATE
MEMBER PROCEDURE ROW_UPDATE
IS
methodenname CONSTANT VARCHAR2(100) := 'WPH.ROW_STATUS.ROW_UPDATE';
BEGIN
IF SYS_CONTEXT('TRACE','TRACE_LEVEL') >= GLOBAL.PA_TRACE.TRACE_TRACE THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_TRACE, methodenname, 'Parameters: ');
END IF;
UPDATE WPH.STATUS
SET KURZBEZEICHNUNG = SELF.KURZBEZEICHNUNG
,BEZEICHNUNG
= SELF.BEZEICHNUNG
WHERE STATUS_ID
= SELF.STATUS_ID
AND GEAENDERT_ZAEHLER = SELF.GEAENDERT_ZAEHLER
RETURNING STATUS_ID
,KURZBEZEICHNUNG
,ERSTELLT_ZST
,ERSTELLT_ID
,GEAENDERT_ZST
,GEAENDERT_ID
,GEAENDERT_ZAEHLER
,BEZEICHNUNG
INTO SELF.STATUS_ID
,SELF.KURZBEZEICHNUNG
,SELF.ERSTELLT_ZST
,SELF.ERSTELLT_ID
,SELF.GEAENDERT_ZST
,SELF.GEAENDERT_ID
,SELF.GEAENDERT_ZAEHLER
,SELF.BEZEICHNUNG
;
IF SQL%ROWCOUNT <> 1 THEN
GLOBAL.RAISE(-20999);
END IF;
-- Der Datensatz hat sich zwischenzeitlich geändert
EXCEPTION
WHEN OTHERS THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_ERROR, methodenname, ' - Exception raised. '
||SELF.TO_STRING()
||', SQLcode=' || to_char(SQLCODE) || ', ' || SQLERRM);
RAISE;
END;
10
12.06.2012
Geschäftslogik in der Datenbank
Optimistisches Locking - DELETE
MEMBER PROCEDURE ROW_DELETE
IS
methodenname CONSTANT VARCHAR2(100) := 'WPH.ROW_STATUS.ROW_DELELE';
BEGIN
IF SYS_CONTEXT('TRACE','TRACE_LEVEL') >= GLOBAL.PA_TRACE.TRACE_TRACE THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_TRACE, methodenname, 'Parameters: ');
END IF;
DELETE FROM WPH.STATUS
WHERE STATUS_ID
= SELF.STATUS_ID
AND GEAENDERT_ZAEHLER = SELF.GEAENDERT_ZAEHLER;
IF SQL%ROWCOUNT <> 1 THEN
GLOBAL.RAISE(-20999);
END IF;
-- Der Datensatz hat sich zwischenzeitlich geändert
EXCEPTION
WHEN OTHERS THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_ERROR, methodenname, ' - Exception raised. '
||SELF.TO_STRING()
||', SQLcode=' || to_char(SQLCODE) || ', ' || SQLERRM);
RAISE;
END;
11
12.06.2012
Geschäftslogik in der Datenbank
Variablen und OO-ROWTYPE
declare
s VARCHAR2(50);
begin
SELECT s.kurzbezeichnung
INTO s
FROM WPH.STATUS s
WHERE s.sTATUS_ID=200;
end;
declare
s WPH.STATUS%ROWTYPE;
begin
SELECT *
INTO s
FROM WPH.STATUS s
WHERE s.sTATUS_ID=200;
end;
12
12.06.2012
Geschäftslogik in der Datenbank
declare
s WPH.STATUS.KURZBEZEICHNUNG%TYPE;
begin
SELECT s.kurzbezeichnung
INTO s
FROM WPH.STATUS s
WHERE s.STATUS_ID=200;
end;
declare
s WPH.ROW_STATUS;
begin
s := WPH.ROW_STATUS(IN_STATUS_ID => 200);
end;
Arbeiten mit OO-ROWTYPE
declare
i ROW_STATUS;
begin
i := ROW_STATUS(IN_STATUS_ID => 200);
i.DBMS_OUTPUT;
i.KURZBEZEICHNUNG := 'Eingestellt';
i.ROW_UPDATE;
i.DBMS_OUTPUT;
end;
<ROW_STATUS>
<OBJECT_TYPE_NAME>WPH.ROW_STATUS</OBJECT_TYPE_NAME>
<STATUS_ID>200</STATUS_ID>
<KURZBEZEICHNUNG>Einstellung</KURZBEZEICHNUNG>
<ERSTELLT_ZST>12.07.02</ERSTELLT_ZST>
<ERSTELLT_ID>-2</ERSTELLT_ID>
<GEAENDERT_ZST>14.08.04</GEAENDERT_ZST>
<GEAENDERT_ID>1469</GEAENDERT_ID>
<GEAENDERT_ZAEHLER>2</GEAENDERT_ZAEHLER>
<BEZEICHNUNG>ORDERAUSFUEHRUNG-STATUS</BEZEICHNUNG>
</ROW_STATUS>
<ROW_STATUS>
<OBJECT_TYPE_NAME>WPH.ROW_STATUS</OBJECT_TYPE_NAME>
<STATUS_ID>200</STATUS_ID>
<KURZBEZEICHNUNG>Eingestellt</KURZBEZEICHNUNG>
<ERSTELLT_ZST>12.07.02</ERSTELLT_ZST>
<ERSTELLT_ID>-2</ERSTELLT_ID>
<GEAENDERT_ZST>15.06.10</GEAENDERT_ZST>
<GEAENDERT_ID>907</GEAENDERT_ID>
<GEAENDERT_ZAEHLER>3</GEAENDERT_ZAEHLER>
<BEZEICHNUNG>ORDERAUSFUEHRUNG-STATUS</BEZEICHNUNG>
</ROW_STATUS>
13
12.06.2012
Geschäftslogik in der Datenbank
Gattungsstamm – Input Daten
G
DE000AAR0082AAR0081900000640329 00"GD090 09062010"GD100 01"GD100A 1"GD160 004"GD161 DE"GD170 EO
"GD171 EUR"GD172 EUR"GD190 PD"GD195 227"GD196 1"GD198A SEC"GD198B 2000"GD198C 2003"GD198D ZZZZ"GD198E ZZZZ"GD198F
E302"GD198G M401"GD200 00025"GD201 DE03472
"GD205B KA05"GD211 1"GD212 703"GD213 25"GD214 22"GD215A
J"GD217 AAC"GD218 J"GD218A J"GD218B J"GD218C J"GD220 142"GD220A 004"GD220C
183"GD225 A"GD226 60"GD227 1"GD228 0413"GD230 MTH"GD234 1"GD240 804110"GD260 AAREAL BANK MTN.HPF.S.67 "GD270A Aareal
Bank AG
"GD270B MTN-HPF.S.67 v.2010(2013) "GD280A Serie 67 v. 2010 (2013)
"GD290 16092010"GD290A
16092010"GD300 16092013"GD312 6"GD321 10"GD322 16062010"GD323 15092013"GD388A
686665"GD388PIDE0006866650"GD400 03"GD410 9"GD420 7"GD423 J"GD424 B"GD430 099"GD440 2"GD455A 000001000000000000"GD455E
1"GD473 ²NOM=1000,W=EUR;
"GD481A 05"GD483 1"GD500 84"GD504A J"GD505B 25000000000"GD505E
2"GD507 0550000"GD545 1"GD545A 2"GD546 09062010"GD571 J"GD572 J"GD621 099"GD622 DE000AAR0082"GD622PWAAR008"GD630A
000000500000000000"GD630B EUR"GD650A 000000500000000000"GD660 16062010"GD663A N"GD663D N"GD669 0000997590000"GD670A
EUR"GD670B %"GD672 1"GD685 DTFSFB"GD697 2B"GD776 3"GD801A 0001750000000"GD805 F"GD810 093"GD811 1"GD812 16"GD812A
16"GD813 SEPT"GD813A SEPT"GD815 0092"GD815A 0044109589"GD819 2"GD821B 09"GD822 01"GD841 2"GD861A
000000100000000000"GD862 16092013"GD910 16092013"GD924 N"GD970G 01"GD986 ²deutsches Recht
G
DE000AAR0082AAR0081909920640329 00"GV992 ²0660/J/ / / / / / / / / / / / /
²0348/J/ / / / / / / / / / / / /
²2597/J/ / / / / / / / / / / / /
G
DE000AAR0082AAR0081909950640329 00"GV995 ²0660/ / / / / / / / / /J/ / / /
²0348/ / / / / / / / / / /J/ / /
²2597/ / / / / / / / / / /J/ / /
E
NO00030753019065612010060932000 00"ED001 2"ED002A 1"ED004A DD"ED023 1"ED024A 01012009"ED025A 31122009"ED190 02
G
NO00030753019065611910000603643 00"GD090 29062010"GD260 PETROLIA DRILLING
Navne-Aksjer NK 5
"GD460A 000000005000000000
NK 5"GD270A Petrolia Drilling ASA
"GD270B
H
NO00030753019065612010032905600200"HD008 28062010"HD015 1300
U
NO00030753019065612010060940500 00"UD001 1"UD002A 1"UD005 1"UD006 1"UD007 4"UD008A AZ"UD010A ST "UD010C
0000010000000"UD010D 0000000100000000"UD011A ST "UD011C 0000100000000"UD011D
0000000010000000"UD021 906561"UD021PINO0003075301"UD025 29062010²ca.
"UD034 28062010"UD078 20"UD087 049"U
D190 02"UD460A 000000000500000000"UD460B 000000005000000000
14
12.06.2012
Geschäftslogik in der Datenbank
Gattungsstamm – Datenbank Model
15
12.06.2012
Geschäftslogik in der Datenbank
Schwergewichtiger TYPE
CREATE OR REPLACE TYPE TYPE_GATTUNG AUTHID CURRENT_USER UNDER GLOBAL.TYPE_OBJECT
( -- Attributes
id
NUMBER(12)
, isin
CHAR(12)
, wkn
CHAR(6)
, sh
NUMBER(2)
, geloescht
DATE
, name
VARCHAR2(80)
, instrument
VARCHAR2(80)
, fids
WP.TABLE_WMFID
, ertraege
WP.TABLE_ERTRAG
, kapitals
WP.TABLE_KAPITAL
, ohc
WP.TABLE_GATTUNG_OHC
, hauptversammlung WP.TABLE_HAUPTVERSAMMLUNG
, bogenerneuerung WP.TABLE_BOGENERNEUERUNG
, umtausch
WP.TABLE_UMTAUSCH
, verlosung
WP.TABLE_VERLOSUNG
, termin
WP.TABLE_GATTUNG_TERMIN
, opposition
WP.TABLE_OPPOSITION
, ifp
WP.TABLE_WMFID
, NWKN
VARCHAR2(4000) -- Nationale WKN
-- Methods
, CONSTRUCTOR FUNCTION TYPE_GATTUNG RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION TYPE_GATTUNG(in_id NUMBER) RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION TYPE_GATTUNG(IN_ID NUMBER, IN_DATUM DATE) RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION TYPE_GATTUNG(in_isin VARCHAR2, in_sh NUMBER DEFAULT 0) RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION TYPE_GATTUNG(in_wkn VARCHAR2, in_sh NUMBER DEFAULT 0) RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION TYPE_GATTUNG(in_wkn VARCHAR2, in_sh NUMBER, in_datum DATE) RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION TYPE_GATTUNG(in_isin VARCHAR2, in_wkn VARCHAR2, in_sh NUMBER DEFAULT 0, in_geloescht DATE DEFAULT NULL) RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION TYPE_GATTUNG(in_isin VARCHAR2, in_wkn VARCHAR2, in_instrument VARCHAR2) RETURN SELF AS RESULT
, MEMBER PROCEDURE add_ertrag(in_ertrag WP.TYPE_ERTRAG)
, MEMBER PROCEDURE add_hauptversammlung(in_hauptversammlung WP.TYPE_HAUPTVERSAMMLUNG)
, MEMBER PROCEDURE add_bogenerneuerung(in_bogenerneuerung WP.TYPE_BOGENERNEUERUNG)
, MEMBER PROCEDURE add_kapital(in_kapital WP.TYPE_KAPITAL)
, MEMBER PROCEDURE add_umtausch(in_umtausch WP.TYPE_UMTAUSCH)
, MEMBER PROCEDURE add_verlosung(in_verlosung WP.TYPE_VERLOSUNG)
, MEMBER PROCEDURE add_ohc(in_ohc WP.TYPE_GATTUNG_OHC)
, MEMBER PROCEDURE add_termin(in_termin WP.TYPE_GATTUNG_TERMIN)
, MEMBER PROCEDURE add_opposition(in_opposition WP.TYPE_OPPOSITION)
, MEMBER PROCEDURE INIT_KAPITAL_DETAIL(SELF IN OUT TYPE_GATTUNG)
, MEMBER FUNCTION GET_KAPITAL_DETAIL(SELF IN OUT TYPE_GATTUNG) RETURN WP.TABLE_KAPITAL
, MEMBER PROCEDURE INIT_FID_DETAIL(SELF IN OUT TYPE_GATTUNG)
, MEMBER FUNCTION GET_FID_DETAIL(SELF IN OUT TYPE_GATTUNG) RETURN WP.TABLE_WMFID
, MEMBER PROCEDURE INIT_SCD_FIDS(IN_DATUM DATE DEFAULT NULL)
, MEMBER PROCEDURE INIT_OHC(IN_BOERSENPLATZ_ID VARCHAR2)
,…
) NOT FINAL
16
12.06.2012
Geschäftslogik in der Datenbank
Schwergewichtiger TYPE (Fortsetzung)
CREATE OR REPLACE TYPE TABLE_ERTRAG AS TABLE OF WP.TYPE_ERTRAG;
-----------------------------------------------------------------------------------------------------------------------CREATE OR REPLACE TYPE TYPE_ERTRAG UNDER WP.ROW_ERTRAG_BASE
( -- Attributes
id
NUMBER(12)
, fids
WP.TABLE_WMFID
-- Methods
, CONSTRUCTOR
, CONSTRUCTOR
, CONSTRUCTOR
RESULT
FUNCTION TYPE_ERTRAG RETURN SELF AS RESULT
FUNCTION TYPE_ERTRAG(in_wmdaten WP.TYPE_WMDATEN) RETURN SELF AS RESULT
FUNCTION TYPE_ERTRAG(OBJECT_TYPE_NAME VARCHAR2, ID NUMBER, BID_NR VARCHAR2, DATUM DATE, FIDS WP.TABLE_WMFID) RETURN SELF AS
, CONSTRUCTOR
, CONSTRUCTOR
FUNCTION TYPE_ERTRAG(BID_NR VARCHAR2, DATUM DATE, FIDs WP.TABLE_WMFID) RETURN SELF AS RESULT
FUNCTION TYPE_ERTRAG(in_BID_NR VARCHAR2, in_DATUM VARCHAR2, in_FIDs WP.TABLE_WMFID) RETURN SELF AS RESULT
, CONSTRUCTOR
FUNCTION TYPE_ERTRAG(IN_ERTRAG_BASE_ID NUMBER, IN_DATUM DATE DEFAULT NULL) RETURN SELF AS RESULT
, MEMBER
PROCEDURE INIT_SCD_FIDS(IN_DATUM DATE DEFAULT NULL)
, OVERRIDING MEMBER FUNCTION compare(in_type1 GLOBAL.TYPE_OBJECT, in_type2 GLOBAL.TYPE_OBJECT) RETURN INTEGER
, MEMBER
PROCEDURE getDBid(in_gattung_id NUMBER)
, MEMBER
PROCEDURE save(in_gattung_id NUMBER,IN_DATUM DATE DEFAULT SYSDATE)
, MEMBER
FUNCTION TO_VF1 RETURN GLOBAL.TABLE_VARCHAR2
) NOT FINAL
--------------------------------------------------------------------------------------------------------------------------CREATE OR REPLACE TYPE ROW_ERTRAG_BASE UNDER GLOBAL.TYPE_OBJECT
(-- attributes
ERTRAG_BASE_ID NUMBER(12)
, GATTUNG_BASE_ID NUMBER(12)
, BID_NR
VARCHAR2(5)
, DATUM
DATE
, ERSTELLT_ZST
DATE
, GEAENDERT_ZST
DATE
, ERSTELLT_ID
NUMBER(12)
, GEAENDERT_ID
NUMBER(12)
, ERSTELLT_IP
VARCHAR2(30)
, GEAENDERT_IP
VARCHAR2(30)
, GEAENDERT_ZAEHLER NUMBER(10)
-- define constructors
, CONSTRUCTOR FUNCTION ROW_ERTRAG_BASE RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION ROW_ERTRAG_BASE(ERTRAG_BASE_ID NUMBER, GATTUNG_BASE_ID NUMBER, BID_NR
,…
) NOT FINAL
17
12.06.2012
Geschäftslogik in der Datenbank
Schwergewichtiger TYPE & Load Balancing
MEMBER PROCEDURE INIT_KAPITAL_DETAIL(SELF IN OUT TYPE_GATTUNG)
IS
methodenname CONSTANT VARCHAR2(300) := 'WP.'||$$PLSQL_UNIT||'.INIT_KAPITAL_DETAIL';
FUNCTION parm RETURN VARCHAR2 IS BEGIN
RETURN substr( 'Parameter: ' || CHR(10) || 'SELF:' || SELF.TO_STRING(),1,32760);
END;
BEGIN
IF SYS_CONTEXT('TRACE','TRACE_LEVEL') >= GLOBAL.PA_TRACE.TRACE_TRACE THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_TRACE, methodenname, parm());
END IF;
SELF.kapitals := WP.TABLE_KAPITAL();
FOR rec IN (SELECT d.kapital_base_id
FROM WP.Kapital_Base d
WHERE d.gattung_base_id = SELF.id
ORDER BY datum
)
LOOP
SELF.kapitals.EXTEND;
SELF.kapitals(SELF.kapitals.LAST) :=
WP.TYPE_KAPITAL(in_kapital_base_id => rec.kapital_base_id);
END LOOP;
EXCEPTION
WHEN OTHERS THEN
GLOBAL.pa_trace.TRACE( GLOBAL.pa_trace.TRACE_ERROR, methodenname, parm()||CHR(10)||
', SQLcode=' || to_char(SQLCODE) || ', ' || SQLERRM);
RAISE;
END;
--------------------------------------------------------------MEMBER FUNCTION GET_KAPITAL_DETAIL(SELF IN OUT TYPE_GATTUNG) RETURN WP.TABLE_KAPITAL
IS
methodenname CONSTANT VARCHAR2(300) := 'WP.'||$$PLSQL_UNIT||'.GET_KAPITAL_DETAIL';
FUNCTION parm RETURN VARCHAR2 IS BEGIN
RETURN substr('Parameter: ' || CHR(10) || 'SELF:' || SELF.TO_STRING(),1,32760);
END;
BEGIN
IF SYS_CONTEXT('TRACE','TRACE_LEVEL') >= GLOBAL.PA_TRACE.TRACE_TRACE THEN
GLOBAL.PA_TRACE.TRACE( GLOBAL.PA_TRACE.TRACE_TRACE, methodenname, parm());
END IF;
IF SELF.kapitals IS NULL THEN
SELF.INIT_KAPITAL_DETAIL();
END IF;
RETURN SELF.kapitals;
EXCEPTION
WHEN OTHERS THEN
GLOBAL.pa_trace.TRACE( GLOBAL.pa_trace.TRACE_ERROR, methodenname, parm()||CHR(10)||
', SQLcode=' || to_char(SQLCODE) || ', ' || SQLERRM);
RAISE;
END;
18
12.06.2012
Geschäftslogik in der Datenbank
Fliegengewichtiger COMP
CREATE OR REPLACE TYPE COMP_GATTUNG UNDER GLOBAL.TYPE_OBJECT
( -- Attributes
GATTUNG_BASE_ID
NUMBER
, WKN
CHAR(6)
, ISIN
CHAR(12)
, SH
NUMBER(2)
, NAME
VARCHAR2(80)
, INSTRUMENT VARCHAR2(80)
, GELOESCHT DATE
-- Methods
, CONSTRUCTOR FUNCTION
, CONSTRUCTOR FUNCTION
, CONSTRUCTOR FUNCTION
, CONSTRUCTOR FUNCTION
, CONSTRUCTOR FUNCTION
, CONSTRUCTOR FUNCTION
COMP_GATTUNG RETURN SELF AS RESULT
COMP_GATTUNG(IN_GATTUNG_BASE_ID NUMBER) RETURN SELF AS RESULT
COMP_GATTUNG(IN_ISIN VARCHAR2, IN_SH NUMBER DEFAULT 0) RETURN SELF AS RESULT
COMP_GATTUNG(IN_WKN VARCHAR2, IN_SH NUMBER DEFAULT 0) RETURN SELF AS RESULT
COMP_GATTUNG(IN_ISIN VARCHAR2, IN_WKN VARCHAR2, IN_SH NUMBER) RETURN SELF AS RESULT
COMP_GATTUNG(IN_SECURITY_ID VARCHAR2, IN_ID_SOURCE VARCHAR2) RETURN SELF AS RESULT
, MEMBER FUNCTION GET_ABRECHNUNGS_WAEHRUNG_ISO(IN_BOERSENPLATZ_ID VARCHAR2) RETURN VARCHAR2
, MEMBER FUNCTION GET_ABRECHNUNGS_WAEHRUNG_ID(IN_BOERSENPLATZ_ID VARCHAR2) RETURN NUMBER
, MEMBER FUNCTION GET_ABRECHNUNGS_WAEHRUNG_ISO RETURN VARCHAR2
, MEMBER FUNCTION GET_HANDELS_WAEHRUNG_ISO(IN_BOERSENPLATZ_ID VARCHAR2) RETURN VARCHAR2
, MEMBER FUNCTION GET_HANDELS_WAEHRUNGEN_ISO(IN_BOERSENPLATZ_ID VARCHAR2) RETURN BBS.TAB_ROW_WAEHRUNG
, MEMBER FUNCTION GET_RIC RETURN VARCHAR2
, MEMBER FUNCTION GET_RIC(IN_BOERSENPLATZ_ID VARCHAR2) RETURN VARCHAR2
, MEMBER FUNCTION GET_SEDOL RETURN VARCHAR2
, MEMBER FUNCTION GET_CUSIP RETURN VARCHAR2
, MEMBER FUNCTION GET_EMITTENT_NR RETURN VARCHAR2
, MEMBER FUNCTION GET_HEIMATLAND_ISO RETURN VARCHAR2
, MEMBER FUNCTION GET_HEIMATBOERSE_ID RETURN VARCHAR2
, MEMBER FUNCTION GET_LETZTER_HANDELSTAG(IN_BOERSENPLATZ_ID VARCHAR2) RETURN DATE
, MEMBER FUNCTION IS_MIFID_RELEVANT RETURN BOOLEAN
, MEMBER FUNCTION IS_DAX RETURN BOOLEAN
, MEMBER FUNCTION IS_MDAX RETURN BOOLEAN
, MEMBER FUNCTION IS_SDAX RETURN BOOLEAN
, MEMBER FUNCTION IS_TECDAX RETURN BOOLEAN
, MEMBER FUNCTION IS_STOXX RETURN BOOLEAN
, MEMBER FUNCTION IS_HANDELBAR(IN_LAND_ISO VARCHAR2) RETURN BOOLEAN
, MEMBER FUNCTION IS_HANDELBAR(IN_BOERSENPLATZ_ID VARCHAR2) RETURN BOOLEAN
, MEMBER FUNCTION IS_HANDELBAR_FH(IN_BOERSENPLATZ_ID VARCHAR2) RETURN BOOLEAN
, MEMBER FUNCTION IS_INVESTRO RETURN BOOLEAN
, MEMBER FUNCTION IS_ZERTIFIKAT RETURN BOOLEAN
, MEMBER FUNCTION IS_WARRANT RETURN BOOLEAN
, MEMBER FUNCTION IS_FOND RETURN BOOLEAN
, MEMBER FUNCTION IS_BEGO_FOND RETURN BOOLEAN
, MEMBER FUNCTION IS_EHF RETURN BOOLEAN
, MEMBER FUNCTION IS_DEF RETURN BOOLEAN
,…
) NOT FINAL
19
12.06.2012
Geschäftslogik in der Datenbank
Schwergewichtiger TYPE
CREATE OR REPLACE TYPE TYPE_KUNDE UNDER BBS.ROW_KUNDE
( -- attributes
DEPOT
BBS.TABLE_DEPOT,
KONTEN
BBS.TABLE_KONTO,
KONTEN_BBS
BBS.TABLE_KONTO_BBS,
land
nationalitaet
rechtsform
branche
betreuer1
betreuer2
betreuer3
betreuer4
stammkreis
VARCHAR2(35),
VARCHAR2(35),
VARCHAR2(105),
VARCHAR2(105),
VARCHAR2(35),
VARCHAR2(35),
VARCHAR2(35),
VARCHAR2(35),
VARCHAR2(35)
-- define constructors
, CONSTRUCTOR FUNCTION TYPE_KUNDE
RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION TYPE_KUNDE(IN_STAMMNR VARCHAR2)
RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION TYPE_KUNDE(IN_UNTERDEPOTID NUMBER)
RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION TYPE_KUNDE(IN_KUNDENID NUMBER, IN_KONTOID NUMBER)
RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION TYPE_KUNDE(IN_DEPOTNUMMER CHAR, IN_REFERENZNUMMER NUMBER)
RETURN SELF AS RESULT
---------------------------------------------------------------- static functions instead of constructors
-- duplicate signature problem in Java
, STATIC FUNCTION CONSTRUCTOR_TYPE_KUNDE(IN_KUNDENID NUMBER)
RETURN BBS.TYPE_KUNDE
, STATIC FUNCTION CONSTRUCTOR_KONTONUMMER(IN_KONTONUMMER VARCHAR2)
RETURN BBS.TYPE_KUNDE
, STATIC FUNCTION CONSTRUCTOR_KONTO_BBS_ID(IN_KONTO_BBS_ID NUMBER)
RETURN BBS.TYPE_KUNDE
-- define member functions
, MEMBER PROCEDURE ROW_SELECT(IN_STAMMNR VARCHAR2)
, MEMBER PROCEDURE ROW_SELECT(IN_KUNDENID NUMBER, IN_VERSION NUMBER)
, MEMBER PROCEDURE init_text_fields
, MEMBER PROCEDURE INIT_DEPOT(SELF IN OUT TYPE_KUNDE,
IN_REFERENZNUMMER NUMBER DEFAULT NULL)
, MEMBER PROCEDURE INIT_DEPOT(SELF IN OUT TYPE_KUNDE, IN_DISPLAY_ID
, MEMBER PROCEDURE INIT_KONTEN(SELF IN OUT TYPE_KUNDE)
,…
) NOT FINAL
20
12.06.2012
Geschäftslogik in der Datenbank
NUMBER, IN_REFERENZNUMMER NUMBER DEFAULT NULL)
Fliegengewichtiger COMP
CREATE OR REPLACE TYPE COMP_KUNDE UNDER GLOBAL.TYPE_OBJECT
( -- Attributes
KUNDE_ID
NUMBER(12)
, STAMMNUMMER
CHAR(10)
, INHABER
VARCHAR2(35)
, SPRACHE_ID
NUMBER(12)
-- Methods
, CONSTRUCTOR FUNCTION COMP_KUNDE RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION COMP_KUNDE(in_kunde_id NUMBER) RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION COMP_KUNDE(in_stammnummer CHAR) RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION COMP_KUNDE(in_unterdepot_id NUMBER) RETURN SELF AS RESULT
) NOT FINAL
21
12.06.2012
Geschäftslogik in der Datenbank
Mischung OO-Type und relationale FK ID
Analogon zur DEREF in ODBMS kann man mit dem FK eines Type den anderen
Type instanzieren
declare
b wph.ROW_BOERSE;
h wph.ROW_HANDELSSYSTEM;
begin
b := wph.ROW_BOERSE('194');
h := wph.ROW_HANDELSSYSTEM(b.HANDELSSYSTEM_ID);
end;
22
12.06.2012
Geschäftslogik in der Datenbank
Wie programmieren wir in PL/SQL
-- Allocation ermitteln
FOR rec_alloc IN (SELECT g.COLUMN_VALUE AS xml
FROM TABLE (XMLSEQUENCE(rec_order.XML.EXTRACT('Order/Allocations/Allocation'))) g)
LOOP
-- Neue Allocation anlegen
t_allocation := NEW WPH.TYPE_ALLOCATION ( IN_KUNDE_ID
=> t_ob.KUNDE_ID
, IN_ANNAHMEART_ID => t_ob.ANNAHMEART_ID
, IN_ALLOC_IDENT
=> t_ob.ORDER_NR_EXTERN
, ...);
-- Order hinzufuegen
t_allocation.ADD_ORDER(IN_ORDER_BUCH_ID => t_ob.ORDER_BUCH_ID);
-- Client Account ermitteln
v_client_account := GLOBAL.PA_XML.EXTRACT_STRING(rec_alloc.XML, 'Allocation/ClientAccount');
-- Stueckzahl ermitteln
v_stueckzahl := GLOBAL.PA_XML.EXTRACT_NUMBER(rec_alloc.XML, 'Allocation/Stueckzahl');
IF v_stueckzahl IS NOT NULL THEN
-- Allocation hinzufuegen
t_allocation.ADD_ALLOCATION(IN_CLIENT_ACCOUNT => v_client_account
, IN_STUECKZAHL => GLOBAL.PA_XML.EXTRACT_NUMBER(rec_alloc.XML, 'Allocation/Stueckzahl')
, IN_KURS
=> NULL);
ELSE
-- Prozentsatz ermitteln
v_prozentsatz := GLOBAL.PA_XML.EXTRACT_NUMBER(rec_alloc.XML, 'Allocation/Prozentsatz');
-- Allocation hinzufuegen
t_allocation.ADD_ALLOCATION(IN_CLIENT_ACCOUNT => v_client_account
, IN_PROZENTSATZ => v_prozentsatz);
END IF;
END LOOP;
-- Allocation einstellen
t_allocation.EINSTELLEN();
23
12.06.2012
Geschäftslogik in der Datenbank
Wie programmieren wir in PL/SQL
-- zentrale Schnittstelle zum Steuermodul
PROCEDURE STEUER_BERECHNUNG(...)
IS
t_steuer BBS.TYPE_STEUER;
BEGIN
-- geschäftsbedingt Instanzierung
IF ....GESCHAEFTSART = 'KKZ' THEN
t_steuer := NEW BBS.TYPE_STEUER_KKZ(...)
ELSIF ....GESCHAEFTSART = 'WPK' THEN
t_steuer := NEW BBS.TYPE_STEUER_WPK(...)
ELSIF <weitere Geschäftsbereiche> THEN
t_steuer := NEW BBS.TYPE_STEUER_XXX(...)
END IF;
-- Aufruf der Steuerverrechnung
t_steuer.BERECHNE_STEUERN;
END;
24
12.06.2012
Geschäftslogik in der Datenbank
Unsere Leitsätze
Man sollte alles so einfach wie
möglich machen, aber nicht einfacher
Albert Einstein
"Der einfache und klare Zweck sowie Prinzipien
bedingen komplexes und intelligentes Verhalten".
"Komplexe Regeln und Vorschriften
bedingen einfaches und dummes Verhalten".
Dee Hock, Designer VISA-Systems 1960-1970
Ein System erreicht Perfektion nicht,
wenn nichts weiter hinzugefügt werden kann,
sondern wenn nichts weiter entfernt werden kann.
???
25
12.06.2012
Geschäftslogik in der Datenbank
Q&A
Vielen Dank !
26
12.06.2012
Geschäftslogik in der Datenbank
Herunterladen