Friends,
This Ask Tom thread which I found via another SO question, mentions Table and Transactional API’s and I’m trying to understand the difference between them.
A Table API (TAPI) is where there is no access to the underlying tables and there are “getters” & “setters” to obtain information.
For example to select an address I would:
the_address := get_address(address_id);
Instead of:
select the_address
from some_table
where identifier = address_id
And then to change the address I would invoke another TAPI which takes care of the change:
...
change_address(address_id, new_address);
...
A Transactional API (XAPI) is again where there is no direct access to modify the information in the table but I can select from it? (this is where my understanding is kind of hazy)
To select an address I would:
select the_address
from some_table
where identifier = address_id
and then to change it I would call
...
change_address(address_id, new_address);
...
So the only difference I can see between a TAPI and a XAPI is the method in which a record is retrieved from the database, i.e. a Select Versus a PL/SQL call?
Is that it? or have I missed the point entirely?
Let’s start with the Table API. This is the practice of mediating access to tables through a PL/SQL API. So, we have a package per table, which should be generated from the data dictionary. The package presents a standard set of procedures for issuing DML against the table and some functions for retrieving data.
By comparison a Transactional API represents a Unit Of Work. It doesn’t expose any information about the underlying database objects at all. Transactional APIs offer better encapsulation, and a cleaner interface.
The contrast is like this. Consider these business rules for creating a new Department:
Using Table APIs the transaction might look something like this:
Whereas with a Transactional API it is much simpler:
So why the difference in retrieving data? Because the Transactional API approach discourages generic
get()functions in order to avoid the mindless use of inefficient SELECT statements.For example, if you just want the salary and commission for an Employee, querying this …
… is better than executing this …
…especially if the Employee record has LOB columns.
It is also more efficient than:
… if each of those getters executes a separate SELECT statement. Which is not unknown: it’s a bad OO practice that leads to horrible database performance.
The proponents of Table APIs argue for them on the basis that they shield the developer from needing to think about SQL. The people who deprecate them dislike Table APIs for the very same reason. Even the best Table APIs tend to encourage RBAR processing. If we write our own SQL each time we’re more likely to choose a set-based approach.
Using Transactional APis doesn’t necessarily rule out the use of
get_resultset()functions. There is still a lot of value in a querying API. But it’s more likely to be built out of views and functions implementing joins than SELECTs on individual tables.Incidentally, I think building Transactional APIs on top of Table APIs is not a good idea: we still have siloed SQL statements instead of carefully written joins.
As an illustration, here are two different implementations of a transactional API to update the salary of every Employee in a Region (Region being a large scale section of the organisation; Departments are assigned to Regions).
The first version has no pure SQL just Table API calls, I don’t think this is a straw man: it uses the sort of functionality I have seen in Table API packages (although some use dynamic SQL rather than named SET_XXX() procedures).
The equivalent implementation in SQL:
This is much nicer than the nested cursor loops and single row update of the previous version. This is because in SQL it is a cinch to write the join we need to select Employees by Region. It is a lot harder using a Table API, because Region is not a key of Employees.
To be fair, if we have a Table API which supports dynamic SQL, things are better but still not ideal:
last word
Having said all that, there are scenarios where Table APIs can be useful, situations when we only want to interact with single tables in fairly standard ways. An obvious case might be producing or consuming data feeds from other systems e.g. ETL.
If you want to investigate the use of Table APIs, the best place to start is Steven Feuerstein’s Quest CodeGen Utility (formerly QNXO). This is about as good as TAPI generators get, and it’s free.