[ORACLE] Datawarehouse bouwen: Klantdimensie vs Klant

Pagina: 1
Acties:

  • bartgabriels
  • Registratie: April 2005
  • Laatst online: 16-02 10:01
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
create or replace procedure update_demografie_dimklant
is
cursor cursklant is
select * from klantdim
for update of demografiekey;  
l_klantnr number;
l_waarde number;
l_kind number;
l_inkomen number;
l_rijksregisternr number;
k_klant number;
k_demografie number;
begin
for recklant in cursklant loop

select klantnummer, inkomen into l_klantnr, l_inkomen from klant where rijksregisternr=recklant.rijksregisternr;

--huidige demografie van de klant bepalen 
select nvl(sum(waarde),0) into l_waarde from eigendom where klantnummer=l_klantnr;

--aantal kinderen berekenen
select count(*) into l_kind from kind where klantnr = l_klantnr;

k_demografie := zoek_demografie(l_kind, l_inkomen, l_waarde);
update klantdim set demografiekey = k_demografie where current of cursklant;  
end loop;
end;
/
list 
show errors;


Ik ben bezig met het laatste opdrachtje voor mijn examen (Datawarehousing), echter zit ik hier al enkele ettelijke uren op te zwoegen.

In de tabel klantdimensies worden ALLE klantversies bijgehouden. Het kan dus zijn dat verschillende rijksregisternummers dubbel voorkomen, maar dan met een ander adres (vb: een verhuis)

In de tabel klant worden alle huidige klantversies bijgehouden die gebruikt worden door de 'filialen'. Hier is dus enkel de laatste versie van elke klant nuttig.

Nu moet ik door middel van een procedure ervoor zorgen dat de demografiegegevens, dit is een code op basis van loon, aantal kinderen en onroerend goed, aan de klantversie in de klantdimensie wordt gekoppeld.

Er is echt een addertje onder het gras: het kan zijn dat de klant nog wel bestaan in klantdimensie, maar niet meer in de klantentabel die gebruikt wordt voor de filialen. Hierop loopt deze procedure dus vast, aangezien het loon, aantal kinderen, ... daar nog steeds uitgehaald wordt.

De klant in de tabel "klant" laten staan MAG niet, laten we er vanuitgaan dat er reeds een heel systeem rond geschreven is dat niet aangepast kan worden.

Er zou dus een systeem moeten zijn, dat er voor zorgt dat hij controleert of het rijksregisternummer dat in de klantendimensie staat, gecontroleerd wordt in de tabel klant. Wanneer dit niet bestaat, moet hij alle update's niet uitvoeren.

Hopelijk is het duidelijk.

[ Voor 3% gewijzigd door bartgabriels op 05-06-2006 20:43 ]


  • JaQ
  • Registratie: Juni 2001
  • Laatst online: 23:48

JaQ

Ik begrijp echt geen hout van je verhaal, maar je hebt het er over dat je procedure "vast" loopt. Krijg je ook een foutmelding?

goed lezen is ook een vak.

Als je je benadering nou eens andersom legt, dus in plaats van een cursor over je klantdimentie een cursor over je klanttabel laat lopen.

Verder is er helemaal niets mis met indenting ;)

[ Voor 51% gewijzigd door JaQ op 05-06-2006 23:13 ]

Egoist: A person of low taste, more interested in themselves than in me


  • bartgabriels
  • Registratie: April 2005
  • Laatst online: 16-02 10:01
JaQ schreef op maandag 05 juni 2006 @ 23:11:
Ik begrijp echt geen hout van je verhaal, maar je hebt het er over dat je procedure "vast" loopt. Krijg je ook een foutmelding?

goed lezen is ook een vak.

Als je je benadering nou eens andersom legt, dus in plaats van een cursor over je klantdimentie een cursor over je klanttabel laat lopen.

Verder is er helemaal niets mis met indenting ;)
Het jammere is, vanuit de opdracht is het duidelijk dat de benadering moet komen vanuit de dimensie. Jammer maar helaas dus :)

De oplissing is simpel, maar ik weet niet helemaal hoe ik ze in code moet gooien
Er moet dus telkens er een andere record in de cursor wordt aangeroepen, gecontroleerd worden op de klant nog bestaat in de transactionele databank voor de filialen.

  • JaQ
  • Registratie: Juni 2001
  • Laatst online: 23:48

JaQ

bartgabriels schreef op maandag 05 juni 2006 @ 23:31:
[...]


Het jammere is, vanuit de opdracht is het duidelijk dat de benadering moet komen vanuit de dimensie. Jammer maar helaas dus :)

De oplissing is simpel, maar ik weet niet helemaal hoe ik ze in code moet gooien
Er moet dus telkens er een andere record in de cursor wordt aangeroepen, gecontroleerd worden op de klant nog bestaat in de transactionele databank voor de filialen.
Maar dat is bizar onhandig en dom in dit geval. De ene tabel is namelijk veel groter dan de andere en iedere zichzelf respecterende DBA die je warehouse bewaakt zal je code zo terug sturen vanwege performance redenen... Maar goed: is een exception handler een idee? (exception when no_data_found bijvoorbeeld ;))

