Do you know the difference between USER_TAB_COLS & USER_TAB_COLUMNS?

I just noticed the difference – I was wondering why I couldn’t see the virtual columns (i.e. columns that support function-based indexes) on a table, and it was because I was querying USER_TAB_COLUMNS. Once I used USER_TAB_COLS instead there they were.

The difference is noted in the documentation (Oracle 10g Release 2 (10.2)) for USER_TAB_COLS and ALL_TAB_COLS but not for USER_TAB_COLUMNS or ALL_TAB_COLUMNS, unfortunately.


Replace the default XDB welcome page

I was annoyed that to get to my main PL/SQL page I have to type in a full URL like this:

http://host:7777/mydad/home

(e.g. “mydad” could be “apex” for Oracle Apex)

If I was using Apache HTTP Server I’d do something this article suggests. But I’m using Oracle’s Embedded PL/SQL Gateway.

A. I got rid of the “:7777” by changing the HTTP port to 80, e.g.:

SQL> exec dbms_xdb.sethttpport(80);

Now, I can get to it without the port number:

http://host/mydad/home

B. Now I want to remove the need to remember to type “home”. To do this, I just tell the DAD what the default page is:

SQL> exec dbms_epg.set_dad_attribute('MYDAD','default-page','home');

Now, the url is a bit simpler:

http://host/mydad

The URL is now rewritten automatically to point to “mydad/home”.

C. Finally, I want to remove the need to specify the DAD. To do this is a little more complicated. I’ll create an XDB resource that will override the default XDB navigator that comes up.

    1. Log into Enterprise Manager

 

    1. Open the “Administration” tab and select “Resources” under “XML Database”

 

    1. Click “Create” and set the fields as follows:
      Owner = SYS
      Name = index.html
      Location = /
      Type = XML Database Resource File
      Source = Specify the file contents
      Contents =
      <html><head><meta http-equiv="REFRESH" content="0; URL=http://host/mydad"></head><body><a href="http://host/mydad">Home</a></body></html>

 

  1. Click “Ok”

(you’ll need to change “host” and “mydad” to appropriate values in the sample Contents above)

Now, the url is simply:

http://host

This causes it to load the index.html page from the XML database, which redirects to the DAD, the default page for which is “home”.


APEX 3.0 via Embedded PL/SQL Gateway

I managed to get APEX 3.0 working on Oracle 10.2.0.1 using the embedded PL/SQL gateway (i.e. without installing Apache), contrary to the advice given here. I used apex_epg_config instead of apex_epg_config11. For it to work, however, I had to remove some security on XDB so it’s not a recommended option. This involved modifying my xdbconfig.xml to allow anonymous access to XDB using this:

DECLARE
  configxml SYS.XMLType;
BEGIN
  SELECT INSERTCHILDXML(xdburitype('/xdbconfig.xml').getXML(),
         '/xdbconfig/sysconfig/protocolconfig/httpconfig',
         'allow-repository-anonymous-access',
         XMLType('true'),
         'xmlns=&quot;http://xmlns.oracle.com/xdb/xdbconfig.xsd&quot;')
  INTO configxml FROM DUAL;
  DBMS_XDB.cfg_update(configxml);
END;
/

Now for some general tips:

Tip #1. List Your DAD Authorizations

As described so well in the excellent article DBMS_EPG – The Embedded PL/SQL Gateway in Oracle 10g Database Release 2, you can authorize and deauthorize a DAD using the DBMS_EPG package. It should be noted that dropping a DAD will not remove the authorizations as well, so you need to deauthorize it as well. To find out what authorizations have been made on your database, you can query the DBA_EPG_DAD_AUTHORIZATION view, e.g.:

SQL&gt; select * from dba_epg_dad_authorization;

DAD_NAME USERNAME
-------- ---------
APEX     ANONYMOUS

1 row selected.

There’s also a USER_EPG_DAD_AUTHORIZATION view which shows the DAD_NAME for authorized DADs for the current user.


Tip #2. List Your DADS

You can find out what DADs have been set up on your instance using the DBMS_EPG package. There is a bug, however, that causes dbms_epg.get_all_dad_attributes to return nothing, so this script gets each attribute separately with dbms_epg.get_dad_attribute. The script lists all the DADS, their mappings and their attributes.

set serveroutput on

PROMPT list all dads
declare
  blank       dbms_epg.varchar2_table;
  dad_names   dbms_epg.varchar2_table;
  paths       dbms_epg.varchar2_table;
  procedure show_dad_attribute(dad in varchar2, attr in varchar2) is
    val varchar2(4000);
  begin
    val := dbms_epg.get_dad_attribute(dad, attr);
    if val is not null then
      dbms_output.put_line('... ' || attr || '=' || val);
    end if;
  end;
