|
YOUR FEEDBACK
Did you read today's front page stories & breaking news?
SYS-CON.TV SYS-CON.TV WEBCASTS |
TOP COLDFUSION LINKS Product Review Putting Oracle SQL to Work in Your ColdFusion Applications
Putting Oracle SQL to Work in Your ColdFusion Applications
Jun. 7, 2001 12:00 AM
SQL is the bread-and-butter language of relational databases. Although the language has been standardized (SQL-92 and SQL:99), virtually no vendor's implementation strictly conforms to the standards. Most database products use their own syntax (in joins, for example) and, more important, implement several language extensions. For the developer it's necessary to know about product-specific extensions in order to leverage the database optimally. This is true whatever the nature of the application - Web or client/server. In addition, for the Web programmer knowledge of these extensions can help shift a lot of the processing load off the Web/application server to the database where it belongs (see Ben Forta's comments on this in "Take Your Database Out of Retirement," CFDJ, Vol. 1, issue 3). In this article we present some features of Oracle SQL that we've found useful when developing ColdFusion applications. This article is separated into two parts. Part 1 explores some of the built-in functions that you have at your disposal when working with Oracle and compares them to the corresponding ColdFusion functions. Part 2 will show how some basic application problems can be solved with SQL, with particular reference to Oracle-specific syntax. This overview is not comprehensive, but it should help the Oracle novice find his or her way around the database by pointing out features that work particularly well in ColdFusion application development.
Leveraging Oracle Functions
in ColdFusion
For quick reference, we've listed ColdFusion string, numeric, and date functions with their Oracle counterparts in Tables 1, 2 and 3, respectively. Many ColdFusion functions have no direct counterpart in Oracle and vice versa. However, as you'll see in many of the following examples, much of what can be achieved with ColdFusion functions can also be achieved by using one or more Oracle functions in tandem. Many examples use an Oracle table called DUAL. This is a single row table that contains a dummy entry (as can be seen by selecting * from DUAL). The table is owned by SYS (which is the user with the most privileges in Oracle installations), and most Oracle installations make it available to all users through a public synonym. Selecting from DUAL is a useful technique when you want to have Oracle do a computation and return the result to you.
Invoking Oracle Functions in ColdFusion
<cfquery name="yourFunction"The variable yourFunction.return_ value[1] contains the returned value.
A Simple Audit Trail Using USER
and SYSDATE
The insert in Listing 1 enters the current account user and system date (down to the second) into the four columns. These columns can then be used at any time to keep track of who made modifications to your data and when. It's also worthwhile noting here that if you need extensive auditing of your data, that is, keeping exact track of any and all modifications to your data, Oracle has an advanced auditing system built into the RDBMS. The audit trail produced by the built-in system not only allows you to audit data, but also user sessions. A detailed discussion of the Oracle audit trail is beyond the scope of this article, but it's important for you as a CF developer to know that it exists in case you need advanced auditing capabilities. Inserting Dates into Oracle As we're sure many readers have experienced, inserting dates into an Oracle database from ColdFusion can be a bit trying. One simple way to do this is to pass date values as strings and convert the string to a date data type using the Oracle TO_DATE function (see Listing 2).
Truncating Dates <cfquery name="yourQuery"It's important to note that the second parameter of both TO_DATE and TO_CHAR functions is extremely flexible and easy to use. This parameter, formerly called a date mask, allows you to deal with just about any date/time format you may want to use.
Using DECODE
DECODE(expression,where DECODE returns one of value_1, value_2,..,value_N, or default_value depending on whether expression evaluates to evaluated_ value_1,evaluated_value_2,..,evaluated_value_N, or some other value (treated as the default). This function is extremely useful in making dynamic assignments in SQL statements. As an example, assume that we pass a numeric month value (1 through 12) via a ColdFusion variable (form.month) to a select statement and, depending on the value of form.month, we want to select the appropriate month from a table containing monthly values. DECODE sets the column name on the fly (see Listing 3). With the select statement in Listing 3 you've effectively turned the month into a parameter that causes the database to return data from different columns depending on its value. The other way to achieve the same result would be to use a CFCASE or CFIF - a tedious and expensive option. DECODE is much more elegant, and it also pushes the task on to the database, thereby conserving your ColdFusion resources. Also note that Listing 3 also shows that the default_value is optional.
Ensuring Consistent Capitalization of Returned Values
<cfquery name="yourQuery"At times you may want to extract a substring from a character string; however, you only know the characters delimiting the substring, not the numeric start and end positions of the substring. In this case, you can't use the SUBSTR (substring) function directly. However, you can use the INSTR function to get the positions of the delimiting characters and pass these on to the SUBSTR function. An (artificial) example should help make the preceding prose a bit clearer. Here we want to extract the word "whom" from the substring "for.whom.the.bells.toll". <cfquery name="yourQuery"Yes, we know you can achieve the same thing using the ColdFusion string function GetToken, but, remember, the idea is to stress your database and save your ColdFusion server.
Concatenating Strings
<cfquery name="yourQuery"The query column alias emp_name contains the concatenated information. By the way, the concatenation operator is useful if you want to generate a comma-delimited file for import into Excel, for example. We'll leave this as an exercise for our readers.
Trimming Strings
<cfquery name="yourQuery"The first argument of these functions is the string to be trimmed and the second is the trim string, which contains the characters to be trimmed out. Thus, the above query returns the string "012" - the characters "a", "b", and "c" are trimmed out from the left and right ends of the string. If you don't specify the second string, the functions assume you want to trim white-space characters - equivalent to the ColdFusion Ltrim and Rtrim functions. <cfquery name="yourQuery"This returns the string "012". Again this can be done (but shouldn't be) on the ColdFusion server.
Replacing Characters in a String
<cfquery name="yourQuery"This removes the "abc" in the middle of the first string. Here's an example in which one string is replaced by another: <cfquery name="yourQuery"This replaces "abc" with "def".
Translating Characters in a String
<cfquery name="yourQuery"What would happen if you change the string to "01acc2", keeping the replace and translate strings the same? Now that you've tried it, you know what TRANSLATE can do for you.
Arithmetic with Nulls
<cfquery name="yourQuery"
Warning the User About Data Volume
<cfquery name="countRecs"However, the number may not be very significant if you're dealing with wide tables with lots of columns or where the data types of the columns are very large, for example, VARCHAR2(2000). You can actually provide users with a good estimate of the volume of data they're going to slosh about over the intranet/Internet by using the VSIZE function as follows: <cfquery name="dataSize"VSIZE returns the number of bytes in the internal Oracle representation. The above query sums the total value of bytes in the internal representation for all the columns you've included and the records you've selected. Although this won't be exactly the volume of data to be transferred, it will be extremely close (for example, one character is one byte in Oracle internal representation). You can also use the same technique to prevent users from accessing more than a set volume of data.
Oracle SQL Extensions and Idiosyncrasies
Pseudo Columns One of the pseudo columns that Oracle makes available to every result set is the ROWNUM. For each row returned by a query, the ROWNUM pseudo column returns a number indicating the order in which Oracle selects the row from a table or a set of joined rows. The first row selected has a ROWNUM of 1, the second has 2, and so on. A frequent requirement is to get the top N records in a table. If you combine the ORDER BY clause in a query with a WHERE clause on the ROWNUM pseudo column, you can easily generate top N hit lists. For example: <cfquery name="topN"This query returns, very simply, the top 10 salaried employees and their salaries. No additional ColdFusion code is necessary. This example also shows that the FROM clause doesn't necessarily need to contain a table name; it can even refer to a set of records returned by a subquery. There's another Oracle pseudo column - ROWID - that's essentially the physical storage address of the row. This can be useful in constructing a SQL statement to detect duplicate rows in a table. We'll leave you to mull over how this can be done.
Outer Joins
The first thing to notice in Listing 4 is the syntax for the outer join, which could be quite different from what you're used to in other database products. The principle is the same, though: the (+) on the SALES side of the join tells Oracle that you want all products returned, including those for which no sales have been made.
Bill of Materials (Hierarchy) Problems
The query assumes that the top person in the hierarchy has no manager (manager_id is NULL). Note the use of the LPAD function to offset the records depending on the hierarchy level. The pseudo column LEVEL is always returned by such a query, and, as the name suggests, denotes the hierarchy level of the record.
Locking Records
There are many ways of dealing with such problems, often depending on the context of the transactions in question. One of the simplest ways is to use the SELECTŠFOR UPDATE command. When you write your CFQUERY tag to call up the required records for display, add the FOR UPDATE command at the end of the select statement (see Listing 6). The result is that other database sessions will only be able to view the records in question, not modify them. The FOR UPDATE clause has placed a lock on the complete record set. Only the current user's session will be able to process an UPDATE or DELETE statement on the records. Any other session that attempts to modify the same data will automatically be forced to wait by Oracle. To release the locks and make the data available to other database sessions for modification, you need to send a COMMIT or close the current user's database session. Be careful when using such statements: make sure you lock only the necessary records using the WHERE clause. If not, you may accidentally cause other users to wait for COMMITs on data they're not interested in.
Conclusion
As a ColdFusion developer you're in the privileged position of being able to pick and choose how best to utilize Oracle's rich feature set within your Internet applications. If you're clever about your choices, your applications will go into production quicker and run faster with fewer resources. Learn as much as you can about the database you're using - your users will thank you for your efforts. By the way, one of the best sources for Oracle information is the Oracle developer's Web site at http://technet.oracle.com, and the free membership provides access to countless resources. Among the most important is the complete documentation for the Oracle RDBMS. You can view it online or download it in PDF format. Like any technical documentation it isn't exactly an inspiring read. However, it's comprehensive, well organized, and chock-full of examples, and is definitely your best bet for information on Oracle. In Part 2 we'll delve into the procedural extensions that Oracle provides to SQL within the database: PL/SQL and Java. YOUR FEEDBACK
CFDJ LATEST STORIES . . .
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||