bijvoorbeeld:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
PROCEDURE blaat

  var BOOLEAN := TRUE;

BEGIN

  BEGIN
  
    SELECT kolommen
       INTO variabelen
       FROM tabel
     WHERE iets=iets;

  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      var := FALSE;
  END;

  IF var THEN

    doe iets intelligents

  END IF;

END blaat;

[ Voor 18% gewijzigd door JaQ op 05-06-2006 23:51 . Reden: voorbeeld toegevoegd ]

Egoist: A person of low taste, more interested in themselves than in me


  • bartgabriels
  • Registratie: April 2005
  • Laatst online: 16-02 10:01
Ja ik weet het wel dat het onlogisch is, maar opdracht is nu eenmaal opdracht. Daar kunnen wij als student niet buiten.

Maar goed, bedankt voor de hulp, dat ik zelf niet op die exception handler gekomen ben. Waarschijnlijk was dit te voor de hand liggend om na 10 uur PL/SQL en SQL+ codes te zitte werken op te komen.

Maar, het werkt nu volledig.
Merci

Oh ja, in je code, zet de exception handler onder de if structuur, dan is hij helemaal correct. Mss kan dit handig zijn voor mensen die zoeken op GoT naar en bepaald probleem.

[ Voor 20% gewijzigd door bartgabriels op 06-06-2006 09:54 . Reden: Foutje in bovenstaande code ]


  • JaQ
  • Registratie: Juni 2001
  • Laatst online: 23:48

JaQ

bartgabriels schreef op dinsdag 06 juni 2006 @ 09:53:
Oh ja, in je code, zet de exception handler onder de if structuur, dan is hij helemaal correct. Mss kan dit handig zijn voor mensen die zoeken op GoT naar en bepaald probleem.
Dat lijkt me niet. Als je goed naar mijn voorbeeld kijkt, dan zie je dat een procedure wordt geopend met precies 1 variabele (die boolean).

Vervolgens begin ik een nieuw blok, met begin, daarin doe ik de query, handel de exception en als die afgaat, dan zet ik de boolean naar false. Vervolgens eindig ik het blok. Pas daarna ga ik checken of de boolean TRUE is. (en dat is ie dus niet als de NO_DATA_FOUND is afgegaan.

Je kan dus rustig een blok in een blok plaatsen. Dat zou uiteraard ook kunnen met een private functie of procedure. (dus tussen procedure blaat en begin in een nieuwe procedure definieeren, uiteraard met volledige syntax.


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
procedure Y

  procedure X
  begin
    doe iets...
  exception
    when no_data_found then
       niets gevonden dus
    when others then
      doe iets anders
  end X;
begin
 
  X

exception
  when others then
    nog weer een andere exception handler
end Y;


Een no_data_found exception aan het einde van deze procedure zou het complete nu van het sub-blok weghalen. Snap je?

niet om te patsen of zo, maar ik ben Oracle DBA, met een specialisme in webservers. Dat betekend echter niet dat ik geen sql en pl/sql meer kan ;)

Egoist: A person of low taste, more interested in themselves than in me


  • bartgabriels
  • Registratie: April 2005
  • Laatst online: 16-02 10:01
Nochtans, als ik de code invoer in SQL*Plus, is dit de enige manier om er zonder errors vanaf te komen
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
create or replace procedure update_demografie_dimklant
is
cursor cursklant is
select * from klantdim
for update of demografiekey;
var BOOLEAN := TRUE;  
l_klantnr number;
l_waarde number;
l_kind number;
l_inkomen number;
l_rijksregisternr number;
k_klant number;
k_demografie number;
begin
for recklant in cursklant loop

select klantnummer, inkomen into l_klantnr, l_inkomen from klant where rijksregisternr=recklant.rijksregisternr;

--huidige demografie van de klant bepalen 
select nvl(sum(waarde),0) into l_waarde from eigendom where klantnummer=l_klantnr;

--aantal kinderen berekenen
select count(*) into l_kind from kind where klantnr = l_klantnr;

k_demografie := zoek_demografie(l_kind, l_inkomen, l_waarde);

IF var THEN
update klantdim set demografiekey = k_demografie where current of cursklant;  
end if;
end loop;

EXCEPTION WHEN NO_DATA_FOUND THEN
      var := FALSE;

end;
/
list 
show errors;


[EDIT]
AAhhh, nu zie ik het, je subbed 2 PL/SQL procedures in elkaar :). Dan moet het inderdaad niet onder elkaar :)

Ik hou het liever allemaal in 1 procecure.

[ Voor 10% gewijzigd door bartgabriels op 07-06-2006 07:31 ]


  • JaQ
  • Registratie: Juni 2001
  • Laatst online: 23:48

JaQ

Vergeet niet dat je blok eindigd na de exception handler. Dit betekend dat je in jouw voorbeeld misschien maar een klein gedeelte van de updates doet. Een private procedure of een sub-blok is de enige correcte oplossing.

Egoist: A person of low taste, more interested in themselves than in me

Pagina: 1