Toehoorder bij Planboard Oracle DBA Symposium

Ik ben afgelopen dinsdag naar het Planboard Oracle DBA-symposium geweest, dat werd gehouden op landgoed De Horst in Driebergen. Was hierop geattendeerd door de weblog van Harald van Breederode.
Bij binnenkomst leek het meer op een reünie (“ik heb je vorig jaar gemist”,”ik ben alle keren geweest”,”leuk je weer te zien”), maar dat kon nooit over mij gaan, ìk was er voor het eerst! Gelukkig kwam ook ik de nodige bekenden tegen (blijkbaar is het Nederlandse Oracle-wereldje erg klein, althans wanneer het gaat om de party-crashers).

Na de inschrijving en het verplichte bordje-aan-een-lintje-om-je-nek begon het programma.

Ik heb de volgende sprekers beluisterd:

  • Yuri van Buren (Performance management-onderzoek met Oracle Grid Control)
  • Toon Koppelaars (Semantische Query Optimalisatie)
  • Harald van Breederode (Real Application Testing)
  • Erik Valk (Online Table Redefinition)
  • Jonathan Lewis (Interpreteren van Statspack)

(van eventuele recensies zal ik hier weblinks plaatsen)

Tussendoor was er meer dan voldoende gelegenheid om na te praten met de sprekers of mede-luisteraars waardoor de dag voor mij een meerwaarde had ten opzichte van een zware cursus-dag. Ook het gevarieerde programma maakte het prettig om bij te wonen (al was ik ‘s avonds bekaf). Na afloop nog een lekker en gezellig diner.

Bijdrage afdrukken Bijdrage afdrukken

Installatie Oracle database 10g op Windows Server 2008

Mij werd laatst gevraagd om bij een klant een installatie uit te voeren van Oracle-database 10g op een nieuwe (virtual) server.
Bij aankomst bleek dit te gaan om een Windows 2008-server (die Windows-versie had ik nog niet gezien).
Na het starten van de Oracle installer crashte deze meteen.
Volgens de documentatie is de Oracle installer van patchset 2 (naar 10.2.0.3) of hoger gecertificeerd voor Windows Server 2008 en Windows Vista.

In eerdere versies van de Oracle Universal Installer kon je nog browsen naar een ander installatiepunt. Deze mogelijkheid kon ik niet vinden in de installer van 10g.

Oplossing:

  • Ik heb de installer gebruikt van patchset 3 (naar 10.2.0.4). Deze is aanwezig in p6810189_10204_Win32.
  • pas in het bestand oraparam.ini (\Disk1\install) de waarde aan van de parameter SOURCE= (de standaardwaarde is ../stage/products.xml) zodat deze verwijst naar de products.xml van de 10g-basis-installatie (SOURCE=../../../Install/Disk1-database/stage/products.xml).
  • De installer kan nu worden opgestart.
  • Bij het controleren van de prerequisites kun je de melding dat dit Operating System niet is gesupport, negeren door het zetten van een vinkje. De installatie verloopt nu probleemloos.
  • Wil je patchset 3 installeren, pas dan in de oraparam.ini de waarde van SOURCE weer aan naar de default.

Verder bleek de database geen connecties van buitenaf te accepteren.
Reden: de ingebouwde firewall van Windows Server 2008. De fraaiste oplossing is om aan de firewall een uitzondering toe te voegen voor TCP-poort 1521 9standaard poortnummer van de Oracle Listener).

Hierna werkte alles probleemloos.

Bijdrage afdrukken Bijdrage afdrukken

Oracle collections, records en table-types deel II

In een eerdere bijdrage schreef ik over het gebruik van PL/SQL-records en ref cursoren.

Omdat ik binnenkort aan de slag mag voor een klant waarbij de opdracht luidt een procedure te schrijven die een geneste recordstructuur ontvangt en deze wegschrijft naar de diverse onderliggende tabellen, ben ik aan de slag gegaan om uit te zoeken hoe dit zou kunnen gaan in een voorbeeldsituatie
Ik heb de volgende opzet bedacht:

  • We hebben een bedrijf dat meerdere adressen (vestigingen) heeft en uit meerdere afdelingen bestaat
  • Een afdeling heeft meerdere werknemers
  • Een werknemer heeft een adres.

De bedoeling is, dat de verwerkende programmatuur 1 object ontvangt waarin het bedrijf + de onderliggende gegevens aanwezig zijn, en deze gegevens weer afzonderlijk beschikbaar maakt voor verdere verwerking.

