Thursday, July 17, 2008

Oracle Magazine?

I ran across a new magazine, Oracle Journal by sys-con. It must be very new because while browsing around the site, I was unable to actually find any Oracle content. It has three news stories (paragraph long news blurbs actually) that are repeated at least 4 times on the page that I can see.


It is an interesting concept. I like Oracle magazine but it is published by Oracle. There's a certain conflict as far as hard hitting news goes. But for a magazine to work, it actually needs content, not just ads. I wonder if they need a writer? I could do some articles for them. Hmmm. Worth thinking about.


LewisC




Technorati : , ,

Wednesday, May 28, 2008

Oracle RAC and Grid Q&A With The Experts

LewisC's An Expert's Guide To Oracle Technology


Q&A about RAC and Grid with the RAC Experts




I recently got the opportunity to sit down and talk to two RAC gurus and learn what RAC is and how it relates to Oracle's Grid technology. Listen to the discussion with Philip Newland and Scott Jesse, both from Oracle Corp. Philip is a technical manager with Oracle's RAC Pack team and Scott is an Oracle Support Services Manager for the RAC Assurance Team. Scott is also the co-author of two Oracle Press books, "Oracle9i for Windows 2000 Tips & Techniques" and "Oracle Database 10g High Availability with RAC, Flashback & DataGuard".


There were plenty of questions asked and answered. Here are five important questions. Listen to the podcast to hear the rest.


What does Oracle mean by Grid?


An Oracle Grid allows you to add computing capacity, CPUs or storage, on demand as needed without pre-purchasing monolithic hardware. On an Oracle Grid, you can add capacity one cheap PC at a time.


There is no product for sale called Oracle Grid. You can't just walk into a store and buy a grid. Oracle Grid is a technology composed of several innovative Oracle products.


What components make up an Oracle Grid?


RAC


Oracle Real Application Clusters (RAC) allows Oracle customers to add database capacity (by adding servers) to an existing cluster. RAC allows a database to be spread across multiple servers. You can dynamically add and remove nodes (servers) as required.


RAC allows an application to transparently scale, add performance and be available 24/7. RAC can be very affordable to scale because it allows you to add cheap servers when you need them.


ASM


Oracle Automatic Storage Management (ASM) eases storage management by abstracting file systems to where DBAs need them. ASM also allows consolidation of storage so that applications that need storage have it available when they need it.


Clusterware


Oracle Clusterware provides the intelligence for a cluster. A cluster is a series of servers acting as a single entity. Clusterware provides the management and monitoring of a cluster.


Oracle Clusterware is not limited to providing scalability and high availability for Oracle Databases. With Oracle Clusterware, you can provide these services for third-party databases, application servers and pretty much any other kind of application.


Cluster File System


Oracle Cluster File System (OCFS & ACFS2) allows an Oracle database cluster to share disk across many servers. OCFS ensures that Oracle sees a consistent image of the disks on each server.


Does RAC work with Oracle Standard Edition?


Oracle Standard Edition, the edition of Oracle for the SMB market, comes with a license for a 4 node RAC cluster. A standard edition license allows up to 4 CPU sockets in a cluster. Those 4 sockets may be in a single server or in two, three or four servers. As long as your cluster does not exceed 4 sockets, RAC is included as part of your Standard Edition License.


Standard Edition does not limit the size of your database in anyway so as long as the processing power for a four socket configuration suits your needs, this can be a great way to save. If you need to scale to a larger cluster, Standard Edition can easily be upgraded to Enterprise Edition allowing you up to 1000 nodes.


Standard Edition RAC configurations are required to use ASM. Because ASM saves time and effort, this is not really a limitation but more of a method for Oracle to help you ensure your success.


How do I monitor my Grid?


Oracle provides both DB Control and Grid Control for monitoring and managing your databases. DB control is a web based tool that allows you to manage one database at a time. Oracle Grid Control allows you to manage entire grids and is an add on package. Grid Control can simplify all of your grid management tasks.


Can I mix and match hardware?


Yes. Oracle expects that vendors are improving hardware constantly and that customers will need to upgrade hardware over time. Rather than force customers to maintain a single vendor or configuration, Oracle RAC will work across various hardware configurations. While one server may be a single CPU and 4GB of RAM, another server in the same cluster can be 4 CPUs (with dual cores) and 16GB of RAM.


The only requirement is that the Operating Systems must match: Windows to Windows, Linux to Linux, 32 bit to 32 bit, etc.


Summary


