Database Objects

I need to brush up on my skills to modify columns in tables, create indexes, and create constraints. Just don't get a lot of practice in these tasks. I thought I would write down some notes on these and other Oracle object manipulation commands.

This might be obvious. But you cannot add a NOT NULL constraint to a column on a table with records in it (which don't meet the constraint). When you create a foreign key column, you can set the constraint as DEFERRABLE. It won't be enforced until a COMMIT has been issues, or until you explicitly set the constaint as IMMEDIATE.

You can create an index on a column right when you are creating the table. The command can reference an existing index name. Or more commonly, it can just stick the index creation SQL right in there with the column definition in parentheses.

Function based indexes allows you to store indexes on the values of a function. That way when SQL uses the function, the optimizer will use the index to speed things up.

FLASHBACK lets you recover objects and data. For example you can do this on a TABLE. You could also do this on DML that has transpired. When you do it on a table, it recovers the table from the DROP TABLE command. You can't restore the state prior to when the last ALTER TABLE was issued. You can restore it to a newly named table. Non-bitmap indexes are recovered. Non foreign key constraints are recovered. And privileges are recovered.

The FLASHBACK works because when you DROP TABLE, it gets saved away. See details by querying the USER_RECYCLEBIN view. However if you issue a PURGE, the dropped table will be removed from the recycle bin and you cannot FLASHBACK recover it.

The FLASHBACK can bring a table back to a point in time defined by:
  1. Prior to the DROP
  3. An SCN
  4. A restore point
External tables are a special kind of table. They are read only. The metadata about the table is stored in the database. The data is stored outside the database. You can SELECT from the external table. But you cannot issue DML against it. There are no indexes, constraints, LOB columns or unused columns allowed on an external table.

To use an external table, you must first CREATE DIRECTORY where the file will be located. Then you grant privileges on the directory. Finally you create the table with a special EXTERNAL syntax. You have to specify how the table will be loaded (i.e. SQL*Loader or DATAPUMP). We actually use external tables on our project when we have a file we need to access from database code.

Views, Sequences, and Such

I will be honest. I don't use views all the much. But it is good to know a little about about them. They are SELECT statements that have a name. You access a view just like you would a table. For example, you can DESCRIBE it. There are some scenarios where you cannot do all insert/update/delete operations on a view:
  • If a required field in a table is not contained in the view
  • SQL to create view has GROUP BY
  • SQL to create view has aggregation
  • SQL to create view uses DISTINCT
  • SQL to create view has more than one table (through a join)
I think I have mentioned before that an inline view is when the table section of a FROM clause is replaced by a SELECT statement. Now let's move on to sequences. They are mainly to create values for a primary key. They have properties such as INCREMENT BY and START WITH. You use the pseudo columns NEXTVAL and CURRVAL to get sequence values. Note that you cannot access CURRVAL in a session without first getting the NEXTVAL.

Indexes are objects to make queries run faster. The WHERE clause and ORDER BY clause will specifically benefit from some indexes. They cannot be placed on columns of type LOB or RAW. You automatically get an index for a primary key or a unique column. The optimizer might use an index for almost everything except for NOT EQUALS comparisons. A composite index has two or more columns in it.

Finally synonyms are aliases for database objects. They can be for tables, views, sequences, or even other synonyms. The object referenced does not even have to exist when you create the synonym. But it must by the itme you use it. There are two types of synoyms:
Private synonyms are those created without the PUBLIC keyword. They are owned by the user that creates them. They get precedence over a PUBLIC synonym with the same name. Public synonyms are owned by a used called PUBLIC. The are visible to all users. You cannot ALTER a synonym. But you can CREATE OR REPLACE one.


I use subqueries once in a while. That's why I am not very strong with them. They are going to be on my OCA SQL Expert exam. Time to bone up on my subquery knowledge. There are different classifications (a subquery may fall in more than 1 category):
  • Single row
  • Multiple row
  • Multiple column
  • Correlated
  • Scalar
Most subqueries are categorized by how many rows and columns the subquery returns. The exception is the correlated subquery. It references (correlates with) the outer query. A correlated subquery cannot stand on its own. Here is where you can use a correlated subquery:
By the way, an inline view is when a subquery takes the place of a table in the FROM clause of a SELECT query. Now let's get back to the categories. A multiple row subquery needs special comparisons in the outer query:
  • IN
  • NOT IN
  • ANY (also known by SOME)
  • ALL
Multiple column subqueries take the form in the WHERE clause as follows - WHERE (col1, col2) = (SELECT col1, col2 FROM ... etc). This one does not seem as intuitive. Then there is the scalar subquery that returns a single row and column. There are a number of places you cannot use a scalar subquery:
  • CHECK constraint
  • Function based index
  • DEFAULT value
  • WHEN (from the CASE)
EXISTS checks whether there are any rows in the subquery. If so, it returns TRUE. If not, it returns FALSE. You can also use the opposite which is NOT EXISTS. If you use a SELECT that employs the EXISTS, it is called a semijoin.

WITH allows you to name a subquery block. The named queries act like inline views or temporary tables. The name is valid in all of the statement except in the subquery itself.

All About Joins

There are multiple ways to classify SQL joins:
  • Inner joins match values in all tables
  • Outer joins match even if one table does not have a match
  • Equijoins do an exact match on values
  • Non-equijoins match with comparisons such as "greater than"
There are three types of outer joins:
  1. Left
  2. Right
  3. Full
A natural join will join multiple tables that have the same column names. You cannot provide aliases for the joined columns. This produces an inner join.

Another way to join tables with same column names is to use USING(same_col_name). You cannot prefix the column name with an alias or even a table name. This is similar to the natural join, except that this allows outer joins as well as inner joins.

The self join will join a table with itself. It can be an inner join or an outer join. It can be an equijoin or a non-equijoin.

Finally there is the Cartesian product. It is also called the cross join. This is not very useful. You invoke it with the CROSS JOIN syntax, or SELECT FROM multiple tables without specifying any joins. Be warned that you might get a whole lot of rows with this option.

Scalar Functions and Timezones

I continue studying up for my OCA SQL Expert exam. Today I want to talk about scalar functions. These are also called single row functions. But before we dive into them, I want to revisit DUAL. This is a table specific to Oracle. It only has one column DUMMY of type VARCHAR2(1). That column has the value 'X'. You can use dual when you want to issue a select but do not want to go against any other table.

Now back to scalar functions. An example math scalar function is MOD. It stands for modulus. It is the remainder left over when you divide integers. A similar function is REMAINDER. However REMAINDER will find the closet divisor, possibly going past when evenly divides, and might return a negative number.

How about we talk about timezones? Here are three types:
  1. UTC - Universal timezone, previously GMT
  2. Database - the timezone on the server returned by DBTIMEZONE()
  3. Session - the timezone of the user returned by SESSIONTIMEZONE()
Recall that a TIMESTAMP is a date plus fractional seconds. Well you can also have TIMESTAMP WITH TIMEZONE. This has a TIMESTAMP plus details on the timezone. The timezone info is stored in a UTC offset or a region name. There is also TIMESTAMP WIT?H LOCAL TIMEZONE. This is the time normalized to the database timezone.

The CURRENT_DATE() and CURRENT_TIMESTAMP() functions returns values in session timezone. The FROM_TZ() produces a TIMESTAMP WITH TIMEZONE. So does TO_TIMESTAMP_TZ(). You can use CAST() to change the type. You can EXTRACT() details of a timezone. And you can use AT TIME ZONE to transform a time to a different timezone.

Certification Review of SELECT

Okay. I am reading up every night to study for the SQL Expert certification exam. When you put DISTINCT in your SELECT statement, it operates on sets of columns that you use. It produces the same result as UNIQUE. Here are the different operations that are in play with your SQL statement:
  1. Projection
  2. Selection
  3. Joining
Projection is choosing a subset of columns. Selection is choosing a subset of rows. And joining is combining two or more tables.

A view acts like a table. It looks like a table. Behind the scenes, it runs a SELECT statement to produce its results.

Synonyms are aliases for existing objects. Private synonyms are owned by a schema. And public synonyms are owned by a user named PUBLIC.

The WHERE clause has access to all columns in a table, regardless of whether they exists in the SELECT list. The order of precedence, highest to lowest, of logical operators is NOT, AND, then OR.

If BETWEEN is in a WHERE clause, it is inclusive of the two end points given.

The ORDER BY also has access to all columns in the table. It is always the final part in a SQL statement. It can use alias names for sorting. You can also do positional ordering, the first column being number 1. NULL values always have the highest values.

I really have only one interesting fact about LIKE. The % is only expanded after the LIKE keyword. So don't use it on the left side!

More Certification Review

I took a peek at the different kinds of certification offered by Oracle. There is an advanced PL/SQL certification that might be in my future. However I might also want to get some database administration in there. And I am curious about APEX certification.

The beginner database administration certification seems easy. You just pass a test. But to get to the next level, you need to jump through some hoops. One such hoop is that you need to take a class from Oracle. All formats of training cost the same amount. So if I go this route, I will probably attend a class in person. The problem is that cool classes like hard core performance tuning last five days. And that means they cost $3500. I guess I could get my company to pay. However the price seems a bit high.

Anyway, I am reading up my study guide to pass the SQL Expert certification exam. I learned some details about certain types that cannot be UNIQUE, PRIMARY KEY, or FOREIGN KEY. They are:
  • BLOB
  • CLOB
Those don't make sense to be a primary key. Not sure why they could not be unique, unless their size makes checking for uniqueness prohibitive. Oh well. That's the rule.

Next up I learned that there are six types of SQL statements:
  1. DDL
  2. DML
  3. TCL
  4. Session control
  5. System Control
  6. Embedded
That last one does not feel like a separate type. You can embed DDL or DML in another language. But I digress. I know DDL - things like CREATE TABLE. However I was not as familiar with FLASHBACK and PURGE. That's why I need to study up. FLASHBACK apparently reverts the table or DB to a prior version. And PURGE gets rid of items from the recycle bin. What? Is this Microsoft Windows?

DML is the old INSERT/UPDATE/DELETE. It also encompasses MERGE. I don't use MERGE. It is some kind of combination of the other types of DML, all in one statement. I guess I will be studying that too. TCL is things like COMMIT. I know about ALTER SESSION and ALTER SYSTEM. And I got plenty of experience with embeded SQL by using Pro*C.

Okay. I am up to Chapter 4 in my study guide. 14 more chapters to go and I shall be ready to take the certification test by the end of the month. I will let you know how I fare.

Certified SQL Expert

I saw a perfect position for me at my company. It seemed to be just the kind of PL/SQL developer position I have been searching for. There were a few problems though. One was that the location was on the other side of town. And the other was that they wanted a lot of different certifications.

I am an Oracle PL/SQL Developer Certified Associate. The main reason I got certified was that my company said they wanted people to get certified, and they were willing to pay. So I think I bought some training materials. Went in for an in person class. Then took and passed the test.

The certifications desired for my dream job were ones I had not heard of before. Maybe they are new. I really don't pay too much attention to certifications any more. I think it is time for that to change. So I have been studying the OCA Oracle Database SQL Certified Expert Exam Guide. Got an online copy. I am encouraged that I get most of the answers right at the end of each chapter.

There were a lot of basics that I did not have a strong grasp on. For instance I knew object names were capped at 30 characters. I found that limit the hard way. However I did not know objects need to start with a letter. Also did not know the only special characters allowed in the name are $, _, and #.

Speaking of names, there are objects that are grouped together in namespaces. That is, certain objects cannot have the same name in the same namespace. Here are those namespaces:
  • user, role, public synonym
  • table, view, sequence, private synonym
  • index
  • constraint
We have naming conventions that make sure these things don't cross paths even if they are in different namespaces. But it is good to know the exact rules, especially if you are going to be taking a certification test.

Job Applicant Statistics

I applied to a job a little over a week ago. This was through a site that I normally do not visit. The site tried real hard to get me to pay for a subscription. No thanks. There are plenty of free job boards out there. If they don't work, I still do not think I will pay to find a job.

One strange thing about this site was that it provided statistics on my competition. It did not name any names. But it informed me about the details of the other people who applied for the job I was interested in. Weird.

Here were the different current salaries of the competition:
  • $60k
  • $70k
  • $80k
  • $100k
  • $140k
  • $150k
They were all over the place. Should I be concerned that there were some low ball salaries in there? Nah. Those applicants are probably underpaid. Most applicants had a bachelors degree. But some had a masters.Here are their current titles:
  • Analyst
  • DBA
  • ETL Developer
  • Oracle Developer
  • Project Lead
  • Senior Architect
  • Senior Developer
Those were some nice titles. Finally here are some of the areas of expertise the competition possessed:
  • Banking
  • Consulting
  • Databases
  • Front end development
  • Project Management
Well the competition is fierce as usual. I had better make sure I have enough goodies to set myself apart. I am Oracle certified. Got a lot of years experience. Also have a lot of schooling. I think I know my stuff.

What else can I do to improve my rank? Get some more certifications. I am working on that. Expand my areas of expertise. There are a lot of hot technologies in the Oracle Database universe. The real winner might be reaching out to my network. I have worked so long that I know tons of people out there with an Oracle database background.

Group Functions

A group function will return one row for possibly many matching rows in the table(s) you select from. These are also called multirow functions or aggregate functions. One common example is COUNT(). It returns a single row. Even if there are no rows to select from, COUNT() returns zero.

Then there is the RANK() group function. It will order specified column(s) from first to last. Ties get the same rank, but subsequent numbers are skipped based on how many rows tie.

GROUP BY will put sets together to be treated as a whole. Group functions then operate on these sets. You can combine the ORDER BY with GROUP BY. ORDER BY can contain any expression in the GROUP BY clause, and expression in the SELECT clause, group functions, and USER/SYSDATE/UID.

The HAVING clause will restrict sets of rows from a GROUP BY. It requires GROUP BY. You can use any expression from the GROUP BY, or any group functions in the HAVING clause.

Little Bit of Large Objects

The system I work on makes small use of large objects in the Oracle database. We send letters for faxing companies. The letters are signed with an image of the sender's signature. Those signatures are bitmap images stored as LOBs in the Oracle database. Let's see what the latest book I am reading has to say about large objects.

Prior to Oracle 8, large objects were represented by the LONG and LONG RAW types in the database. There could be at most one column of this type per table. The data was stored inline with the other columns in the table.

Now we have two general types of large objects (LOBs): internal and external. The internal variety are stored in the database in tables. Examples of this are the CLOB, NCLOB, and BLOB. I am most familiar with the BLOB. You can manage these objects with the DBMS_LOB built in package.

Then there are external LOBs. An example of this is a BFILE. The data is stored on disk. And the access to the data is read only. I don't recall ever working with external LOBs. Maybe it is time for a small practice project with them?


I am still reading "Oracle Advanced PL/SQL Professional Guide". This book really stresses the different types of collections. So let's get down to business. Collections contain elements of the same type. They are stored in memory in either the PGA or SGA. Some types can also be stored in the database. Here are the collections Oracle has to offer:
  1. Associative Arrays
  2. Nested Tables
  3. VARRAYs
Associative arrays were originally called PL/SQL tables. Then they were called index by tables. Now I guess they are associative arrays. These I used to use a lot in data correction scripts. Not so much any more. You index the array by either a number or string. It can be a sparse collection. You define a type for the associative array like TYPE my_assoc_type IS TABLE OF VARCHAR2(4) INDEX ?BY BINARY_INTEGER.

Next you have nested tables. Indexes are numeric and start with 1. These start out as dense collections. But they could get sparse if you DELETE an item. This type of collection can be stored in a database. When you do that, the data for columns of this type is stored out of line. You can initialize the collection with a constructor. And you can define a collection of this type like TYPE my_nested_type IS TABLE OF VARCHAR2(4).

The VARRAY is like the nested table. It also has numeric indexes which start at 1. You can store collections of this type in a table. Unlike nested arrays, columns of this type in a database table have the collection stored inline. The result is better performance than nested tables in database tables. This collection type is always dense. While you can DELETE from a VARRAY, you must DELETE all items in the VARRAY. You can define a collection of this type like TYPE my_varray_type IS VARRAY(10) OF VARCHAR2(4).

Here are some functions that work on collections:
  • LAST
  • NEXT
  • EXTEND (nested table or VARRAY only)
  • TRIM (nested table or VARRAY only)

All About Cursors

I have been studying my "Oracle Advanced PL/SQL Professional Guide" to prepare for a technical interview. There was a lot of information on cursors in the book. That is good since I use cursor a lot. But I normally only use a specific style of cursor.

To start with, you can define a cursor in the declaration section. If it needs any parameters, you pass it a list in parentheses almost like you do a function. Then you OPEN the cursor, passing in any parameters in parentheses. You can then FETCH the cursor into your variables. And before doing a CLOSE on the cursor, you might be checking any of the cursor attributes:
  • %FOUND
Normally you will check %NOTFOUND to see if you are at the end of the result set. You can always access the %ISOPEN attribute on a cursor. However the others will throw an exception unless you are accessing them between the OPEN and CLOSE of the cursor.

When using a FORALL cursor, there are the additional attributes %BULK_ROWCOUNT and %BULK_EXCEPTIONS. Most of the time when you define an explicit cursor, you have the cursor name that you prepend to the attributes. However you could do an implicit cursor by executing a SELECT statement. In that scenario, you can still check the attribute, but you use the term SQL instead of the cursor name. For example, you can check SQL%ROWCOUNT.

Then there is my good friend the ref cursor. I actually don't use these very frequently. My cursors are created and used in a procedure or function. I don't pass cursors around to other procedures. But if you had to, you could use a ref cursor. It is, as the name implies, a reference to a cursor. There are two types: strong and weak. Strong ref cursors have a fixed return type in the prototype. Weak ref cursors can be used for any SELECT statement. There is also a generic SYS_REFCURSOR which is a weak ref cursor.

The book goes on at length about collections. However that warrants its own separate post.

Back to Basics

I had a technical interview set up for today. It was for a senior PL/SQL developer position. Figured I would brush up on some Oracle knowledge. So I pulled out a copy of my eBook "Oracle Advanced PL/SQL Professional Guide". Strangely enough, there was a lot of basic information in there that was good to review.

For example, DUAL is actually a table owned by SYS. I just considered it a virtual scratch pad table area. But it is a real table. It only has one column called DUMMY of type VARCHAR2(1). Furthermore, that table has exactly one row with a value of "X".

I reviewed the syntax to create a package. There is no BEGIN keyword in declaring the specification. Just an END. The package body has an optional BEGIN-END pair. But that is for a one time initialization set of code. It executes once the first time your session accesses the package. I have actually used this feature a time or two.

Now a bit about types. I know that NUMBER is an Oracle type. INTEGER on the other hand, is an Oracle subtype of NUMBER. You can define your own subtypes. Not that I do that much.

There were a bunch of tips on getting better performance. Some were not intuitive. Try to do your operations in a single SQL statement.Avoid the use of implicit conversion. I am all behind that. Implicit conversion just feels like sloppy program to begin with. Do not define your variables as NOT NULL.

Huh? You would think limiting a variable to NOT NULL might help performance. Nope. For those variables, Oracle has to do extra work to keep checking if the thing is getting set to NULL. Use PLS_INTEGER for math operations. And of course, use BULK COLLECT and FORALL when dealing with collections.

Thinking About Triggers

I got my Oracle 12c database up and running. Time to start developing. Put together a small script to create a few tables. Also created sequences to populate the IDs in the tables. I thought I would get automated and have insert triggers on the tables setting the ID values. Sweet I thought.

Went through a couple iterations until I got the basic table definitions the way I wanted. Then I coded up a procedure to insert records into the tables. Something strange was happening though. The IDs were not getting set. I thought I manually tested the triggers from the SQL*Plus command prompt.

Turns out my trigger became invalid when I kept dropped and recreating the tables. Easy enough to fix. Just recompile the triggers. Then I did some philosophical thinking about my setup. I insert a new row of data. The trigger populates the ID. How do I then find out what that ID is if I want to insert it as a foreign key in some table?

In the old days, I would let my procedures explicitly generate the IDs. That way I had the ID before the INSERT, and I could then use the value I stored in a variable to use as foreign keys. Now that the IDs are set automatically in triggers, I got to query the database after the fact. There has to be a better way to do this. Any ideas?

Pluggable Databases

I had installed my Oracle 12c database. Then I logged into Enterprise Manager with the SYSTEM account. I tried creating a user. This is what I got back:
SQL Error
Error signaled by database server
ORA-65096: invalid common user or role name
ORA-06512: at "SYS.PRVTEMX_ADMIN", line 8565
ORA-06512: at "SYS.WRI$_REPT_SECURITY", line 288
ORA-06512: at "SYS.DBMS_REPORT", line 898
ORA-06512: at line 1
What? At first I thought something was broken with user creation. Then I paid closer attention to the ORA-65096. Okay. I need a more complicated username. Nope. That was not the problem. Finally I broke down and Googled the subject.

Apparently there is some new magic going on with Oracle 12c. The username needs to start with C##. I should have known something was up when the default username in Enterprise Manager when you create a new user is C##.

This has something to do with the Oracle 12c multitenant architecture. That is somehow connected to pluggable databases as well. Those are not terms I am familiar with yet. I did see online that there were some hacks I could apply that would let me name usernames the way I want. Time to get hacking.

Apex Redux

As I was getting ready to install Oracle 12c, I pondered whether I should try to install APEX. Did a bit more research into what APEX is. Obviously it stands for application express. It is a rapid web app development tool. You need an Oracle database running application express. It is normally installed along with the database.

APEX is data in a bunch of tables plus some PL/SQL code. Since it is web based, you specify a URL which gets translated to an APEX PL/SQL call. Results are sent back in the form of HTML. Each request uses a separate database session.

There are two models that APEX can run under: the three tier model and the two tier model. Here is the three tier model:
  1. Web browser
  2. Oracle HTTP server with mod_plsql
  3. Oracle database with Oracle APEX
The second item could be replaced by an APEX listener. Then there is the two tier model:
  1. Web browser
  2. Oracle database with embedded PLSQL gate plus APEX
In APEX, a workspace is where you develop apps. It is a virtual private database. If you are not ready to install APEX on your machine, Oracle does have a hosted environment. When you first log into APEX, you arrive at your workspace home page. Application Builder is used to put your HTML interface together.

There are some sample objects available. One is Human Resources (HR) and another is Order Entry (OE). I think I will just stick with my Oracle database 12c for now. There will be time to play with APEX in the future.

Users Galore

I had installed Oracle 12c on my laptop. It informed me that Enterprise Manager was accessible using this link: https://localhost:5500/em.

Before I could run over and log in with Enterprise Manger, I decided to click the Password Management button at the end of the database install and configuration. There were a ton of accounts that got created for free with the database.

The only two accounts that were unlocked by default were SYS and SYSTEM. I always wondered what the difference between these two were. They are both real users with schemas. SYS owns the data dictionary tables. I guess SYSTEM is one I should log onto first to create my real daily user?

One thing I do know is that these are unlike SYSDBA and SYSOPER, which are actually roles and not users. The real surprise was the tons of other users that got created by default. I left all those user accounts locked by default. Here are the multitude of accounts:
  • XDB
  • APEX_040200
  • DVF
  •  SYSDG
  • DIP
Those were a lot of users. Some of the names were chosen well so I have an idea of what they are used for. I will have to do some Internet research to find out more. For now I tried logging into the database. At first it kept complaining that my username/password were wrong. Took a while to figure out that I had the caps lock on when I typed in the passwords for SYS and SYSTEM.

In Enterprise Manager, I went over to Security|Users to create my first user account. Now we are cooking with gas. I think I am going to have some fun with this database. Already got a few applications that I need written.

Oracle Install

So I downloaded this 3G Oracle Database 12c installation. And the Universal Installer would not run. I was not going to run around trying to install the required Java Runtime Environemt. I already have that on my machine. Maybe the location could not be detected. Therefore I did what any anxious developer would do. I restarted the install.

This time around it worked. That's when I arrived at Step 1 of 10. Had to decide between a desktop and server class. Well my little laptop is definitely the desktop variety. Then I was given the chance to specify the Windows user for the Oracle home user. I just chose a built-in account. That might be a security risk in the production world. But this is just my throw away database.

There was a drop list choice for the installation type. However the only option in it was the Enterprise edition. Good enough for me. The global database name was defaulted to "orcl.home" which I accepted as is. For some reason I decided to save my response file. You never know when I might want to do an unattended install with the same set of options.

Here were the steps for the database install:
  1. Prepare
  2. Copy files
  3. Setup
  • Setup Oracle base
  • Oracle Database configuration
Yeah. Steps one, two and three. Then some other steps. Somebody has their numbering mixed up. I swear it is not me. Finally after leaving the thing run all night, my database installation was complete. My SID was orcl. That was the default name I chose. I got a URL to run Enterprise Manager Database Express. Watch out world. Here I come.

Orale 12c Baby

Yesterday I decided it was time to install Oracle on my laptop. I downloaded Oracle Database 12c Release from Oracle. The 64-bit Windows edition requires two zip files to be downloaded. They were 1.5G each in size.

If you want to program with Oracle components, you will need one of the following versions of Microsoft Visual Studio:
  • Visual C++ 2010 SP1
  • Visual C++ 2012
  • Visual C++ 2013 Update 2
Note that the VC++ 2013 does not work with Pro*C yet. Here are some components that you can use if you have the right development environment from Microsoft:
  • Oracle Call Interface
  • Pro*C/C++
  • XDK
Somewhere I read that I would only get a 30 day evaluation. What? I want a free version of Oracle that I can play around with indefinitely. But for now, 30 days will work. I ran the setup.exe program. It launches a command prompt style window. That in turn launches the Oracle Universal Installer.

Oops. The Universal Installer would not run on my machine. It complained that the Java run-time was not found at "bin\jawaw.exe". I was directed to go to to install the JRE version 1.4 or higher. Umm I thought the installer was supposed to install Oracle's own version of the JRE.

Oracle 12c New PL/SQL Features

Now let's see what Oracle 12c has in store for PL/SQL and database changes. The RESULT_CACHE has been improved. You can now use it with functions that specify invoker's rights. The WITH clause can define a PL/SQL function that you can call directly from SQL without a PL/SQL context switch. It can also be used to get access to a constant from a package.

ACCESSIBLE BY will allow you to specify packages that can access your newly defined package. You cannot call this newly defined package directly. But the packages on the "white list" can. This allows you to define helper functions that have restricted usage.

You can now grant roles to program units. That is, grant them to packages, procedures, and functions. Then you can use invoker's rights on them. They can get the privileges they need through the roles. You can bind PL/SQL types such as BOOLEAN to SQL. FETCH FIRST let's you limit the number of rows that return from a query.

BEQUEATH_CURRENT_USER let's you specify a view to have invoker's rights. Invisible columns can be created when you specify INVISIBLE during the DDL. They can only be seen if you explicitly name them. DESCRIBE does not see them. Neither does SELECT *. However %ROWTYPE knows about them. They have no column order. Strangely enough, that can be mandatory columns.

The UTL_CALLSTACK package contains routines previously found in DBMS_UTILITY. Then there is the EXPAND_SQL_TEXT in the DMBS_UTILITY package that expands view queries to their base tables. You can ENABLE_DDL_LOGGING. This is an init param. All DDL will now be logged in an XML file. It can be activated at the database or session level.

Temporary undo can now be stored in a temporary table instead of the undo tablespace. You can now issue a TRUNCATE TABLE CASCADE to get rid of tables plus those that depend on the table you are truncating.

Oracle 11g New PL/SQL Features

All right. We are now at the point where I am learning features of the current Oracle database we run in production. There is a DBMS_UPDATE_PARALLEL that let's you group sets of rows into chunks. Then you can update the chunk for performance gains. Regular expressions get a new REGEXP_COUNT method.

You can use CURRVAL and NEXTVAL in PL/SQL without having to SELECT them from DUAL. You get all kinds of options for specifying parameters in function/procedure calls. You can still do the old positional method. But you can also do the named method. Or you could combine positional and named in what we call a mixed style.

Big news. There is a RESULT_CACHE directive you can put at the end of a function declaration. Results of the query get cached in the SGA. This can speed things up considerably. There are some limitations:
  • Does not work in an anonymous block
  • Does not work with invoker's rights
  • There can be no OUT parameters
  • The function cannot access a data dictionary
  • The function cannot access a temporary table
  • The function cannot access a sequence
  • The function cannot access a SQL function
  • No parameters can be any type of LOB
  • No parameters can be a REF CURSOR
  • No parameters can be a collection
  • No parameters can be an object
  • No parameters can be a record
  • Return type cannot be any of these prohibited parameter types either
Whew. That was a lot of restrictions. I am sure there are good reasons for them.  Now back to the new stuff. FOLLOWS can be used when defining triggers to set the order of triggers on the same table at the same firing point. PRAGMA_INLINE can inline a subprogram go speed.

New types SIMPLE_INTEGER, SIMPLE_FLOAT, and SIMPLE_DOUBLE are what you would expect. They have the added restriction that they cannot be NULL. CONTINUE can be used to move to the next iteration in a loop. Compound triggers can put triggers for more than one firing point together. This let's you share code and data between them. They all have to be DML triggers. You can only GOTO code in your own section. Other restriction that make sense are that :NEW can only be changed BEFORE EACH ROW. And :OLD and :NEW cannot be referenced in the before and after statement triggers.

There is a new syntax to specify the parent you inherited a method from. It looks like (SELF AS my_parent).my_method(). FORALL can not reference specific elements in collections. This can be done in the SET and WHERE clauses. LISAGG is a new built in function that does string aggregation. That is, it can turn values from multiple rows into one big concatenated row.

COLLECTION improvements have been made. You can CAST to a specific type of collection. You can order the elements in a COLLECTION. You can specify that the collection has only DISTINCT values in it.

Virtual columns can be added to tables. This let's you store an expression in something that behaves like a column. Syntax involves GENERATE ALWAYS AS ... VIRTUAL during column definition. It can be index. It can be part of a constraint. This makes it act like a view.

Hey. PIVOT is a new keyword to transpose rows to columns. This is good for applications such as reports. It is an aggregate operation. There is a reverse UNPIVOT that transposes columns to rows instead.

Oracle 10g New PL/SQL Features

I am on a mission to learn what new features were added to PL/SQL over the years. Now onto what was new in Oracle 10g. There are new BINARY_FLOAT and BINARY_DOUBLE types. They adhere to the IEEE definitions. FORALL let's you transfer data in sparse collections to the database. Use the keywords INDICES OF or VALUES OF.

Regular expressions can now be used in SQL queries. Here are the functions:
Nested tables have some improvements. They support multiple set operations. For example, you can use EQUALS, UNION, INTERSECT, and EXCEPT on them. Collections can also be assigned to other collections. There is a user defined quote character. You choose the character. It cannot appear in your string. When you use it, single quotes can be in the middle of your string.

 A new UTL_MAIL package sends mail programmatically without having to know the low level details of the SMTP protocol. A new UTL_COMPRESS package lets you zip and unzip data. It works with RAW/BLOB/BFILE types.

There is now conditional compilation of PL/SQL. You can get the current version with DBMS_DB_VERSION. Then you can use conditional $IF expression $THEN statement syntax. There is also $ERROR handling.

DBMS_DDL allows you to hide PL/SQL source code from users. Use the CREATE_WRAPPED keyword. The PLS_INTEGER grows in size to match BINARY_INTEGER. Implicit conversion can now be done between CLOB and NCLOB. Watch out for performance implications though.

DBMS_UTILITY gets the FORMAT_ERROR_BACKTRACE method to print out the call stack during exception processing. COLLECT is a new group function that gathers GROUP records and rturns them in a collection. You can write and read external tables.

Oracle 9i New PL/SQL Features

In my day to day job, I usually employ PL/SQL features that have been around since the old days. I am talking about Oracle 8 here. It is not that I don't occasionally see features recently added. But I just don't have them in my repertoire. I think I got Oracle certified around the time that Oracle 9i came out. Specifics for 9i were not on my test. So I probably never studied them.

Now I am looking around for my next gig. I want it to be a database development job. Specifically I want to be an Oracle developer. So I had better know what is new. I use the term "new" loosely. Well let's pick up where I left off. What was new way back when Oracle 9i came out?

There is a new DBMS_METADATA package that can extract object definition. It will output XML or DDL. Your choice. Then there are the ANSI-standard CASE statements and expressions. The UTL_RAW package can convert to and from NUMBER and BINARY_INTEGER. There is a web version of SQL*Plus called iSQL*Plus.

You can insert a full row into a PL/SQL table now. You can create collections that are indexed by a VARCHAR2. They become hash tables. You can override an object's default constructor with your own code. The TREAT keyword allows you to specify which method you have inherited gets executed.

TIMESTAMP is a new type with fractional seconds. "Table Functions" produce a collection of rows. The result can be queried like you query with SQL. An example of the product is a nested table or VARRAY. Speaking of nested, you can nest collection types now. For example, you can have a PL/SQL table of PL/SQL tables.

You can do bulk fetches with native dynamic SQL (EXECUTE IMMEDIATE). There is a MERGE command which combines insert and update. This is something that is allegedly important for data warehousing.

Storing XML in the Database

Previously you could store XML in a CLOB data type. Then you could use DBMS_LOB to get at parts of the XML. This had the advantage that the original XML format was saved. However, the database did not know anything about the structure of the XML document in the CLOB.

The XMLTYPE was introduced in Oracle 9iR1. This allows the database to natively support XML. The type is treated as a user defined type with built in functions that operate on it. Therefore you can use it in SQL just like any other user defined type. The SQL can query parts of the XML document. You can use the type for column data types. You can use it in PL/SQL as types. It supports XML Schema.

There are different ways that XMLTYPE can internally store the data. However it is stored, an XML DOM tree structure can be constructed on demand when the need arises. Here are some options on how the XMLTYPE can internally store the data:
  1. As a CLOB
  2. Object Relational
  3. Binary XML
CLOB format keeps the original XML document format. Performance is decreased. Object relational format will shred the XML. White spaces get removed. Performance is increased. The binary XML storage option was added in Oracle 11g. The XML gets parsed first then stored in binary form.

If you want to get a some parts of the XML, you can use the extract() function. Pass it an XPath string. It will give you back an XMLTYPE. Or you can use the extractvalue() function. It too takes an XPath string to specify the piece of XML you want. It however returns a scalar value.

OEM and Grid Control

First there was Oracle Enterprise Manager Database Control. This is known as OEM. It controlled a database. You view it in a singe window. It is web based. Was historically good for new Oracle features. It is easy to set up.

Next there was Oracle Enterprise Manager Grid Control. This allows you to manage many databases, application servers, and other products. The Grid Control resides on a separate server and has its own database. You can monitor Oracle infrastructure. You can also monitor non-Oracle items such as:
  • Other databases
  • Web servers
  • Application servers
  • Firewalls
  • Operating systems
Grid Control reduces your costs. It reduces complexity. There are a couple components that make up the Grid Control:
  1. Oracle Management Servive
  2. Oracle Management Agent
  3. Oracle Management Repository.
The agents run on the things being managed. There is a separate server that manages all these agents. And the information is stored in a database (repository). Grid control lets you perform system monitoring. You can view server alerts. You can set up notification rules. This allows you to detect performance problems.

To simply monitoring, you can combine single components into groups. Then you can monitor the whole group as one. You can automate administrative tasks. You can publish customized reports. These reports can be HTML based. You can manage Oracle patches. The Grid Control is extensible through management plugins.

Data Masking

We test the application on our project using a development database created by scrubbing production data. That original scrub happened over 10 years ago. Our development data is starting to get a bit stale. It gets updated every year to try to keep pace with the new dates. But formats and structures change. This sounds like a job for Oracle Data Masking,

Data Masking is an add on pack for Enterprise Manager. It allows you to meet data privacy and data protection mandates. It replaces sensitive values with realistic replacements. Thus you can use production like data for non-production uses.

Data Masking can actually scan for sensitive data. It can make sure sensitive data does not leave the production environment. Its operation is also called scrambling or anonymization. The scrubbing is based on rules that you set up or choose from some preset formats.

Here are the data type supported for scrubbing:
  • Numeric
  • String
  • Date
  • LOB (requires Grid 11gR1)
These are the overall steps you take to perform the data masking:
  1. Clone production to a staging environment
  2. Select mask definition in staging
  3. Clone the masked staging data to a test environment
The predefined mask formats allow you to generate random numbers for replacements. You can also do some post processing to ensure the data is of believable format. Masking is controlled by the DM_FMTLIB package. Here are some presets for well known data types that are supported:
  • Credit card numbers
  • ISBN numbers
  • UPC codes
  • Social Security Numbers
  • Phone numbers
 Here are the roles you need to perform a masking operation:
  • Select catalog role
  • Select any dictionary
  • Execute privileges on DBMS_CRYPTO
Be aware that masking partitioned tables might cause some partition movement if you mask the partition key. There are some types that are not supported by masking:
  • Clustered tables
  • Object tables
  • XML tables
  • Virtual columns
Masking can happen quickly because of the following optimiations:
  • Bulk operations
  • Disabled logging
  • Running in parallel

Oracle Spatial

Oracle has support to location enable application. This is called Spatial. It was named Oracle Spatial since Oracle 8. And it is now called Oracle Spatial and Graph since Oracle 10g. Spatial consists of functions and procedures for quick spatial data access and analysis. The code is available in the MDSYS schema.

Spatial defines a number of geometry types:
  • Point
  • Line
  • Polygon
  • Arc
  • Circle
  • Rectangle
Spatial allows you to deal with height and depth data. Or it can represent longitude and lattitude data. This is application to a Geographic Information System (GIS) application. It allows you to project this data onto a two dimensional surface.

The basic building block in Spatial is an element. Types, like mentioned before, are point, line, or polygon. Many elements make up a geometry. And a collection of geometries is a layer.

Spatial allows you to perform an area of interest query. There are two tiers to its query model: (1) primary filter, and (2) secondary filter. To help speed querying, a concept of a spatial index has been created. This is a logical index. There are two types. The first, which is the default, is the R-tree. It uses a minimum bounding box. The second is the quadtree. It uses a technique called tessellation. Each rectangle is chopped into smaller rectangles.

Oracle Label Security

There are many ways to lock down data access in Oracle. A low granularity technique is one we use on my project. That would be the Discretionary Access Control (DAV). With this you pretty much determine whether users have SELECT/INSERT/UPDATE/DELETE privilege to any given table. The users can either do those operations, or they cannot.

The Virtual Private Database (VPD) technology takes security to another level. You get more control. Specifically you decide which rows any type of user is allowed to see. I have written about VPD before. Now I want to talk about Oracle Label Security (OLS). OLS is built upon VPD. But unlike VPD, which requires you to write an access function in PL/SQL, OLS runs "out of the box."

Out of the box means you don't need to do any programming to use OLS. You can set up what you need using Oracle Enterprise Manager. You can create labels. Assign labels to rows. And also assign labels to users. Also you can use Oracle's policy manager tool.

As you can imagine, OLS was originally created to server government applications. Specifically it was meant to address Department of Defense security needs. However OLS must have been a hit. Because now it is also being used in the commercial sector.

The high level idea is that users can have labels associated with them. Specific rows of specific tables can also have labels applied to them. When a table is accessed by a user, the labels of the user and rows are compared. If the labels match, the user gets access. This label information is stored in a new column added to the table for access purposes.

Although I have heard it different ways, more people report that OLS does not come installed by default in the Oracle database. If so, you must use the Universal Installer to add it in. You also need to configure the LBACSYS account that gets installed with OLS. You must unlock it, set its password, and grant it SELECT ANY DICTIONARY.

Recovery Manager

Oracle has had the Recovery Manager (RMAN) since Oracle 8. It is installed along with the database. RMAN is a database client. The client can be run from the command line or Enterprise Manager. One main feature is cross platform backup and restore. RMAN automates a lot of the administration of backups. It can do point in time table recovery. It also can detect corruption in backups.

RMAN backups are stored as backup sets. It can do incremental as well as full backups. RMAN works with a media manager. That would be the system that controls the devices where backups are stored. For example, one media manager might control your tape drive.

An important facet of RMAN operation is the recovery catalog. This is a database schema where RMAN activity is recorded. It tracks the file names of all database files. It stores the location of redo logs. It can be used if the control file is lost.

RMAN is started by running the rman executble. You CONNECT TARGET to log into a database. The user needs SYSDBA privileges, although you do not explicitly state AS SYSDBA. The BACKUP command will start the backup. Unique file names are generated for backup files. The files are proprietary and specific to RMAN only.

You can do a hot backup while the system is running. The database must be in ARCHIVELOG mode. This results in what they call an inconsistent backup because it will require redo logs. Backups can be full or incremental. Incremental backups start at level 0 which is equivalent to a full backup. The VALIDATE command checks whether there is any backup corruption.

You can put RMAN commands in a file. Run it with the @ sign, just like SQL*Plus. Use the LIST BACKUPS for a report. Or use the REPORT command for a more comprehensive report. DELETE will explicitly get rid of old backups. Any backups older than the retention period are automatically deleted. Recovery involves a RESTORE DATABASE along with a RECOVER DATABASE command.