Het bedrijf Ywemacom import/export heeft 2 adressen; een hoofdadres en een nevenadres
Hoofdadres: Hoofdstraat 1, Amersfoort
Nevenadres: Nevenstraat 1, Amersfoort
Het bedrijf heeft 2 afdelingen, elk met 2 werknemers. Iedere werknemer heeft 1 adres
Afdeling 1 :Verkoop
Werknemer 1: Jan de Groot
Adresgegevens: Hugo de Grootstraat, te Utrecht
Werknemer 2: Karen Veenstra
Adresgegevens: Winkelstraat, te Amsterdam
Afdeling 2: Transploft
Werknemer 1: Joop Schroefstra
Adresgegevens: Stadsring, te Amersfoort
Werknemer 2: Henk Woudenberg
Adresgegevens: Vinkenhof, te Scherpenzeel

In dit voorbeeld worden deze gegevens in de eerste procedure in de package body, ‘VUL’ , in regels 38 – 64 aan het object bedrijf_rec toegevoegd.
Hierna wordt dit object in regel 67 aan de tweede procedure, ‘TOON’ als parameter meegegeven.
Deze procedure pluist het object uit-elkaar en toont de inhoud dmv DBMS_OUTPUT.PUT_LINE. In de praktijk zal in plaats hiervan een serie inserts in tabellen plaatsvinden.

De stored-package BEDRIJF:

CREATE OR REPLACE package bedrijf as
--
   type adres_rec is record (straat varchar2(100)
                            ,nummer number
                            ,plaats varchar2(100)
                            ,adrestype varchar2(100)
                            );
   type adres_tab is table of adres_rec index by pls_integer;
   --
   type werknemer_rec is record (naam varchar2(100)
                                ,adres adres_rec
                                );
   type werknemer_tab is table of werknemer_rec index by pls_integer;
   --
   type afdeling_rec is record (naam varchar2(100)
                              , werknemer werknemer_tab
                              );
   type afdeling_tab is table of afdeling_rec index by pls_integer;
   --
   type bedrijf_rec is record (naam varchar2(100)
                          , adres adres_tab
                          , afdeling afdeling_tab
                          );
--
procedure vul;
end bedrijf;
/

CREATE OR REPLACE package body bedrijf as
--
procedure toon (p_bedrijf bedrijf_rec);
--
procedure vul is
-- vul een bedrijfsrecord
--
   l_bedrijf bedrijf_rec;
begin
   l_bedrijf.naam := 'Ywemacom import/export';  -- record-type
      l_bedrijf.adres(1).adrestype := 'Hoofdadres'; -- table-type
      l_bedrijf.adres(1).straat := 'Hoofdstraat';
      l_bedrijf.adres(1).nummer :=1;
      l_bedrijf.adres(1).plaats := 'Amersfoort';
      l_bedrijf.adres(2).adrestype := 'Nevenadres';
      l_bedrijf.adres(2).straat := 'Nevenstraat';
      l_bedrijf.adres(2).nummer :=1;
      l_bedrijf.adres(2).plaats := 'Amersfoort';
      l_bedrijf.afdeling(1).naam := 'Verkoop';
         l_bedrijf.afdeling(1).werknemer(1).naam := 'Jan de Groot';
            l_bedrijf.afdeling(1).werknemer(1).adres.straat := 'Hugo de Grootstraat';
            l_bedrijf.afdeling(1).werknemer(1).adres.nummer := 1;
            l_bedrijf.afdeling(1).werknemer(1).adres.plaats := 'Utrecht';
         l_bedrijf.afdeling(1).werknemer(2).naam := 'Karen Veenstra';
            l_bedrijf.afdeling(1).werknemer(2).adres.straat := 'Winkelstraat';
            l_bedrijf.afdeling(1).werknemer(2).adres.nummer := 2;
            l_bedrijf.afdeling(1).werknemer(2).adres.plaats := 'Amsterdam';
      l_bedrijf.afdeling(2).naam := 'Transploft';
         l_bedrijf.afdeling(2).werknemer(1).naam := 'Joop Schroefstra';
         l_bedrijf.afdeling(2).werknemer(1).adres.straat := 'Stadsring';
            l_bedrijf.afdeling(2).werknemer(1).adres.nummer := 15;
            l_bedrijf.afdeling(2).werknemer(1).adres.plaats := 'Amersfoort';
            l_bedrijf.afdeling(2).werknemer(2).naam := 'Henk Woudenberg';
            l_bedrijf.afdeling(2).werknemer(2).adres.straat := 'Vinkenhof';
            l_bedrijf.afdeling(2).werknemer(2).adres.nummer := 78;
            l_bedrijf.afdeling(2).werknemer(2).adres.plaats := 'Scherpenzeel';
