In a perfect situation, when we need to display an inline image inside an Apex report, we might simply pick the BLOB column and apply the special formatting required in these cases, I mean that weird format mask containing a list of column attributes separated by colons where each member represents a column name in the table being queried:
SELECT ... dbms_lob.getlength(thumbnail) as image,
... FROM image_table...
The format mask specified in the column attributes of the report is something like:
Note also the call to dbms_lob.getlength that for some reason is still NOT properly documented and it is absolutely necessary to make work this type of reports otherwise you will incur into the rather obscure error message when you try to run the report:
report error: ORA-06502: PL/SQL: numeric or value error: character to number conversion error
But as I said, sometimes we are not in a perfect situation.
We might have some rows with an image and some without images.
How do we display an alternate image in case the BLOB value is null?
SELECT ... nvl2(thumbnail, '<img src="'||APEX_UTIL.GET_BLOB_FILE_SRC ('P4_X',id)||'" />', '<img height="72" src="#IMAGE_PREFIX#1px_trans.gif" width="72" />' ) as image,
the SQL above displays the BLOB image stored in image_table only if the value is not null (it might still be an empty BLOB, but that's another story and you'd better to avoid this further annoyance), otherwise it displays a transparent image that you could replace with anything that suits better your needs, say an icon with a question mark or whatever.
Now, the problem with a report column defined in a SQL statement like this is that you can no longer use Apex's built-in report image formatting, but you need to add some additional pieces here and there.
The first requirement comes from APEX_UTIL.GET_BLOB_FILE_SRC itself: the first parameter must be the name of a page item (P4_X in the code above), type FILE BROWSE, containing the format mask specifying a list of columns, similar to the picture above, but without the Blob table.
Now, where does Apex take the name of the table if it doesn't ask me to specify one here?
It will be soon clear as you try to run the page, because it will throw the following run-time error.
Error: No corresponding DML process found for page 4
Contact your application administrator Technical Info (only visible for developers) is_internal_error: true apex_error_code: WWV_FLOW_NATIVE_ITEM.NO_DML_PROCESS_FOUND component.type: APEX_APPLICATION_PAGE_ITEMS component.id: 2568302329371214 component.name: P4_X
This means that Apex is expecting to retrieve the name of the table from a built-in Row Fetch process where you specify the table name and it's primary key(s).
But wait a minute, I am not using a built-in Row Fetch in this page because I am running a report.
Never mind, you can create a *fake* Row Fetch process by specifying never as a condition in the process attributes.
After adding the fake Row Fetch process, the report will magically start working.
However there is one last refinement to be done:
the FILE BROWSE page item we added is probably undesired, visually speaking.
If that is the case, you need to add something like style="display:none;" in the HTML Form Element Attributes to hide it from the user.
I wish we could have a more streamlined version of APEX_UTIL.GET_BLOB_FILE_SRC in a future release of Apex such that we could supply all the necessary parameters without having to resort to this kind of tricks.