Grid Computing - Oracle allows you to scale by tying together cheap hardware in a cluster allowing multiple servers to act as one. Oracle provides the software that enables database grids (via RAC) as well as storage grids (via ASM and OCFS). Oracle's Grid allows a business to start as large or small as they need, spending money on hardware and other system resources only when it is actually needed. RAC and Grid is transparent to the application allowing painless and immediate scaling when required.


I think this is one of my better podcasts. Check it out.


LewisC





Del.icio.us : , , ,

Friday, May 23, 2008

When to use Triggers (and when not to!)

LewisC's An Expert's Guide To Oracle Technology


By request, this entry will discuss some issues surrounding DML triggers. Triggers are a nifty feature. When you need them, they are very useful. They can also make maintenance and debugging an absolute nightmare.


API vs Trigger Approaches


I am an API style programmer. I do not mean that I put all of my logic in INSERT/UPDATE/DELETE procedures for each table, although that is not a bad idea. What I mean is that I tend to write functional packages and those packages deal with DML.


As an example, let's say I have an HR system. I have a People table, a Job table, a Pay-Scale table and an Assignment table. Jobs have pay scales and the Assignment table associates a person to a job. All of the tables sequences for primary keys and all tables use database defined referential integrity.


I would have an API for Jobs. That API would deal manipulating Jobs and Pay-Scales. The insert code would select the PK sequences.


I would have an API for adding people. An Employee MUST have an assignment (that is kind of what defines an employee), so the Assignments table is also manipulated in the People API. A person can change Jobs (get a new assignment), be separated (remove the assignment), etc. If for some bizarre reason I wanted to have the Job name in the assignment table in addition to the Job PK (I don't recommend this, it's just an example), I would do that in the API.


So, what how does this relate to this blog topic? Not a single trigger. If there is an error anywhere, I have a couple of APIs to look at.


What would be a trigger based approach? A trigger to populate the PKs. A trigger to populate the denormalized Job name. Possibly even triggers to deal with integrity and referential constraints (but I sure hope not!).


In the trigger based approach, you now have code in many places, any of which can (and at some point will) break. In addition to the maintenance issue, there is also a performance impact with row-level trigger processing.


I would choose the former, API approach over the trigger based approach every time. I have inherited trigger based applications and suffered through every one of them. When I have time, I convert those to APIs as soon as I can.


Referential Integrity


Do not use triggers instead of foreign keys. I have seen trigger based foreign keys and the reason was that the "model was too complex for database referential integrity". In every case where that statement has been made (at least that I have seen), it was due to a poor data model and not a limitation in the database.


Distributed referential integrity is a different beast. I have seen one case where a trigger was used to maintain integrity with data in a different database. I have to admit that in this case, I don't see any alternatives. The trigger incurred some overhead in the application but it was an acceptable amount. If the remote database was down, the trigger failed but that was an intended effect.


Auditing


I have used Triggers for auditing database changes in the past. I even wrote a code generator that generated the triggers for me by looking at the dictionary and dynamically getting columns and such. At one time, I think that was the best approach. Today, Fine Grained Auditing offers an incredibly robust auditing mechanism. It works with SELECT statements and it also allows you to capture other information that is impossible or difficult to get with any other method.


Replication and Data Feeds


Another use of triggers has traditionally been to replicate all or subsets of data to different schemas or databases. Sometimes for application usage and other to aggregate data in a warehouse. Almost all databases now offer some kind of a database link and any database worth using offers some kind of replication.


In many cases, the database will create triggers behind the scenes but at least the database is then responsible for maintaining those triggers. Oracle offers Oracle Streams which is very robust and offers scheduled or real-time replication and Change Data Capture.


Multi-database Support


If you truly need to maintain your application on multiple databases, triggers can be useful. I don't mean that you use a bunch of Oracle features and hope to one day migrate but you actually, actively maintain your code base to run on multiple platforms.


In this case, triggers can keep you from changing your code as often. Take the PK example of using sequences. Some databases use an auto-increment data type, other databases use sequences but the select syntax is different from Oracle's syntax. In this case, you can encapsulate the logic in a trigger and only change that code when required. In the case of migrating to a database with auto-increment, you won't need the trigger at all.


Also, when auditing your application, you may have specific needs that individual databases might not support. In that case, you might want to use triggers to audit. You would want to have a common audit record across database types so it would make sense to use the triggers even on databases that support advanced auditing.


Third-party Applications


If you need to alter data or flow in a third-party application, your only option might be a trigger. In that case, you really have no choice. Before you choose a trigger, think about the other available options. In many cases, Fine Grained Auditing or streams can achieve the same thing and will be a lot less intrusive to the application.


I hope this answers some of the questions about using triggers. Did I miss any cases where it really makes sense to use a trigger? Have you seen triggers used in other ways (good example or bad)?