--
-- roep de procedure aan met het bedrijfs-object als parameter
   toon(p_bedrijf => l_bedrijf);
end vul;
--
procedure toon (p_bedrijf bedrijf_rec) is
-- pluis het bedrijfs-object uit en druk de inhoud af
   l_bedrijf bedrijf_rec;
begin
   l_bedrijf := p_bedrijf;
   --
   dbms_output.put_line ('Bedrijf: '||l_bedrijf.naam); -- 1 bedrijf
   dbms_output.put_line ('Adresgegevens: ');
   for bedrijfsadressen in l_bedrijf.adres.first..l_bedrijf.adres.last loop
       dbms_output.put_line (l_bedrijf.adres(bedrijfsadressen).adrestype||': '||l_bedrijf.adres(bedrijfsadressen).straat||' '
                              ||l_bedrijf.adres(bedrijfsadressen).nummer||' te '
                              ||l_bedrijf.adres(bedrijfsadressen).plaats);
    end loop;
   -- afdelingen af
   for afdelingen in l_bedrijf.afdeling.first ..l_bedrijf.afdeling.last loop
      dbms_output.put_line ('Afdeling '||afdelingen||' is: '||l_bedrijf.afdeling(afdelingen).naam);
      -- werknemers af
      for werknemers in l_bedrijf.afdeling(afdelingen).werknemer.first..l_bedrijf.afdeling(afdelingen).werknemer.last loop
         dbms_output.put_line('Werknemer '||werknemers|| ' is: '||l_bedrijf.afdeling(afdelingen).werknemer(werknemers).naam);
         -- bijbehorende adresgegevens
         dbms_output.put_line('Adresgegevens: '||l_bedrijf.afdeling(afdelingen).werknemer(werknemers).adres.straat||' '
                                                  ||l_bedrijf.afdeling(afdelingen).werknemer(werknemers).adres.nummer||' te '
                                                  ||l_bedrijf.afdeling(afdelingen).werknemer(werknemers).adres.plaats);
      end loop;
   end loop;
end toon;
--

end bedrijf;
/

Aanroep in sql*plus en het resultaat

SQL> set serveroutput on
SQL> begin
2      bedrijf.vul;
3  end;
4  /

Bedrijf: Ywemacom import/export
Adresgegevens:
Hoofdadres: Hoofdstraat 1 te Amersfoort
Nevenadres: Nevenstraat 1 te Amersfoort
Afdeling 1 is: Verkoop
Werknemer 1 is: Jan de Groot
Adresgegevens: Hugo de Grootstraat 1 te Utrecht
Werknemer 2 is: Karen Veenstra
Adresgegevens: Winkelstraat 2 te Amsterdam
Afdeling 2 is: Transploft
Werknemer 1 is: Joop Schroefstra
Adresgegevens: Stadsring 15 te Amersfoort
Werknemer 2 is: Henk Woudenberg
Adresgegevens: Vinkenhof 78 te Scherpenzeel

PL/SQL procedure successfully completed.

SQL>

Bijdrage afdrukken Bijdrage afdrukken

Oracle Databaselink via Heterogeneous Services

Je kan niet-Oracle databases benaderen vanuit Oracle. Daartoe maak je gebruik van de Oracle component “Heterogeneous Services”. Het wordt standaard meegeïnstalleerd met een Oracle database server. Als je het apart moet installeren, dan moet je in ieder geval ook het script %ORA_HOME%\rdbms\admin\caths.sql draaien, als user sys.
Heterogeneous Services bestaat uit twee onderdelen: Generic Connectivity en Transparent Gateways. Het eerste gaat met OLEDB of ODBC en is gratis. Het tweede gaat met specifieke gateway componenten (dat wil zeggen: een gateway is specifiek voor de soort databron die je wil benaderen), waarvan er een aantal door Oracle meegeleverd worden, maar kost extra licenties. Dit verhaal gaat verder alleen over Generic Connectivity.