begin
  dbms_epg.get_dad_list(dad_names);
  if dad_names.count &gt; 0 then
    for i in dad_names.first..dad_names.last loop
      dbms_output.put_line(dad_names(i));
      paths := blank;
      dbms_epg.get_all_dad_mappings(dad_names(i), paths);
      if paths.count &gt; 0 then
        for j in paths.first..paths.last loop
          dbms_output.put_line('... path=' || paths(j));
        end loop;
      else
        dbms_output.put_line('... No mappings found');
      end if;
      show_dad_attribute(dad_names(i),'after-procedure');
      show_dad_attribute(dad_names(i),'always-describe-procedure');
      show_dad_attribute(dad_names(i),'authentication-mode');
      show_dad_attribute(dad_names(i),'before-procedure');
      show_dad_attribute(dad_names(i),'bind-bucket-lengths');
      show_dad_attribute(dad_names(i),'bind-bucket-widths');
      show_dad_attribute(dad_names(i),'cgi-environment-list');
      show_dad_attribute(dad_names(i),'compatibility-mode');
      show_dad_attribute(dad_names(i),'database-username');
      show_dad_attribute(dad_names(i),'default-page');
      show_dad_attribute(dad_names(i),'document-path');
      show_dad_attribute(dad_names(i),'document-procedure');
      show_dad_attribute(dad_names(i),'document-table-name');
      show_dad_attribute(dad_names(i),'error-style');
      show_dad_attribute(dad_names(i),'exclusion-list');
      show_dad_attribute(dad_names(i),'fetch-buffer-size');
      show_dad_attribute(dad_names(i),'input-filter-enable');
      show_dad_attribute(dad_names(i),'info-logging');
      show_dad_attribute(dad_names(i),'owa-debug-enable');
      show_dad_attribute(dad_names(i),'max-requests-per-session');
      show_dad_attribute(dad_names(i),'nls-language');
      show_dad_attribute(dad_names(i),'path-alias');
      show_dad_attribute(dad_names(i),'path-alias-procedure');
      show_dad_attribute(dad_names(i),'request-validation-function');
      show_dad_attribute(dad_names(i),'session-cookie-name');
      show_dad_attribute(dad_names(i),'session-state-management');
      show_dad_attribute(dad_names(i),'transfer-mode');
      show_dad_attribute(dad_names(i),'upload-as-long-raw');
    end loop;
  else
    dbms_output.put_line('No dads found');
  end if;
end;
/

When the above script is run, you’ll get something like this:

APEX
... path=/apex/*
... authentication-mode=Basic
... database-username=ANONYMOUS
... default-page=apex
... document-path=docs
... document-procedure=wwv_flow_file_mgr.process_download
... document-table-name=wwv_flow_file_objects$
... nls-language=american_america.al32utf8
... request-validation-function=wwv_flow_epg_include_modules.authorize

The State Of My Blog

I’ve had a few blogs in my head the last few months but haven’t had a chance to write them up. This is partly affected by the release cycle at work, and some extra-curricular volunteer work, but mostly by the birth of our second child.

[Warning: the next paragraph is not Oracle-related – skip ahead to the following paragraph if you like…]

Daniel’s arrival has probably affected our home routine more than Chloe’s did; at least with Chloe there was only one child requiring attention at any given moment; now there’s two kids screaming and during the week Daddy’s away at work for 10+ hours a day, so Rosalie’s got to handle it all by herself. The pressure isn’t helped much when one or more of us falls sick; last week Chloe and I were beset with headaches and fever, and while we’re almost recovered now, Daniel has started getting blocked up and having trouble sleeping. To top it all off Rosalie’s a bit under the weather as well. The cold and wet weather here in Perth has probably been a contributor – we’ve had temperature ranges as low as 8-17 degrees (Celsius)!

Yet another contributor to my lack of blogging activity was a fair amount of involvement in the State Youth Games earlier this month; this took a lot of my time, especially throughout May. Soon, I’ll blog about the Oracle APEX-driven web site I created for our team, partly on my non-Oracle blog [EDIT: since removed] and on this blog. The most interesting part of that was learning how to allow connections directly to my http server at home.

With all that excitement, I’ve managed to mostly keep up with all the blogging out there, which was massively helped with my home-grown RSS reader. It is also an Oracle APEX-driven web site for my private use, it regularly polls all my RSS feeds, downloads them to my computer, and keeps track of which ones I’ve read yet. RSS items that have enclosures (e.g. Rocketboom) are downloaded as well, so when I’m ready to watch or listen to them there’s less delay. At the moment I’ve got some hard-coded rules that automatically mark some items as “not interesting”, but eventually I hope to implement some kind of guided learning so that it will be able to mark new items as “probably interesting” or “probably not interesting” based on my feedback on prior items. Even with the hard coded rules, however, it cut down my reading time by about 50% which is nice. A few months ago the database had over 1,000 unread items; over the last few weeks I’ve managed to whittle that down quite a bit, and when I was sick I read the last few so now I’m fully up to date – e.g. Oracle 11g is on its way! 🙂 I can barely wait to get that installed.

That’s the State Of My Blog(s). I hope you enjoyed that because I normally avoid blogging-about-blogging like the /*TODO: insert cliche*/.


