DBPedias

Your Database Knowledge Community

Patrick Barel

  1. KScope 11

    About 4 weeks from now KScope11 will be well underway. I am really looking forward to attending this conference. I think it is more ‘developer-centric’ than for instance Oracle Open World is. I still have to create my schedule for the days, but I know of at least one session where I will be present.

    That will be my own session on Pipelined Table Functions. It will be on Tuesday, June 28th. Here’s the abstract of my presentation:

    “If you can do it in SQL, use SQL.” But sometimes even the very powerful version of SQL that Oracle provides is not enough and you need more, like loops, conditions, etc. If you can make the output of a function like it’s a table, then you can use it in SQL and have access to all the power PL/SQL provides. After this session, you will know how to create functions that can be used as tables in SQL.

    Before that I will do a preview session (or test run if you will) on Tuesday, June 14th at AMIS in the Netherlands. If you are not attending KScope11 in Long Beach and you live in or near the Netherlands then you are invited to join us. If you are attending KScope11 then you are of course invited to join me there.

    Hope to meet you either in Nieuwegein or in Long Beach.

  2. OPP Brussels

    Coming Wednesday the first edition of the OPP conference in Europe will start. I will be doing a presentation on Thursday on one of my favorite tools: PL/SQL Developer. I will be attending a lot of PL/SQL oriented sessions like ‘The Helsinki Declaration’ by Toon Koppelaars and for instance the ‘SOA for PL/SQL developers’ by Lucas Jellema. Actually I will only be attending one session by my personal friend Steven Feuerstein. But the good news is that we will be spending Tuesday afternoon together. My kids are really anxious to see him again.
    I will also be attending a couple of APEX oriented sessions for instance on ‘Dynamic Actions’ and on ‘Plugins’.
    It would be nice if you could be there, especially my session of course. If you attend my session then there are some goodies for you to take away. There are t-shirts and CD’s with a trial version of the tool. There are even a couple of packages with the user manual included.
    So, hope to see you there.

  3. OPP 2010

    On October 27th and 28th the combined OPP (Oracle PL/SQL Programming) and APEXposed conference is coming to Europe. To Brussels to be exact. I have had the privilege to attend these conferences since the first one in 2005. The nice thing about this conference is that it is the only conference (at least that I know of) that is totally focused on PL/SQL. Three tracks with all kinds of ideas of what you can do in PL/SQL. From using collections (been around since Oracle 7) to Edition Based Redefinition (Oracle 11Gr2).
    If there is a slot in the agenda that has nothing you like, you are welcome to switch to the APEXposed conference to see if there is something you like.
    I know I am a big fan of PL/SQL since it has nothing to do with building a front-end but more with getting the job done, using as less resources as possible and applying the best techniques available in the version I am working with.
    I am not much of a visual developer. But using APEX, even I can make nice applications that are easy to build and even look nice.
    Shameless plug: I will also be doing a presentation on my favorite tool PL/SQL Developer. If you attend the conference, I hope you will come and see this.

  4. Where Am I…

    .code, .code pre { font-size: small; color: #00007F; font-family: “Courier New” Courier monospace; background-color: #ffffff; /*white-space: pre;*/ } .code pre { margin: 0em; } .code .rem { color: #008000; } .code .kwrd { color: #007F7F; } .code .comm { color: #ff0000; } .code .str { color: #006080; } .code .op { color: #0000c0; } .code .preproc { color: #cc6633; } .code .asp { background-color: #ffff00; } .code .html { color: #800000; } .code .attr { color: #ff0000; } .code .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .code .lnum { color: #606060; }

    On my new job we wanted to provide some logging. Especially about what program is currently running. Of course it would be easy enough to add a line at the start of the program with the name of that program and one at the end. But, as things go during development, names (and types) of programs tend to change and we would have to change those lines accordingly. Something that can (and will) be easily forgotten.

    Why not have the code tell us where we are. That way we wouldn’t have to change our code if the program name changes. But unfortunately there is no such thing as a function to tell me where I am.

    So, I decided to write one of my own. In the old days, using Novell network software, there was a function called WhoAmI, so I decided to name my function WhereAmI. What does Oracle offer me to tell me where I am. There is such a thing as DBMS_UTILITY.FORMAT_CALL_STACK. This provides a nice call stack of all the programs called in sequence like this:

       1:  ----- PL/SQL Call Stack -----
       2:    object      line  object
       3:    handle    number  name
       4:  287562CC         7  function UTIL.WHEREAMI
       5:  29DEBFF8         7  anonymous block

    The first three line are header information. The fourth line is where we are when this function is being called, being our function, so the first line of interest to us is the fifth line:

       1:  29DEBFF8         7  anonymous block

    Actually we only need the text in the third column. That tells us exactly where we are. Using string searching capabilities we remove everything we don’t need. First of all, we search for the position of the first space, then we copy the rest of the string and by using the trim functionality we remove any (leading and trailing) spaces from it. Now we have:

       1:  7  anonymous block

    If we execute this trick again we are left with the information we are interested in:

       1:  anonymous block

    Using this function at the start and end of our programs where to see the exact name of the program we are entering or exiting no matter what the type is, or if it is packaged or not. Only thing it doesn’t show me is whether it’s a private program or a local program.

    The complete code for the function is like this:

       1:  FUNCTION whereami RETURN VARCHAR2 IS
       2:    l_callstack   VARCHAR2(2000);
       3:    l_returnvalue VARCHAR2(100);
       4:  BEGIN
       5:      <<code>>
       6    -- Get the current callstack
       7:    l_callstack := dbms_utility.format_call_stack;
       8:   -- The line of interest is the fourth line.
       9:    l_returnvalue := substr(l_callstack
      10:                           ,instr(l_callstack, chr(10), 1, 4) + 1
      11:                           ,(instr(l_callstack, chr(10), 1, 5) - instr(l_callstack, chr(10), 1, 4)));
      12:    -- All we are interested in is the type and the name of the program.
      13:    l_returnvalue := TRIM(substr(l_returnvalue, instr(l_returnvalue, ' ', 1)));
      14     l_returnvalue := TRIM(substr(l_returnvalue, instr(l_returnvalue, ' ', 1)));
      15:    RETURN l_returnvalue;
      16  END whereami;
  5. CodeGen and APEX.

    When building code to support your APEX application, it is always nice to be able to generate large parts of that code. I am really fond of creating code using the QDA. The only trouble is that you need to create all the packages separately. What I have found works for me is to create a single script for the sequence, all the packages and the trigger creation. This is something that had to be done by hand because QNXO generates separate files for the different parts of the Table API.
    I could create a new script and just copy in all the lines in the other scripts, but what would happen if one was to change? I would have to make that change in multiple places. Something I would rather not do. So instead of creating a new script with copies of the current code I decided to copy the ‘install’ script and adapt that to create the complete install script. Instead of calling a different file using the @@ option in SQL*Plus (or PL/SQL Developer of course), I [INCLUDE]d the scripts I needed. This way I am using the exact same script which is being used when creating the QDA scripts ‘the old way’. I had a bit of a problem generating the sequence and the triggers. I appeared that some setup scripts were not run.
    In the existing ‘tree’ these scripts were run at different levels of the hierarchy. I could of course create a similar hierarchy, but I don’t want that. I don’t like to be constrained to a special way to work. CodeGen supplies the possibility to run setup scripts prior to the actual script. There is my way out. I want to run some setup scripts prior to my actual script.
    The setup scripts that need to be executed:
    NAMING-CONVENTIONS-FOR:”QCGU Development Architecture for PL/SQL”
    QDA_flags_for_table_processing
    The actual script:
    REM One full install script for the QDA code
    REM Based on the existing scripts.
    REM SPOD: Single Point Of Definition
    REM (c) 2010: Bar Solutions
    [include]primary_key_generation_controls
    #
    # Remove any lines that aren’t relevant.
    #
    REM Remove any lines you don’t need or don’t apply to your situtation.

    # 1.4 Do not always include this line.
    [IF]{qda_generating_pky}[EQ]{qda_true}[AND]{pkycoldatatype_sql}[IN]INTEGER,NUMBER
    CREATE SEQUENCE {sequence_name:[objname/a]};

    [ENDIF]
    [INCLUDE]Types Package Specification
    SHOW ERRORS
    [INCLUDE]Query Package Specification
    SHOW ERRORS
    [INCLUDE]Change Package Specification
    SHOW ERRORS
    [IF]{include_utility_packages}[EQ]{qda_true}
    [INCLUDE]Utilities package specification
    SHOW ERRORS
    [ENDIF]
    [INCLUDE]Query Package Body
    SHOW ERRORS
    [INCLUDE]Change Package Body
    SHOW ERRORS
    [IF]{include_utility_packages}[EQ]{qda_true}
    [INCLUDE]Utilities package body
    SHOW ERRORS
    [ENDIF]
    #
    # 1.4 Apply logic here from the audit trigger script
    [SETALIAS]l_pky_gen[TO]{qda_false}
    [IF]{qda_generating_pky}[EQ]{qda_true}[AND]onepkycol
    [SETALIAS]l_pky_gen[TO]{qda_true}
    [ENDIF]
    [IF]{l_pky_gen}[EQ]{qda_true}[OR][-]
    {grp_int_table}[EQ]{qda_true}[OR][-]
    {have_audit_columns}[EQ]{qda_true}
    [INCLUDE]Audit triggers
    [ENDIF]
    And of course I need to copy the arguments from the scripts that are executed when I run the entire script group.
    And there it is, a single script to install the packages for the QDA.

  6. Fun with APEX…

    favorite During the last couple of days I have been playing around with the new, hosted version of APEX. I know I haven’t been using all the features available in APEX and I have mostly been using my mod_plsql skills, because I don’t know how to do certain things in APEX (yet).

    I have been (and am still) rebuilding a webpage I have built using PHP and MySQL (http://bar-solutions.com/ezlinks). I am pretty pleased with the result so far (http://tryapexnow.com/apex/f?p=2231 username/password: demo/demo)

    It is fun to build code (PL/SQL code of course) to have the pages do what I want them to. I have been using a nice regular expression by Alex Nuijten to split the defined tags into separate entries.

    If you have any issues, bugs etc, please don’t hesitate to mention them. Maybe I will solve it (if at all possible ;-))

  7. Export APEX to the rescue…

    I had a good time in Atlanta at OPP doing my presentations. When I got back I had some issues regarding our APEX application that I needed to solve. But the guys at the office decided to drop all objects from the schema and create all the necessary objects again. This way we got rid of all the development code and all the rubbish gathered over the last couple of months. That is a good thing. Not so good was that the APEX application was also imported again and I created a script that creates a run-only version of the application.
    This is a good thing, because on the test, acceptance and definitely production database we don’t want the development to continue. We have a space for that and that is called, the development environment. Luckily I had a sandbox application in place that was still accessible. I decided to export this application twice, once as a RUN-ONLY application and once as a RUN-AND-BUILD application.

    By comparing both the scripts that have been created I thought I could find the difference on how the application would be created.

    It appeared that, besides from some time issues, the main difference lies in the way the application is being created. With a run-only application the call to create the application is like this:

    –application/create_application
    begin
    wwv_flow_api.create_flow(

    p_build_status => ‘RUN_ONLY’,

    end;
    /

    With a run-and-build application the call to create the application is like this:

    –application/create_application
    begin
    wwv_flow_api.create_flow(

    p_build_status => ‘RUN_AND_BUILD’,

    );
    end;
    /
    Well, that looked promising. I decided that I had to change the current export script as this had the RUN_ONLY option in place. I couldn’t wreck it anymore than it already was.

    I changed the script. ran it, and there it was. My application was available for editing again. Instead of finding out what table data to change and spending hours finding out where Oracle stores the way an application behaves, it took me just the time to export (twice), do the comparison, make the change en run the import. Less than an hours work. Thank Oracle for such an easy way to rescue my application and save me from hours, if not days, of recreating it.

  8. Life after OPP…

    As I am writing this I am on a plane ride back from Atlanta to Amsterdam. I had a great time in Atlanta during OPP. I also enjoyed doing the sessions I presented. One was on ‘Table Functions’ and another was on Collections and Bulk Operations. Both these session were scheduled in the same timeslot Steven Feuerstein got, yet both times I have drawn a bigger audience than he did. Something I am really proud of.

    I also did a presentation in the tools track for Allround Automations’ product ‘PL/SQL Developer’. This audience was of course smaller, but it allowed this presentation to be more interactive. The guys from Allround were nice enough to sent out some shirts and books and the audience really enjoyed those. I could barely save one for myself ;-).

    I have been busy for months preparing for this seminar. Not full time of course, but it has taken up a lot of my thoughts over the last couple of months. Now what should I do with my time. Maybe prepare for OPP2010 ;-). Don’t even know when and if there will be one. Don’t even know if I will be invited as a presenter again.

    I know I learned a lot preparing for the sessions. I know how to use the stuff I was talking about, but I needed more in depth knowledge, which I got from reading documentation, blogs, books etc. So, until next year, I will be doing something different with my spare time. Maybe I can focus on becoming on OCP on PL/SQL.

  9. OPP-Preview (partially Dutch)

    WebButton De Oracle PL/SQL Programming conference vind dit jaar in Atlanta, Georgia plaats. Patrick Barel is daarbij om een drietal presentaties te geven. Voor degene die niet aanwezig zullen zijn in Atlanta vind deze OPP-Preview plaats.
    Tijdens deze KC zal Patrick twee van deze presentaties geven.
    Na het diner zal Alex een re-run geven van zijn ODTUG presentatie: "SQL Holmes".

    Het programma voor deze avond:
    16:30
    "Pipelined table functions" - Patrick Barel
    Pipelined table functions offer an ideal convergence of the elegance and simplicity of PL/SQL with the performance of SQL. Complex data transformations are effortless to develop and support with PL/SQL, yet to achieve high-performance data processing, we often resort to set-based SQL solutions. Pipelined functions bridge the gap between the two methods effortlessly, but they also have some unique performance features of their own, making them a superb performance optimization tool.

    18:00
    diner: Chinees

    Na diner (rond 19:00):
    "SQL Holmes: The Case of the Missing Performance" - Alex Nuijten
    During this presentation, a case study is unfolded to reveal the true cause of a slow performing query. Did the database just "have a bad day"? Was the evil DBA to blame? The PL/SQL developer who didn’t get enough coffee? Or was it the application sending the "wrong" query in the first place?
    In this classic "whodunnit" you will take a tour past the crime scene. Investigate the query, use the tools of the trade and collect all the relevant information. Follow the trail to uncover the truth and nothing but the truth…

    20:00
    Ter afsluiting:
    "Optimizing SQL with Collections" - Patrick Barel
    Collections (array-like structures in PL/SQL) are used in two of the most important performance features of PL/SQL: FORALL and BULK COLLECT. This session demonstrates the power of these features and offers in-depth guidance on how to apply them.

  10. Reading values from a varchar2 indexed Associative Array

    logo-oracleOracle has provided us with collections since Oracle 7. It is one of the most renamed features in the Oracle database. In Oracle 7 they were called ‘PL/SQL Tables’. In Oracle 8 they were renamed to ‘Index By Tables’ and since Oracle 9 they are called ‘Associative Arrays’. If you index by an integer value then you can read the values by using an integer index variable. If the array is dense, that means all the indexes, from the first to the last, have a value associated to them you can even use a numeric for loop to get to the data. But what if you index by a string value, which is a possibility since Oracle 9i.

    9iThe solution is actually rather simple. Using a simple loop. First of all create an index variable of the same type you use to index the collection. It would be kind of silly to declare the collection using a varchar2(10) and then declare an index variable as a varchar2(5). If an index value would be ‘Patrick’ then this wouldn’t fit in the index variable resulting in a error.

    ORA-06502: PL/SQL: numeric or value error: character string buffer too small

    Then assign the index variable the value of the first index used. Now start the loop and do the stuff you want with the collection. At the end of the loop assign the next index value to the variable. If you try to read past the end of the collection, then the value of the index will be NULL, which is a great marker to exit the loop.

    If you put the exit clause as the first statement in the loop, then there is no reason to check for any items present in the collection. If you want to check how many items are present, then use <collection>.count.

    I have created a small script to demonstrate how it can be done:

    declare
      subtype index_t is varchar2(10);
      type  birthdates_tt is table of date index by index_t;
      l_birthdates birthdates_tt;
      l_indx index_t;
    begin
      -- Fill the table with the birthdates
      l_birthdates('Patrick') := to_date('29-12-1972','DD-MM-YYYY');
      l_birthdates('Dana') := to_date('06-03-1976','DD-MM-YYYY');
      l_birthdates('Quinty') := to_date('18-12-1998','DD-MM-YYYY');
      l_birthdates('Kayleigh') := to_date('19-11-2000','DD-MM-YYYY');
      l_birthdates('Mitchell') := to_date('23-06-2003','DD-MM-YYYY');
    
      -- make index variable the same as the first from the list
      l_indx := l_birthdates.first;
      -- start a simple loop
      loop
        -- exit the loop when we passed the end
        exit when l_indx is null;
        -- write the value of the index and the value at index in the AA to screen
        dbms_output.put_line(l_indx ||' => '||l_birthdates(l_indx));
        -- select the next index value from the list
        l_indx := l_birthdates.next(l_indx);
      end loop;
    end;
    /

    WebButtonI hope this information helps in leveraging the power of collections. That is no need to know the index values upfront, because you can traverse the collection at runtime where you don’t know the values of the indexes used. Some of this behavior and more about collections will be part of my presentation about Optimizing SQL with Collections at OPP2009.

  1. 1
  2. Next ›
  3. Last »