Stap-voor-stap voorbeeld: MS Access database via OLEDB benaderen vanuit Oracle.
OLEDB werkt alleen op Windows. Dus dit voorbeeld werkt ook alleen met een Oracle database op Windows.
1.    Zet je Access file op de database server of op een plek die je vanuit de database server via het file system kan benaderen.
2.    Maak, bijvoorbeeld in diezelfde directory, een nieuw tekstdocument en geef het een naam met de extensie UDL (van universal data link). Dubbelklik op de UDL file. Selecteer de tab Provider, selecteer “Microsoft Jet 4.0 OLE DB Provider”. Klik Next>> Selecteer de MDB file, doe voor de zekerheid Test Connection en klik OK.
3.    Bedenk een naam voor je database connectie van maximaal 8 tekens. Bijvoorbeeld: HSTEST. Dit noemen we de SID (service id). Ga op de database server naar %ORACLE_HOME%\hs\admin. Maak een kopie van de file inithsoledb.ora en noem hem init<SID>.ora. In dit geval dus: initHSTEST.ora. Edit in de file de parameter HS_FDS_CONNECT_INFO. Geef die parameter de waarde “UDLFILE=<Absoluut pad naar de UDL file, met dubbele backslashes>”, inclusief de dubbele quotes er omheen. Dus bijvoorbeeld:
HS_FDS_CONNECT_INFO=”UDLFILE=E:\\oracle\\oradata\\hstest\\hstest.udl”
4.    Edit de file %ORACLE_HOME%\network\admin\listener.ora, om een listener toe te voegen naar de nieuwe SID. Voeg toe aan de SID_LIST:

(SID_DESC =
(PROGRAM = hsolesql)
(SID_NAME = <SID>)
(ORACLE_HOME = E:\oracle\ora92)
)

5.    Edit de file %ORACLE_HOME%\network\admin\tnsnames.ora (op de server!) om een connectie naar de nieuwe SID toe te voegen. Voeg toe:

<SID> =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = <naam db server>)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = <SID>)
)
(HS = OK)
)

6.    Herstart de listener op de database service. Dit gaat het beste op de command-prompt. Type lsnrctl reload.
7.    Alle configuratie is nu klaar. Nu nog bij de data zien te komen. Start daartoe een sessie met de Oracle database. Bijvoorbeeld als scott/tiger. De truc is nu dat je een database link aanmaakt, bijvoorbeeld:

create database link testlink
connect to "Admin" identified by " "
using 'HSTEST’;

Daarbij moet wat er achter using staat overeen komen met de naam van de connectie in de tnsnames.ora op de server (!).
8.    Vervolgens kan je bij de data komen door @<database link naam> achter de tabelnaam te zetten, bijvoorbeeld:

select sysdate
from dual@testlink;

Uit dit stap-voor-stap voorbeeld kan je alle andere situaties verder wel afleiden. Wat je alleen nog moet weten is:
•    Bij ODBC in plaats van OLEDB moet je:
o    hsodbc in plaats van hsolesql gebruiken als PROGRAM in de listener.ora.
o    Bij HS_FDS_CONNECT_INFO in de init<SID>.ora de DSN naam van de System DSN opgeven die je wil benaderen.
•    Naast hsoleqsl en hsodbc is er ook nog hsolefs, voor file based OLEDB providers.