LewisC

Tuesday, May 13, 2008

Learn Oracle: Triggers

LewisC's An Expert's Guide To Oracle Technology


Today I will be writing about triggers. One of the questions I get fairly often is "what is the difference between a function, a procedure and a trigger?" I already wrote about functions and procedures in Learn Oracle: Procedures and Functions. You should probably read that one before you read this post.


What is a trigger?


A trigger is a special case of stored procedure that is fired during an event rather than being explicitly executed. A function or a procedure can be called from a command line or from within a different calling program. A trigger is called automatically when an event is fired.


In Oracle, a trigger can have the procedural code embedded in the body of the trigger, you can call out to another existing function or procedure, or a combination of both. The code in a trigger is generally the same as any procedure or function. You are allowed to create Java triggers but I see this rarely in live systems.


You cannot execute transaction control statements with in a trigger. That means no commits or rollbacks. If you need to rollback a transaction due to logic in a trigger, raise an exception and allow the calling program to take the appropriate action. As for commits, the calling application should always commit or rollback as needed.


Technically, there is a way to execute transaction control within a trigger but that can be abused, and really damage your data integrity, if done poorly. I will leave that topic for a discussion on advanced PL/SQL.


What are trigger events?


Various databases support different triggering events. Most all enterprise class databases support DML triggers (excluding SELECT). That means that the database will optionally fire anytime a table has a row updated, deleted or inserted. Many databases, including Oracle, also support DDL triggers. These fire when you create, alter or drop an object.


Oracle supports many events in addition to DML events. Oracle supports system events such as the database starting or stopping or when there is a server error. Oracle also supports user events such as a user logging on or off.


For a new user or developer, it is important that you understand DML triggers as you will find many applications that are Dependant on triggers. DDL, user and system triggers tend to have more advanced uses although you will see examples of those for various security related processing (such as VPD).


For the purpose of this blog entry, I'll stick to DML triggers.


Trigger Syntax


There are three main types of DML triggers: before, after and instead of. A before or after trigger can be a statement level trigger or a row level trigger.


Before


Obviously, a before statement trigger will fire before a statement is executed. A before row level trigger fires before each row that is affected by a statement.


After


An after statement trigger will fire after a statement is fired. A before row level trigger fires before each row that is affected by a statement.


Statement vs Row


The difference between a statement level trigger and a row level trigger is very easy to understand. If you perform an update that will affect 10 rows, a statement level trigger will fire once and a row level trigger will fire 10 times.


A statement level trigger does not have access to individual column values. A row level trigger does have access to column values. A before row trigger can change new column values.


Instead Of


An instead of trigger is built on a view. Many views are updateable with an instead of trigger. Many more views are not updateable for various reasons. With an instead of trigger, you can update any of these views. As the name implies, an instead of trigger is executed instead of Oracle trying to execute the command directly against the view.


Trigger Syntax


The syntax of a trigger varies database by database but for Oracle and PL/SQL (as well as for EnterpriseDB and SPL), the basic syntax of a DML trigger is:



CREATE OR REPLACE TRIGGER trigger_name
BEFORE|AFTER|INSTEAD OF
INSERT|DELETE|UPDATE ON table_name
[OF column_names]
[REFERENCING [NEW AS new_cols] [OLD AS old_cols]]
[FOR EACH ROW [WHEN (where_condition)]]
[DECLARE]
BEGIN
EXCEPTION
END;

Let's look at the command row by row. Anything within square brackets ([]) is an optional clause. Any items delimited with a pipe (|) is part of a list.


Row 1: The create or replace should seem familiar if you are familiar with procedures and functions. Naming of a trigger follows standard naming conventions and rules.


Row 2: The BEFORE|AFTER|INSTEAD OF clause tells the database what type of trigger it will be.


Row 3: This line allows you define if the triggering event will be on UPDATE, DELETE, INSERT, a combination or all of these. The "ON table_name" identifies the table for which the trigger will be created.


Row 4: An optional clause is the "OF column_names". This statement only affects an UPDATE. If you only want to fire an update trigger when certain columns are modified, you may include this optional statement and list the columns that should be monitored.


Row 5: In a row level trigger, you have the values of the columns as they existed before the command and the new values as a result of the command. For an insert, there are no old values and for a delete, there are no new values. In an update, you have both old and new.


The REFERENCING clause allows you to name the old row and the new row. By default, they are named :OLD and :NEW. You refer to them as :OLD.column_name and :NEW.column_name. You can query them in both before and after row triggers, like:


IF :old.gl_id = :new.gl_id THEN...


In a before row trigger, you can even set the values of :new columns, i.e.


:new.gl_id := sequence.nextval();