ZFS/Oracle

Zettabyte File System (APC)

Pooled storage, transactional control, snapshots… sounds awfully familiar to me. Oh yeah, features that Oracle have provided in the database for years. 🙂

(I know, very different domain and probably very different implementation (database vs. file system) but some of the concepts are similar.)


“Applications Developer: Soccer or Tetrinet skills desirable”

“Applications Developer – desirable skills: Soccer or Tetrinet”

Job: Applications Developer
Location: Perth – South
Advertiser: Kwinana Software Company
Classification: I.T. & T > Analyst/Programmer
Description: Highly-regarded development house. Build broad & deep skills in Microsoft, Oracle and industrial technologies. Soccer or Tetrinet skills wouldn’t hurt
Link: http://it.seek.com.au/users/apply/index.ascx?Sequence=13&PageNumber=1&JobID=9618584&cid=jobmail

“We have comfy chairs, grunty machines and twin 22” wide-screens on every desk (with webcams, for Skyping between offices).”

Wow.


ORA-06502: PL/SQL: numeric or value error: Bulk bind: Error in define

I came across an inexplicable error when bulk collecting into a PL/SQL table with the NOT NULL constraint the other day. What was confusing was that the code had been passing tests for quite some time.

In the end the only thing that had changed was that a VARCHAR2 which should have been non-null happened to be NULL for one particular row in the table.

Thanks to Connor for the simple test case, listed below.

If you know what might be the cause or reason behind this error, and why it doesn’t occur for dates, I’d be interested.

This was reproduced on Oracle 10.2.0.1.0.

SQL> declare
      type t is table of number not null index by pls_integer;
      r t;
     begin
      select case when rownum < 20 then rownum else null end
      bulk collect into r from all_Objects
      where rownum <= 20;
     end;
     /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: Bulk bind: Error in define
ORA-06512: at line 5

SQL> declare
      type t is table of varchar2(80) not null index by pls_integer;
      r t;
     begin
      select case when rownum < 20 then rownum else null end
      bulk collect into r from all_Objects
      where rownum <= 20;
     end;
     /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: Bulk bind: Error in define
ORA-06512: at line 5

SQL> declare
      type t is table of date not null index by pls_integer;
      r t;
     begin
      select case when rownum < 20 then sysdate else null end
      bulk collect into r from all_Objects
      where rownum <= 20;
     end;
     /
PL/SQL procedure successfully completed.

Table Types Supplied by Oracle

This is a list of all the table types I’ve found in Oracle-supplied packages, e.g. OWA_UTIL in 10g supplies the type:
TYPE datetype IS TABLE OF varchar2(10) INDEX BY binary_integer;

I find them handy for quick one-off scripts.

Oracle_supplied_table_types


Mood Swings

An interesting column comment encountered:

MOOD_SWINGS_IND VARCHAR2(1) (Y/N) “indicates that the person was in a swinging mood at the time of the episode”


AUSOUG Conference 2006 over

Another enjoyable conference. I’ve attended it every year since 2000 and this year’s was packed with presentations. Over 300 attendees spread over up to six presentations meant less crowding, I think; although as always there were a few packed sessions.

Highlights for me were:

  • Connor’s “live demo” of 11g in Being a successful developer with Oracle
  • Learning that cancelling a cursor is a good thing, but finding it can’t be done in PL/SQL – Anjo Kolk, The life of a cursor and its impact on the shared pool
  • Trace Analysis on Steroids – Dave Moore’s talk was an eye-opener, not about performance-enhancing drugs (caffeine’s usually enough for me), but about Trace Analyzer. I thought this would be just another “if you’re not buying our product you’re wasting your time” talk, but in fact this is a totally free, open-source (PL/SQL!) tool that not only collates all the data from a trace file (as tkprof does), but also digs into your database to correlate the trace info with the data dictionary and present it all beautifully in HTML. Downloading and trying out this tool is definitely on my to-do list.
  • Connor again, Odds and ends – an odd but arguably the best session to end the conference with. A number of tricks I’ll want to experiment with once I get a copy of the powerpoints (e.g. I wasn’t aware that contexts can be made “globally accessible”).

Thanks to the AUSOUG committee for another well-organised event.