Wees er op bedacht dat, wanneer je met de Oracle Database Creation Assistant (dbca) een nieuwe database aanmaakt, de regel met HS = OK uit de tnsnames.ora verdwijnt (Oracle bug #315752.1).

Bijdrage afdrukken Bijdrage afdrukken

SQL*Loader en PL/SQL

Ik had de volgende uitdaging:
ik wil met SQL*Loader de data van een csv-bestand inlezen maar heb voor 1 kolom de waarde nodig van een veld in de database (de huidige waarde van een sequence).
Een query doen binnen een SQL*Loader-controlfile is niet mogelijk net als het meegeven van een custom-parameter aan het script.
In de documentatie wordt gesproken van het toepassen van functies op de kolommen, maar dit houdt in de praktijk in het upper- of lowercase zetten of anderszins formatteren van de gegevens.
Na lang zoeken kwam ik een relevant voorbeeld tegen in de voorbeeld-bestanden van het boek Oracle SQL*Loader: The Definitive Guide ( April, 2001) geschreven door Jonathan Gennick en Sanjay Mishra waarin gebruik werd gemaakt van een stored function. Bingo!
Om niet aan de copyrights te tornen van dit boek is de implementatie hieronder van mijzelf.

brondata data.csv

Code;Omschrijving
10;Mutatie
20;In onderzoek
30;Administratieve wijziging
40;Afgevoerd

doeltabel

CREATE TABLE TEST
( ID              NUMBER,
  SEQ_ID          NUMBER                        NOT NULL,
  CODE            VARCHAR2(4 BYTE),
  OMSCHRIJVING    VARCHAR2(150 BYTE),
  CONSTRAINT TEST_PK PRIMARY KEY (ID));

database-sequence

CREATE SEQUENCE TEST_SEQ
  START WITH 1
  MAXVALUE 999999999999999999999999999
  MINVALUE 1
  NOCYCLE
  NOCACHE
  NOORDER;

stored function

CREATE OR REPLACE FUNCTION get_seq_id
RETURN NUMBER
IS
/*******************************************************************************
Naam   : get_seq_id
Auteur : Louis Ywema
Datum  : 07-01-2009
Doel   : Deze functie retourneert de huidige waarde van sequence TEST_SEQ
Opmerkingen :

Wijzigingen
Datum      Naam          Beschrijving
---------- ------------- -------------------------
22-01-2009 Patrick Barel Error handling toegevoegd
*******************************************************************************/
–
l_return NUMBER := 0;
BEGIN
   BEGIN
      SELECT last_number - 1 — last_number is blijkbaar de waarde van nextval
      INTO l_return
      FROM user_sequences
      WHERE sequence_name = 'TEST_SEQ';
   EXCEPTION
      WHEN OTHERS THEN
         l_return := 0;
   END;
–-
   RETURN NVL( l_return, 1 );
END;
/

sql*loader-controlfile test.ctl

OPTIONS ( ERRORS=0, SKIP=1, DIRECT=TRUE)
load data
TRUNCATE INTO TABLE TEST
FIELDS TERMINATED BY ';'
TRAILING NULLCOLS
(CODE,
 OMSCHRIJVING,
 SEQ_ID "get_seq_id",   -- functie get_seq_id haalt het nummer op
 ID   SEQUENCE(MAX,1)   -- genereert een volgnummer
 )

commandscript inlezen_test.cmd om sql*loader-controlfile op te starten

@ECHO OFF
set NLS_LANG=AMERICAN_AMERICA.WE8MSWIN1252
set oracle_home=C:\oracle\product\9.2.0
%ORACLE_HOME%\bin\SQLLDR USERID=/
@ CONTROL=test.ctl LOG=test.log, BAD=test.bad, DATA=data.csv , DISCARD=test.dis,  DISCARDMAX=5

uitvoering

C:\TEMP\blog>inlezen_test.cmd

SQL*Loader: Release 9.2.0.6.0 - Production on Thu Jan 8 19:54:03 2009

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.

Load completed - logical record count 4.

C:\TEMP\blog>

resultaat

SQL> select * from test;

        ID     SEQ_ID CODE OMSCHRIJVING
---------- ---------- ---- -----------------------------------------------------
         1          1 10   Mutatie
         2          1 20   In onderzoek
         3          1 30   Administratieve wijziging
         4          1 40   Afgevoerd

SQL>

conclusie
Door het gebruiken van een stored PL/SQL-functie is het mogelijk om reeds aanwezige data in de database te gebruiken met SQL*Loader

Bijdrage afdrukken Bijdrage afdrukken

Command-scripts en pl/sql

Een enkele keer komt het voor dat ik een MS-DOS command-script wil gebruiken dat weer een Oracle-sql-script aanroept dat een stored function uitvoert. Hoe krijg je dan de uitkomst van die functie terug naar je command-omgeving?
1. Een simpele functie

create or replace function optellen (p_getal1 number
,p_getal2 number)
return number is
begin
return (p_getal1 + p_getal2);
end;
/

2. Het sql-script

-- optellen.sql
var  l_uitkomst number
begin
:l_uitkomst :=optellen(&1,&2);
end;
/
print :l_uitkomst;
exit;

3. Het command-script

rem optellen.cmd
@ECHO OFF
for /f %%D in ('sqlplus -s hr/hr@xe @optellen.sql %1 %2') do (
set res=%%D)
echo uitkomst is %res%

4. Uitvoering
Functie laden in de database en het command-script uitvoeren

C:\Documents and Settings\Administrator\Desktop>optellen.cmd 1 2

C:\Documents and Settings\Administrator\Desktop>rem optellen.cmd
uitkomst is 3
Bijdrage afdrukken Bijdrage afdrukken

Verslag van de FME-gebruikersconferentie in Münster

Ik heb de afgelopen dagen (30 november t/m 2 december) de FME-gebruikersconferentie in Münster bezocht en heb daar een aantal interessante presentaties bijgewoond.
Eerst iets over FME.

Eerlijk gezegd zou ik erg graag eerder met dit programma gewerkt willen hebben! Ik ben inmiddels meer dan 10 jaar professioneel bezig met Oracle-databases, en omdat je niets hebt aan een lege database, ook met het vullen ervan. FME is Haarlemmerolie voor je data. Ieder dataformaat dat redelijkerwijze gebruikt wordt kun je er mee lezen en schrijven. Wanneer ik een Excel of csv-bestand de database in wil krijgen schrijf ik sinds FME geen sql*loader meer, maar maak een FME-workbench; veel sneller en overzichtelijker,en: meerdere malen toepasbaar!

De FME-gebruikersdagen begonnen op maandag, maar de avond ervoor zijn wij al met de directeur van Safe software (de maker van FME), Don Murray uit Toronto, Canada op stap geweest; een bijzonder aardige man en razend enthousiast over zijn eigen spullen! Wat ik eigenlijk wel vreemd vond (maar ook wel aardig) is, dat hoewel FME nog maar zo’n 7500 gebruikers wereldwijd heeft, deze man ze gewoon opzoekt (en ze daardoor bijna alle persoonlijk moet kennen).

Dag 1

Na de registratie (waarbij de onvermijdelijke badge en het tasje) werden de presentaties geopend door de Duitstalige dagvoorzitter Christian Heisig, waarna Don de ochtend vulde met aardige presentaties over de vernieuwingen in FME2009 (waaronder de quick-connect mogelijkheid wat erg handig is wanneer de transformers erg ver uit elkaar liggen; je klikt op de ene en daarna op de andere en ze zijn verbonden, je kunt nu eindelijk van de source-dataset de attributen wijzigen, de workbench kun je nu uitrusten met een soort van generic source en destination waarbij je het datatype en de dataset pas op moment van uitvoeren kiest en waarbij de bronattributen toch als geheel worden meegenomen, erg sterk!), en daarna een presentatie over FME-server waarbij de de gemaakte workbench uploadt naar een FME-server waarna iedereen met een webbrowser de workbench kan uitvoeren nadat de parameters zijn gevuld en de brondata is ge-upload (deze presentatie had ik eerder bij Vicrea al gezien).

Daarna heb ik de presentaties van Klaas Dijkstra van NAVTEQ bijgewoond, waarbij hij vertelde hoe FME wordt ingezet bij het vervaardigen van digitaal kaartmateriaal (in mijn Garmin-GPS zit Navteq-kaartmateriaal), de presentatie van Hans van der Maarel, die vertelde hoe hij voor Rijkswaterstaat en de ANWB het kaartmateriaal helpt te maken met FME, en de presentatie van de Engelsman James Bowler die liet zien hoe met FME een website voor de Engelse verkiezingen (met kiesdistricten) is gemaakt. Als laatste de presentatie van Wibold Jongsma van het Ontwikkelingsbedrijf van de Gemeente Amsterdam (de presentatie waaraan ik ook input heb geleverd) die vertelde hoe FME wordt ingezet bij grondexploitatie-berekeningen bij de ontwikkeling van stedelijke ontwikkelingen. Gelukkig geen moeilijke vragen voor mij, hoewel ik de complete omgeving op mijn laptop bij me had.

‘s Avonds hebben we de kerstmarkt bezocht en was er een diner in restaurant A² aan het AA-meer.

Hier raakte ik meteen aan de praat met Barry Masterson, een Ierse medewerker van Con Terra (het bedrijf dat deze conferentie heeft georganiseerd) die net als ik een enthousiaste bierdrinker en thuisbrouwer is. ’s Avonds beloofde hij mij de volgende dag een paar brouwsels mee te geven.

Dag 2

De tweede dag begon met de presentatie van mijn collega Erik Jan Bodewitz waarin hij dieper inging op het gebruik van Oracle Spatial (en de uitdagingen die je daar tegen kunt komen); hij had slechts een tiental bijwoners verwacht maar de zaal zat vol om te luisteren naar deze goede presentatie. Hierna bezocht ik de presentatie van Wolfgang Hausch over de installatie van FME Server. Helaas deed de internetverbinding het niet waardoor hij geen live-voorbeelden kon geven. De laatste gast-presentatie werd gegeven door Rick Klooster van de gemeente Apeldoorn waarbij hij virtueel Apeldoorn liet zien; een mooie toepassing van hoe ruimtelijke data de burgers van Apeldoorn kan dienen.

De middag begon met de presentatie van Brett Madsen en Jeff Konnen waarbij ze vertelden hoe je een echte FME-guru kunt worden (lees de bijdragen van de FME Evangelist, doe mee met de FME Talk discussiegroep) en met welke opgaven ze vorig jaar bij de FME Idol-wedstrijd werden geconfronteerd. Hierna nam Don Murray het weer over met een blik in de toekomst (FME 2010 en verder) en een inventarisatie van wensen van gebruikers.

Hierna vond ik het welletjes en zijn we richting huis vertrokken.

De niet-techneuten onder de bezoekers hadden het maar moeilijk met al die transformers (maar wat moet je ánders verwachten op een gebruikers-onferentie…). Ik vond het een heel zinvolle en leuke gebruikersbeurs!
Lees hier de terugblik van de organisatoren.

FME-Idols op YouTube

Bijdrage afdrukken Bijdrage afdrukken

FME beurs in Duitsland

De komende paar dagen (30 november t/m 2 december) ben ik voor mijn werk op de FME User Meeting (FME Anwendertreffen) in Münster (die van de vrede in 1648).
Ik heb als ontwikkelaar meegewerkt aan een presentatie (als ik het goed heb gedaan hoef ik mijn mond niet open te doen) met als onderwerp “Improving quality of Urban Development Design and Budgetting by using FME” (het verbeteren van de kwaliteit van plantekeningen voor stedelijke ontwikkeling), gedaan met Wibold Jongsma van het Ontwikkelingsbedrijf van de Gemeente Amsterdam.
Mocht er gelegenheid en aanleding zijn dan laat ik iets van me lezen.

Bijdrage afdrukken Bijdrage afdrukken

Koppensnellers

Wekelijks krijg ik van onze telefoniste de melding dat er een Engelssprekende meneer aan de telefoon is die mij wil spreken.
headhunterNadat ik een paar keer zo’n telefoontje heb aangenomen is het mij wel duidelijk geworden; headhunters op jacht. De laatste tijd laat ik vriendelijk vragen of ze mij per e-mail willen benaderen (je weet tenslotte maar nooit…). Daar hoor je vervolgens nooit meer iets van.

Laatst heb ik een hele email-wisseling gehad met een Nederlandse banenjager. Ene meneer Z van bedrijf XXX.(geen namen en rugnummers, zie verder)

5-11-2008
bericht: Beste Louis,
Wij hebben je geselecteerd als geschikte kandidaat voor de functie van Oracle Developer binnen onze eigen organisatie. XXX is een groeiende onafhankelijke IT-dienstverlener (…)Do you have the skills?
Met vriendelijke groeten,

6-11-2008
Beste Z,
zozo, ben ik geselecteerd als geschikte kandidaat.
Ik ben erg benieuwd wat jouw beweegredenen zijn om mij te selecteren.
Volgens mij staat bij mijn cv dat ik niet beschikbaar ben.
Buiten dat kan ik geïnteresseerd zijn wanneer jullie baan aan de
volgende voorwaarden voldoet:
vaste baan inhouse binnen Amersfoort.
Max 36 uur p/w.

6-11-2008
Beste Louis,
Sterkte met je karakter en succes met je eisenpakket.
Met vriendelijke groeten,
Z

6-11-2008
dag Z,
met mijn eisenpakket is niets mis, sterker nog ik heb deze baan al!
Ik denk dat je op deze wijze van benaderen weinig sukses zult hebben; op mij komt het nogal intimiderend over. Je gaat er blijkbaar vanuit dat iedereen wanhopig op zoek is naar jouw bedrijfje.
Ik niet dus.

Groet,
Louis Ywema

Nadat het een paar dagen stil was gebleven plaatste mijn collega T een bericht op zijn blog met een weergave van bovenstaande, aangevuld met zijn eigen mening.

Daarna volgde er opnieuw een wisseling van e-mails en reacties van Z op deze pagina.

In volgorde:

13-11-2008
Beste Louis,
Schijnbaar zit het je nogal dwars dat je dit ook nog eens moet publiceren. Ook je collega T, nog nooit gesproken heeft zijn mening klaar.

Even kort samengevat:
Jouw opmerking:
“…zozo, ben ik geselecteerd als geschikte kandidaat….” schoot mij in het verkeerde keelgat.

Daarop reageerde ik met een verkeerde reactie. “Succes met je karakter en met je eisenpakket..”.

Klaarblijkelijk gaat het tegenwoordig niet meer om werkvreugde en de kans om je te ontwikkelen, maar alleen om geld en zo weinig mogelijk werken.

Met vriendelijke groeten,
Z

en

13-11-2008
Beste Z,
ik vind het wel genoeg zo.

Ik reageerde met ‘zo zo’ omdat ik voor zover ik weet niet als bemiddelbaar te boek sta (hoe kom jij trouwens aan mijn email-adres?) en de manier van schrijven ‘wij hebben jou geselecteerd’ mij heel erg deed denken aan de Readers Digest-mailings van enige jaren geleden waarin gouden bergen werden beloofd (die ongelezen de papierbak ingingen).
Ik word graag met enig respect benaderd en ben dit ook gewend van andere headhunters.

Ik heb jouw eerste ‘uitnodiging’ aan mijn collega’s laten lezen (zowel Oracle als .net-specialisten) en niemand zou op een dergelijke manier benaderd willen worden.

Verder vind ik de zin ‘Klaarblijkelijk gaat het tegenwoordig niet meer om werkvreugde en de kans om je te ontwikkelen, maar alleen om geld en zo weinig mogelijk werken.’ heel erg vreemd.
Jij weet niet wat voor werk ik doe en welke mogelijkheden mijn werkgever biedt. Ik word door jou in een hoek geplaatst die mij niet zint.

Ik zal jouw laatste reactie niet plaatsen, dit is toch al niet al te beste reclame voor jouw winkel.

daarna:

13-11-2008
Beste Louis,

Ik snap je gedrag niet en die van collega al helemaal niet. Ik heb hem niet eens gesproken…maar wel veroordelen op internet. Jullie vinden mijn reactie BOT, maar jouw reactie is ook BOT.

“…Zo zo…”, dat komt ook respectloos over. Vandaar mijn respectloze reactie, geef ik ook toe.

Je mag best kritiek hebben, geen enkel issue, graag zelfs, daar leer ik ook van. Ik hoor graag wat er zo “naar” aan mijn vacaturetekst is, want ik krijg namelijk ook zeer positieve reacties.

Graag hoor ik ook van je in welke hoek ik je druk en wat je daaraan niet zint.

Met vriendelijke groeten,
Z

Ik had al aangegeven dat het voor mij klaar was, maar toch:

14-11-2008
Beste Louis, T,

Aangezien jullie niet meer reageren op mijn vragen en op mijn mails, heb ik nog het verzoek om jullie verwijzingen naar mijn organisatie te verwijderen op internet. Indien dit niet gebeurd, zal ik juridische maatregelen overwegen.
Met vriendelijke groeten,
Z

Hierop heb ik de naam van zijn bedrijf weggehaald. Dit was nog niet genoeg, want de volgende eis kwam al vlot daarna:

14-11-2008
Louis,

Wat geeft jouw het recht om over mij te publiceren?
Ik wil dat jij en je collega T het ook weghaalt. In zijn geheel.

Z

Hierna heb ik de blog ingetrokken.

Het verhaal vond ik echter de moeite waard om toch te gebruiken, dus geheel geanonimiseerd staat het weer op z’n plek

Bijdrage afdrukken Bijdrage afdrukken

Object necessary for warmstarting database cannot be altered

Eén van de databases die ik beheer was een beetje corrupt (de database deed het gewoon) geraakt.
In de alert-log stonden dagelijks meldingen als:

ORA-00604: error occurred at recursive SQL level 2
ORA-01578: ORACLE data block corrupted (file # 1, block # 53168)
ORA-01110: data file 1: '\\ATHENA\ORADATA\GYGES\VSARCSDE\DB\SYSTEM01.DBF'

Onderzoek wees uit dat de corruptie zat in een database-index van schema SYS

select  owner, segment_name, segment_type
from dba_extents
where file_id = 1
  and block_id <= 53168
  and block_id + blocks > 53168;
OWNER       SEGMENT_NAME       SEGMENT_TYPE
----------  ------------------ ------------------
SYS         I_H_OBJ#_COL#      INDEX

Dit betreft dus SYS-index I_H_OBJ#_COL# op tabel HISTGRM$.
Probeer je deze index te rebuilden of verwijderen dan krijg je meteen de melding:

ERROR at line 1:
ORA-00701: object necessary for warmstarting database cannot be altered

Volgens Oracle Support:

In Oracle, Bootstrap refers to loading of metadata (data dictionary) before we OPEN the database.
Bootstrap objects are classified as the objects (tables / indexes / clusters) with the object_id below 56 as bootstrap objects.
These objects are mandatory to bring up an instance, as this contains the most important metadata of the database.
One of the objects which is included is I_H_OBJ#_COL#.

Het getal van 56 is me niet helemaal duidelijk;

select data_object_id from dba_objects where object_name = 'I_H_OBJ#_COL#';

=> 254

select * from bootstrap$ where sql_text like '%I_H_OBJ#_COL#%';

=> no rows selected
En nu?

De oplossing blijkt eenvoudig te zijn:

shutdown immediate;
startup migrate;
drop index I_H_OBJ#_COL#;
create index i_h_obj#_col# on histgrm$(obj#, col#) storage (maxextents unlimited);
shutdown immediate;
startup;
Bijdrage afdrukken Bijdrage afdrukken