Statement level triggers cannot access row level column data.


Row 6: A DML trigger, by default, is a statement level trigger. When you use "FOR EACH ROW", you turn it into a row level trigger.


The WHEN clause allows you to introduce additional matching criteria that Oracle will test before executing a trigger. It is standard where clause type criteria,


FOR EACH ROW WHEN (old.order_date BETWEEN sysdate - 10 and sysdate)


Row 7 and on are standard PL/SQL syntax. Think of them as an anonymous block attached to the trigger name and criteria.


Example


Here is a very simple trigger using the Employees table from Oracle XE.



SQL> desc employees
Name Null? Type
----------------------------------------- -------- ------------

EMPLOYEE_ID NOT NULL NUMBER(6)
FIRST_NAME VARCHAR2(20)
LAST_NAME NOT NULL VARCHAR2(25)
EMAIL NOT NULL VARCHAR2(25)
PHONE_NUMBER VARCHAR2(20)
HIRE_DATE NOT NULL DATE
JOB_ID NOT NULL VARCHAR2(10)
SALARY NUMBER(8,2)
COMMISSION_PCT NUMBER(2,2)
MANAGER_ID NUMBER(6)
DEPARTMENT_ID NUMBER(4)

Now, I'll create the trigger on employees. The trigger will only fire on insert or update (not delete), update will only fire when email or hire_date is modified and the trigger body will only fire when the :old.salary is greater than 7500. Because it will only fire when an :old value is set, it will never fire for an insert, even though I am defining it for insert.



SQL> create or replace trigger emp_email
2 before insert or update of email, hire_date
3 on employees
4 for each row when (old.salary > 7500)
5 begin
6 dbms_output.put_line('Trigger executing');
7 end;
8 /

Trigger created.

Next, I'll fire two inserts to add a couple of records. Only one of the records will have a salary > 7500. After the inserts, I will update each record. Only the record with a salary > 7500 will display the trigger message.



SQL> set serveroutput on

SQL> insert into employees
2 (employee_id, last_name, email,
3 hire_date, job_id, salary)
4 values
5 (101010, 'Smith', 'smith@barney.com',
6 sysdate, 'PR_REP', 5000);

1 row created.

SQL> insert into employees
2 (employee_id, last_name, email,
3 hire_date, job_id, salary)
4 values
5 (101011, 'Jones', 'jones@barney.com',
6 sysdate, 'PR_REP', 8000);

1 row created.

SQL> commit;

Commit complete.

SQL> update employees set
2 email = 'under7500@noexec.com'
3 where employee_id = 101010;

1 row updated.

SQL> update employees set
2 email = 'over7500@willexec.com'
3 where employee_id = 101011;
Trigger executing

1 row updated.

SQL> commit;

Commit complete.

SQL>


That's pretty much it for DML triggers.


LewisC

Wednesday, April 23, 2008

Oracle Connections to Non-Oracle Databases


LewisC's An Expert's Guide To Oracle Technology


Have you ever needed to bring data from a non-Oracle databases into your Oracle database? This is very common in a warehouse and is even somewhat common in ERP solutions. For a price, Oracle offers Transparent Gateways to many popular databases. What do you do if you need to load some data from a data source but there is no Transparent Gateway (or if you have no budget for one)? If that data source happens to support ODBC, you're in luck and it won't cost you anything above and beyond what you are already paying for your database.


The solution is called Heterogeneous Services Generic Connectivity. I usually just call it HS links. Basically, you configure an ODBC data source and then create a database link against that source. You can run DML against the source just as you would against an Oracle database.


ODBC is available for most flavors of Unix, Linux and, of course, windows. I believe there is even an ODBC package for Mac but I am not a mac user so I can't say that it works. Any features you want to use must be supported by your ODBC driver.


If you are on a 64 bit Windows OS and you are connecting to a 32 bit database, you MUST use the 32 bit ODBC admin tool (c:\windows\syswow64\odbcad32.exe) versus the 64 bit ODBC admin tool (c:\windows\system32\odbcad32.exe). You can get more details about this on my Postgres blog, 32 Bit ODBC Drivers in Vista 64.


Here is the short story about how to get this installed and working. It's really fairly easy. These instructions are for 10g. They probably work in other versions but I have not specifically ran these instructions through those versions.


NOTE: This configuration is done on the database server, not your client. You must have access to an account on your database server that will let you work with system and oracle configuration files..


Configure ODBC


First, get your ODBC drivers for the database you want to connect to. I will use EnterpriseDB since I just happen to have a database loaded and running already. ;-)


If you have installed Advanced Server, you should already have the odbc drivers installed. I know Ingres and SQL Server also automatically install drivers. MySQL provides a separate download. There are so many different tools available that I can't give you detailed instructions on finding and installing your drivers.


Ok, now that you have ODBC installed, create an ODBC data connection. This is really very simple. In Windows, make sure that you choose to create a System DSN. I will call my DSN "EnterpriseDB". Test your DSN to make sure your information is correct. Windows includes a test button on the form where you create the DSN. Make sure to save the DSN.


That's it as far as playing with ODBC goes but remember the DSN name you just created. You'll use it in several places later on.


Configure Connectivity Agent


The next step is to identify the data source to Oracle. You do this by create an initialization file just like you would for an Oracle database. Well, not just like it. But, you get the point.


You should have an HS directory in your Oracle home directory. In HS\ADMIN you should find an INITHSODBC.ora file. Copy this to a init<dsnname>. Mine will be INITEnterprisedbDB.ora. In Windows, case is not significant. In general, I lowercase all file names so my file is really initenterprisedb.ora.


Edit this file. You'll need to change the values of two parameters. You must supply the DSN we created above and a log level. For now I am turning logging off. My file looks like this:


HS_FDS_CONNECT_INFO = EnterpriseDB
HS_FDS_TRACE_LEVEL = off


Save the file, making sure to leave it in the HS\ADMIN directory.


Configure The Listener


At the bottom of your listener.ora file (in Oracle home/network/admin) you need to add a new service under the sid_list_listener:



(SID_DESC = (SID_NAME=EnterpriseDB)
(ORACLE_HOME=C:\oraclexe\app\oracle\product\10.2.0\server)
(PROGRAM=hsodbc)
)

The HSODBC program has under gone name changes. If you are not using 10g, make sure you find the current name to use in the documentation. HSODBC may work in 11g bit I do know the program has been updated and has a new name. The SID_NAME parameter is the ODBC DSN name.


Configure TNSNAMES.ora


You will need to enter a new entry in your TNSNAMES.ora file (in Oracle home/network/admin).


It seems counter intuitive but here you are actually configuring the server where the listener is running not where the remote database is running. Notice the PORT is 1521. That is the port (and the host) where the Oracle listener is listening for connections. ODBC will ensure that your connections make it to the right remote server.



EDB =
(DESCRIPTION=
(ADDRESS=(PROTOCOL=tcp)
(HOST=localhost)
(PORT=1521)
)
(CONNECT_DATA = (SERVICE_NAME=EnterpriseDB)
)
(HS = OK)
)

SERVICE_NAME is, again, the ODBC DSN.

Create a Database Link



create database link edb1 connect to "enterprisedb" identified by "edb" using 'edb';

Notice here that I have the name and password quoted. That's because the remote server, EDB AS, is case sensitive. If the user name and password are not quoted, Oracle will send them in upper case and you'll get an error.


I'm calling my link edb1 but you can call it anything that doesn't violate Oracle naming rules.


In the USING section, you need to use the name defined in your tnsnames.ora.


Test the Link



SQL> create database link edb1 connect to "enterprisedb"
identified by "edb" using 'edb';

Database link created.


SQL> select * from dual@edb1;


D
-
X

SQL> select "lanname" from "pg_language"@edb1 where rownum < 5;



lanname
-----------------------------------
internal
c
sql
plpgsql


SQL>

Notice here that, like user name and password, I have the column and table name quoted. Columns and tables in EDB and Postgres are stored in lower case unless quoted during creation.


There are many parameters you can use to tweak HS. For something like an ETL process, you would want to tweak it as much as possible. For an occasional query, plain vanilla is probably good enough.


Take care,


LewisC








Technorati : , , , , ,

Thursday, January 3, 2008

My Book Has Been Printed

Well, it's taken over a year but it has finally arrived. I started writing the book back in Aug 2006. I finished in late Jan 2007 and the technical editor finished his work in March. Now, In Jan 2008, EnterpriseDB: The Definitive Reference is available. I'm glad I didn't wait for the movie. ;-)

It's kind of ironic. Just this morning, I posted that I am working on my second book. My wife called me at work and told me two boxes of books had arrived. 2008 is turning out to be a good year. I'll have some additional news in the near future.

Anyway, the book looks good. I've already found a few typos and grammar errors just skimming around. I like the font and the pages look really crisp. All in all, I have to say I am very happy that the book is out.

Check out some photos:

EnterpriseDB Book 016

EnterpriseDB Book 020

I think I want to give a couple away. Maybe some kind of contest for the blog readers. Any ideas of something fair? I am willing to pay shipping for a couple but that would only be here in the US. Overseas shipping gets expensive.

LewisC