<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jiramot.info &#187; oracle</title>
	<atom:link href="http://www.jiramot.info/tag/oracle/feed" rel="self" type="application/rss+xml" />
	<link>http://www.jiramot.info</link>
	<description>Developer&#039;s Life</description>
	<lastBuildDate>Mon, 06 Feb 2012 08:49:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Oracle Naming Conventions</title>
		<link>http://www.jiramot.info/oracle-naming-conventions</link>
		<comments>http://www.jiramot.info/oracle-naming-conventions#comments</comments>
		<pubDate>Wed, 21 Jul 2010 12:24:55 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Article]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[plsql]]></category>

		<guid isPermaLink="false">http://www.jiramot.info/?p=531</guid>
		<description><![CDATA[When designing a database it&#8217;s a good idea to follow some sort of naming convention. This will involve a little thought in the early design stages but will save significant time when maintaining the finished system. <p>It&#8217;s less important which exact conventions you choose to follow &#8211; but this page has a few suggestions.</p> [...]]]></description>
			<content:encoded><![CDATA[<h1><span style="font-weight: normal; font-size: 13px;">When designing a database it&#8217;s a good idea to follow some sort of naming convention. This will involve a little thought in the early design stages but will save significant time when maintaining the finished system.</span></h1>
<p>It&#8217;s less important which exact conventions you choose to follow &#8211; but this page has a few suggestions.</p>
<p>The benefits of using a naming convention are more to do with human factors than any system limitations &#8211; but this does not make them any less important.</p>
<p><span id="more-531"></span></p>
<p><strong>Table Names</strong></p>
<blockquote>
<blockquote><p>Table names are <em>plural</em>, field name is <em>singular</em></p>
<p>Table names should not contain spaces, words should be split_up_with_underscores.</p>
<p>The table name is limited to 30 bytes which should equal a 30 character name (try a DESC ALL_TABLES and note the size of the Table_Name column)</p>
<p>If the table name contains serveral words, only the last one should be plural:<br />
APPLICATIONS<br />
APPLICATION_FUNCTIONS<br />
APPLICATION_FUNCTION_ROLES</p>
<p>There are pros and cons to adding a prefix or suffix to identify tables-</p>
<p>Pros: If most access will be made via VIEWS then prefixing all the tables with T_ and all the views with V_ keeps things organised neatly, you will never accidentally query the wrong one.</p>
<p>Cons: Suppose, your naming convention is to have the &#8216;_TAB&#8217; suffix for all tables. According to that naming convention, the APPLICATIONS table would be called APPLICATIONS_TAB. If as time goes by, your application gets a second login, perhaps for auditing, or for security reasons. To avoid code changes, you will then have to create a View or Synonym that points at the original tables and is confusingly called APPLICATIONS_TAB.</p>
<p>Of course if all your code was written against Views in the first place then you skirt right around that issue.</p></blockquote>
</blockquote>
<p><strong>Field Names</strong></p>
<blockquote>
<blockquote><p>Ideally each field name should be unique within the database schema. This makes it easy to search through a large set of code (or documentation) and find all occurences of the field name.</p>
<p>The convention is to prefix the fieldname with a 2 or 3 character contraction of the table name e.g.</p>
<blockquote><p>PATIENT_OPTIONS would have a field called po_patient_option</p>
<p>PATIENT_RELATIVES would have a field called pr_relative_name</p>
<p>ABSENCES would have a field called ab_start_date</p></blockquote>
<p>In a large schema you will often find two tables having similar names which could result in the same prefix. You can avoid this by thinking carefully about the name you give each table &#8211; and documenting the prefixes to be used.</p>
<p>For very complex systems (thousands of tables) consider alternatives e.g. a prefix/suffix to identify the Application module.</p>
<p>Keeping names short: Oracle places no limit on the number of columns in a GROUP BY clause or the number of sort specifications in an ORDER BY clause. However, the sum of the sizes of all such expressions is limited to the size of an Oracle data block (specified by the initialization parameter DB_BLOCK_SIZE) minus some overhead.</p></blockquote>
</blockquote>
<p><strong>Primary Key Fields </strong>- indicate by appending <strong>_pk</strong></p>
<blockquote>
<blockquote><p>e.g.</p>
<p>PATIENTS would have a primary key called pa_patient_id_pk</p>
<p>REGIONS would have a primary key called re_region_id_pk</p>
<p>And so on&#8230;the name of the primary key field being a singular version of the table name. Other tables containing this as a foreign key would omit the _PK</p>
<p>so<br />
CLINIC_ATTENDANCE might then have a foreign key called ca_patient_id<br />
or alternatively: ca_patient_id_fk</p>
<p>Tables with Compound PK&#8217;s, use <strong>_ck</strong> in place of _pk</p>
<p>Notice that where several tables use the same PK as part of a compound foreign key then the only unique part of the FK fieldname will be the table prefix.</p></blockquote>
</blockquote>
<p><strong>View Names</strong></p>
<blockquote>
<blockquote><p>View names are <em>plural</em>, field name is <em>singular</em></p>
<p>View names should not contain spaces, words should be split_up_with_underscores.</p>
<p>While it is common to prefix (or suffix) all views with V_ or VW_, a strong argument can be made that neither are really needed.</p>
<p>One of the easiest ways to boost the performance of an application is to provide, at an early stage in the design, a carefully tuned set of views, then write all the application code against those Views.<br />
Giving your Views friendly easy names will promote their use by developers and end-users, this in turn will mean fewer badly written queries and more use of &#8216;shared SQL&#8217; which will improve the cache hit ratio.</p>
<p>For very large systems, it can make sense to prefix tables/views with the application module name, so a database holding data for both Widget Production and Human Resources data might prefix everything with either HR_ or WP_</p></blockquote>
</blockquote>
<p><strong>Index names</strong></p>
<blockquote>
<blockquote><p>Name the Primary Key index as <strong>idx_</strong>&lt;TableName&gt;<strong>_pk</strong></p>
<blockquote><p>e.g.<br />
PATIENTS would have a primary key index called idx_patients_pk</p></blockquote>
<p>Name a Unique Index as <strong>idx_</strong>&lt;TableName&gt;<strong>_uk</strong></p>
<blockquote><p>e.g.<br />
PATIENTS would have a unique index called idx_patients_uk</p></blockquote>
<p>Where more indexes are added to the same table, simply append a numeric:</p>
<blockquote>
<blockquote><p><strong>idx_</strong>&lt;TableName&gt;<strong>_##</strong></p>
<p>Where ## is a simple number</p></blockquote>
<p>e.g.<br />
PATIENTS would have additional indexes called idx_patients_01, idx_patients_02,&#8230;</p></blockquote>
<p><em>Note &#8211; Conventions that attempt to use the column name as part of the index name become unmanageable as soon as you have multiple columns appearing in multiple indexes.</em></p></blockquote>
</blockquote>
<p><strong>Constraints</strong></p>
<blockquote>
<blockquote><p>Primary and Unique constraints will be explicitly named.</p>
<p>Name the Primary Key Constraint as <strong>pk_</strong>&lt;TableName&gt;<strong></strong></p>
<blockquote><p>e.g.<br />
PATIENTS would have a primary key index called pk_patients</p></blockquote>
<p>Name a Foreign Key Constraint as <strong>fk_</strong>&lt;TableName&gt;</p>
<blockquote><p>e.g.<br />
PATIENTS would have a Foreign Key constraint called fk_patients</p></blockquote>
<p>Note &#8211; in general each constraint should have a similar name to the index used to support the constraint.</p></blockquote>
</blockquote>
<p><strong>Other Fields</strong></p>
<blockquote>
<blockquote><p>Without getting carried away, you can also apply a suffix to non key fields where this is helpful in describing the type of data being stored.<br />
e.g.<br />
A column used to store boolean (Yes/No) values can be given a _yn suffix: retired<strong>_yn</strong>, superuser <strong>_yn</strong>, driver<strong><strong>_yn</strong></strong></p>
<p>In lookup tables an easy way to identify the main text field is to name it as a singular version of the tablename<br />
e.g.</p>
<pre>asset_types.at_asset_type_id_pk   (Primary Key)
asset_types.at_asset_type         (Text field)
asset_types.at_network_yn         (boolean)</pre>
</blockquote>
</blockquote>
<p><strong>SQL</strong></p>
<blockquote>
<blockquote><p>Type all SQL statements in lowercase, being consistent with capitalisation improves the caching of SQL statements. A common variant is to put only SQL keywords in capitals.</p>
<pre>SELECT
   em_employee_id_pk,
   em_employee,
   ab_start_date
FROM
   employees em,
   absences ab
WHERE
   absences.ab_employee_id=employees.em_employee_id_pk;</pre>
<p>You already have a unique prefix worked out for every table, so use the same thing when an ALIAS is required &#8211; this makes the SQL much easier to read.</p>
<p>Always list tables in the FROM / WHERE clause in desired join order &#8211; even with CBO you are giving the Query Optimiser less work to do.</p></blockquote>
</blockquote>
<p><strong>PL/SQL</strong></p>
<blockquote>
<blockquote><p>Prefix scalar variable names with <strong>v_ </strong><br />
Prefix global variables (including host or bind variables) with <strong>g_ </strong><br />
Prefix constants with<strong> c_</strong><br />
Prefix procedure or function call parameters (including sql*plus substitution parameters) with <strong>p_</strong></p>
<p>Prefix record collections with <strong>r_</strong> (alternatively suffix with <strong>_record</strong>)<br />
Prefix %rowtype% collections with <strong>rt_</strong> (alternatively suffix with <strong>_record_type</strong>)</p>
<p>Prefix pl/sql tables with <strong>t_ </strong>(alternatively suffix with <strong>_table</strong>)<br />
Prefix table types with <strong>tt_ </strong>(alternatively suffix with <strong>_table_type</strong>)</p>
<p>Suffix cursors with <strong>_cursor</strong><br />
Prefix exceptions with <strong>e_</strong></p>
<p>If a pl/sql variable is identical to the name of a column in the table Oracle will interpret the name as a column name.</p>
<p><strong>Packages</strong><br />
Prefix package names with PKG_</p>
<p>Write one package for each table &#8211; named PKG_TABLENAME, put all other code that logically belongs to the schema, but not to any particular table in a single Schema package PKG_SCHEMANAME.<br />
If, as is likely, more complex grants are required for different groups of users then create an additional package for each workgroup &#8211; these should contain no code just wrappers that call procedures/functions in the other packages.<br />
This gives a level of separation between the basic code and the user security/grants and makes it easier to change one without breaking the other.</p>
<p>A pl/sql function name like PAYROLL.TAX_RATE the word PAYROLL could refer to either a schema or a package name.</p></blockquote>
</blockquote>
<p><strong>Edit Replace</strong></p>
<blockquote>
<blockquote><p>If you apply a naming convention and then decide to rename something it may be possible to use Edit-Replace to update the associated code. But consider these two fieldnames:</p>
<pre>area_codes.<strong>ac_code</strong>
region_area_codes.r<strong>ac_code</strong></pre>
<p>The columns may be unique but one is a substring of the other!</p></blockquote>
</blockquote>
<p><strong>Instance</strong></p>
<blockquote>
<blockquote><p>Oracle database instance names are limited to eight characters. The first two or three characters of the name should reflect the Application, with the remainder indicating the nature of the instance.<br />
e.g.</p>
<pre>Live instance   SSLive
Test instance   SSTest
Train instance  SSTrain
Data Warehouse  SSdw
Staging Area    SSsa</pre>
</blockquote>
</blockquote>
<p><strong>Data Files</strong></p>
<blockquote>
<blockquote><p>Name Data files so that they identify the instance and the tablespace.</p>
<p>Each filename should end with a two digit numeric value starting with 01, that is incremented by 1 for each new datafile added to the tablespace.<br />
Use the extension &#8220;.dbf&#8221;<br />
e.g.</p>
<pre>SSLive_temp01.dbf
SSLive_rbs01.dbf
SSLive_clinical01.dbf
SSLive_clinical02.dbf</pre>
</blockquote>
</blockquote>
<p><strong>Tablespaces</strong></p>
<blockquote>
<blockquote><p>Avoid naming tablespaces according to time periods.<br />
(Oracle never forgets a tablespace and SMON will scan the list of tablespaces in TS$ every 5 minutes) For a partitioned datawarehouse, try to adopt a strategy of recycling the tablespace names.</p></blockquote>
</blockquote>
<p><strong>Redo Logs</strong></p>
<blockquote>
<blockquote><p>The redo log is a separate file (not in the tablespace)<br />
Name Redo Logs so that they identify the instance, group and member number of the log. Use the extension &#8220;.log&#8221;<br />
e.g.<br />
SSLive_redo_01.log</p>
<p>For more detail on the physical placement of files see Oracle <a href="syntax-ofa.html">Optimal Flexible Architecture</a> (OFA)</p></blockquote>
</blockquote>
<p><strong>Documentation</strong></p>
<blockquote>
<blockquote><p>Lastly &#8211; write and maintain a data dictionary for all data elements &#8211; rather than just dumping the Oracle data dictionary into a text document or an <a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://en.wikipedia.org/wiki/Entity-relationship_model" >Entity relationship diagram</a> &#8211; you should also be defining the <em>business</em> meaning of each data item.</p></blockquote>
</blockquote>
<p><strong>Summary</strong></p>
<blockquote>
<blockquote><p>RDBMS naming conventions can become the subject of endless debate &#8211; here are a few last things to consider:</p>
<p>Does your naming convention make names longer or shorter?</p>
<p>PURCHASE_ORDER_DATE versus PO_DATE</p>
<p>Will you have novice users writing SQL against the database?<br />
If so will they understand the meaning of things like PO_DATE</p>
<p>Is the naming convention documented somewhere that everyone can find? If you arent planning to change it very often, drop the text right into a tableSELECT * from Naming_Conventions;</p></blockquote>
</blockquote>
<p><strong>Related:</strong></p>
<p><a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:6729304326802" >Ask Tom</a> &#8211; Argues against the column prefix<br />
<a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://www.oracle-base.com/articles/misc/NamingConventions.php" >Oracle-Base.com Naming conventions</a><br />
<a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://philip.greenspun.com/sql/style.html" >SQL convention</a> from Philip Greenspun<br />
<a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://www.xoc.net/standards/default.asp" >Reddick Naming convention</a> (hungarian notation)<br />
<a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://www.intelligententerprise.com/001205/celko1_1.shtml" >Joe Celko</a> &#8211; 10 Bad Habits<br />
<a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://vyaskn.tripod.com/coding_conventions.htm" >SQL Server Naming conventions</a><br />
<a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://www.oriolecorp.com/dbcr.html" >Oriolecorp</a> &#8211; File Naming, password conventions<br />
<a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://www.wangz.net/pp/sqlformat.htm" >SQL formatter</a> &#8211; Online SQL beautifier<br />
<a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://support.microsoft.com/?kbid=189220" >Q189220</a> &#8211; Microsoft support for spaces in fieldnames<br />
Standard ISO-11179 &#8211; Rules for defining data elements<br />
<a href="syntax-ofa.html">Optimal Flexible Architecture</a> (OFA)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jiramot.info/oracle-naming-conventions/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HR Schema on Rails</title>
		<link>http://www.jiramot.info/hr-schema-on-rails</link>
		<comments>http://www.jiramot.info/hr-schema-on-rails#comments</comments>
		<pubDate>Wed, 28 Oct 2009 14:30:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Article]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.jiramot.info/?p=432</guid>
		<description><![CDATA[<p>Oracle Database is a product with a distinguished past and a bright future. It boasts innovative, state-of-the-art features as well as a history that predates many modern technologies. Applications have come and gone, but the data of organizations has lived on in Oracle databases that have migrated through various versions. This has resulted in [...]]]></description>
			<content:encoded><![CDATA[<p>Oracle Database is a product with a distinguished past and a bright future. It boasts innovative, state-of-the-art features as well as a history that predates many modern technologies. Applications have come and gone, but the data of organizations has lived on in Oracle databases that have migrated through various versions. This has resulted in a technical challenge, due to the large number of legacy schemas that exist today. Many organizations are faced with the challenge of making this data more widely available to their user base.</p>
<p><a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://www.rubyonrails.org/" >Ruby on Rails</a> (or simply &#8220;Rails&#8221;) is an exciting new framework that developers, DBAs, and system administrators can use to quickly develop Web applications. The framework is open source and rapidly gaining in popularity. It allows you to prototype and develop Web applications with database integration in a fraction of the time possible with other frameworks.</p>
<p>Most of the Rails examples and tutorials available today involve the creation of a new database schema with tables and columns that adhere to structures and naming conventions that the framework expects. These tutorials also assume a rather simple object-relational mapping that is not feasible when working with legacy schemas. However, both the framework and Oracle Database offer features that can be leveraged to allow the creation of Web applications that are integrated with legacy schemas.</p>
<p>This article describes the techniques for creating a Web front end to the Oracle demonstration schema HR. The code available for download with this article includes a complete Ruby on Rails Web Application that was developed on the HR schema running on <a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://www.oracle.com/technology/products/database/xe/index.html" >Oracle Database 10<em>g</em> Express Edition</a> (XE).</p>
<p>The downloaded application works on Windows or Linux. Linux users should convert all backslashes to forward slashes when performing commands described in this article.</p>
<p><span id="more-432"></span></p>
<h2>Why Ruby on Rails?</h2>
<p>Numerous platforms are available for Web development, including Microsoft .Net, Java 2 Enterprise Edition, and PHP. Furthermore, Oracle Application Express (formerly HTML DB), a feature of Oracle Database 10<em>g</em> (also available standalone), is widely considered an ideal platform for quickly developing Web applications with Oracle Database integration. So why has there been so much interest in a new platform using a relatively unfamiliar language?</p>
<p>By its design, Rails allows extremely rapid development of Web applications. It accomplishes this by adhering to conventions rather than forcing a developer to make all of the configuration decisions up front. Once Ruby and the various required packages are installed, you can create a minimal Web application by running less than half a dozen commands and editing one file (database.yml). Included code generators or libraries address many of the most common tasks in Web development. The Ruby language has the object-oriented capabilities of a language like Java but can also be used for creating simple scripts. The range of capabilities of the language enables you to create applications without having to resort to numerous divergent technologies to accomplish the tasks at hand.</p>
<p>Rails has gained an almost legendary reputation for promoting rapid application development. Part of the way this goal has been accomplished is by requiring adherence to set coding standards and naming conventions. Besides being required by the Rails framework, these standards and conventions are generally good coding practices.</p>
<p>Conventions that relate to legacy schema integration with Oracle and Rails include the following:</p>
<ul>
<li>Tables are named in using the plural form of the model they represent. For example, an &#8220;employee&#8221; model maps to an &#8220;employees&#8221; table.</li>
<li>All tables that contain data that will be updated contain a primary key called &#8220;id.&#8221;</li>
<li>In the case of Oracle Database, this primary key is incremented using a sequence with a name based on the table it increments. A table named &#8220;employees&#8221; that contains an &#8220;id&#8221; will be incremented by a sequence named &#8220;employee_seq.&#8221;</li>
</ul>
<p>There are many ways to proceed with creating Rails applications that run against legacy schema. Some of the techniques involve the use of Rails features; others involve the modification of underlying database objects. Rather than attempt to describe every possible way to proceed, the demo Web application is an attempt to leverage the power of both Oracle and Rails in such a way as to provide a reasonable solution that is clear, quickly developed, and easily maintained.</p>
<p>The Rails community characterizes the Ruby on Rails framework as &#8220;opinionated.&#8221; This term is intended as a positive description, indicating that the design of the software promotes adherence to standards and practices. However, such a goal raises the concern that the framework will limit or constrain application development. Our application includes the implementation of a few requirements that illustrate the flexibility of the framework.</p>
<p>The Ruby on Rails framework provides the tools needed to rapidly construct a Web application on a new or a legacy database schema. Consider the output of rake (a Ruby build utility), which provides some idea of the effort involved in creating this project:</p>
<pre>C:\hr_rails\hr&gt;rake stats
(in E:/ruby_apps/hr_rails/hr)
+----------------------+-------+-------+---------+---------+-----+-------+
| Name                 | Lines |   LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Helpers              |    15 |    14 |       0 |       0 |   0 |     0 |
| Controllers          |   243 |   193 |       7 |      35 |   5 |     3 |
| Components           |     0 |     0 |       0 |       0 |   0 |     0 |
|   Functional tests   |   440 |   315 |      10 |      50 |   5 |     4 |
| Models               |   177 |   149 |       6 |       5 |   0 |    27 |
|   Unit tests         |    50 |    35 |       5 |       5 |   1 |     5 |
| Libraries            |     0 |     0 |       0 |       0 |   0 |     0 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total                |   925 |   706 |      28 |      95 |   3 |     5 |
+----------------------+-------+-------+---------+---------+-----+-------+
  Code LOC: 356     Test LOC: 350     Code to Test Ratio: 1:1.0</pre>
<p>Fewer than 30 classes and 400 lines of code were required to develop this application!</p>
<h2>Installing and Running the Web Application</h2>
<p>Installation of Oracle Database XE, Ruby, Rails, and the OCI8 packages are prerequisites for installing this application. Because describing each process would require a series of articles. I will simply refer you to installation resources:</p>
<ul>
<li><a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://www.oracle.com/pls/xe102/homepage/" >Installing Oracle Database XE</a></li>
<li><a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://www.rubyonrails.org/down"  target="_blank">Installing Ruby and Rails</a></li>
<li><a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://www.oracle.com/technology/tech/php/htdocs/php-oracle-tutorial.html" >Installing OCI8</a> (&#8220;PHP OCI8 Extension&#8221; section)</li>
</ul>
<p>After installing these items, download and unzip the <a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://www.oracle.com/technology/pub/files/hr_rails.zip" >hr_rails.zip</a> file, which contains all the code resources associated with this article. The extracted files have the following directory structure shown to the right (Figure 1).</p>
<table border="0" align="center">
<tbody>
<tr>
<td><img src="http://www.oracle.com/technology/pub/images/saternos-rails-f1.gif" border="0" alt="Figure 1" width="214" height="522" /></td>
</tr>
<tr>
<td><span>Figure 1: Directory Structure</span></td>
</tr>
</tbody>
</table>
<p>The directory structure is worth noting as it is a standard structure for all Rails applications. The name of the application (hr, in this case) appears as the root directory. The models, views, and controllers directories within the app directory contain the bulk of the application code. The config directory contains the database.yml file (used to configure database connections) and the routes.rb file (used to define the page that will serve as the index to the application). The public folder contains directories with Web resources, including scripts, images, and stylesheets. Although it&#8217;s not discussed in this article, a test directory contains resources related to unit-testing the application.</p>
<p>With the software installed, the schema created, and the Rails application configured, the application is ready to run. From the hr directory, run:</p>
<pre>ruby script\server</pre>
<p>This command stars WEBBrick, a Ruby Web Server that is included with the installation. In a Web browser, enter the URL of the Web application that will be running on port 3000—for instance, http://localhost:3000.</p>
<p>Sample pages as they appear in the application are listed below:</p>
<table border="0" cellpadding="10">
<tbody>
<tr>
<td><img src="http://www.oracle.com/technology/pub/images/saternos-rails-f2.gif" border="0" alt="Figure 2" width="650" height="518" /></td>
</tr>
<tr>
<td align="center"><span>Figure 2: Main Page</span></td>
</tr>
<tr>
<td><img src="http://www.oracle.com/technology/pub/images/saternos-rails-f3.gif" border="0" alt="Figure 3" width="650" height="518" /></td>
</tr>
<tr>
<td align="center"><span>Figure 3: Regional Compensation Report</span></td>
</tr>
<tr>
<td><img src="http://www.oracle.com/technology/pub/images/saternos-rails-f4.gif" border="0" alt="Figure 4" width="650" height="518" /></td>
</tr>
<tr>
<td align="center"><span>Figure 4: Employee Listing</span></td>
</tr>
<tr>
<td><img src="http://www.oracle.com/technology/pub/images/saternos-rails-f5.gif" border="0" alt="Figure 5" width="650" height="518" /></td>
</tr>
<tr>
<td align="center"><span>Figure 5: Employee Edit</span></td>
</tr>
</tbody>
</table>
<p>Next, let&#8217;s take a look at database and schema configuration for the application.</p>
<h2>Database and HR Schema Configuration</h2>
<p>The SQL*Plus Client (or Oracle Instant Client Software) must be installed on the server where Rails is installed. A TNSNAMES.ora entry referencing the database containing the HR schema to be used must be created. For those new to Oracle, the TNSNAMES.ora file contains the connection information used to connect to an oracle database. The database could be on the same machine or on a remote server. Connection information includes the server name, database name and database port in use. This information is used by the Ruby OCI8 package to allow Rails to communicate with the database. The OCI8 layer is a layer written in Ruby that utilizes the underlying Oracle database configuration (specified in TNSNAMES.ora) to make the database connection.</p>
<p>To create the schema objects required by the Web application, perform the following tasks first:</p>
<ul>
<li>Create a new user (designated as HR_RAILS here) Note: The included script will drop the user if it exists and recreate it.</li>
<li>Grant the new user the appropriate resources and privileges to create its own schema and access the HR schema.</li>
<li>Modify HR schema in a few areas:
<ul>
<li>Create sequences to populate primary keys.</li>
<li>One trigger needs to be modified and another created. The triggers are required due to the job_history table and related constraints. The modified trigger checks to determine if an employee&#8217;s job_id or department_id has changed before inserting a history record. The new trigger deletes an employee&#8217;s job history record if the employee is deleted. The trigger could be modified to archive this data if required.</li>
</ul>
</li>
<li>Create synonyms as well as views for the HR_RAILS schema that adhere to Rails naming conventions.</li>
</ul>
<p>To accomplish these tasks, run the create_rails_db_user_and_privs.sql script and answer the prompts appropriately. For example:</p>
<pre>C:\hr_rails\hr&gt;sqlplus /nolog
SQL*Plus: Release 10.1.0.2.0 - Production on Wed Mar 8 12:31:01 2006
Copyright (c) 1982, 2004, Oracle.  All rights reserved.
SQL&gt; @create_rails_db_user_and_privs
Enter the DBA user:
system
Enter the DBA password:
notmanager
Enter the Database Name ( Oracle SID):
xe
Enter the (new) rails user (user will be DROPPED and created):
hr_rails
Enter the rails user's password:
hr_rails
Enter the HR user (to grant the rails user privs):
hr
Enter the HR user's password:
hr
Connected.
.
.
.</pre>
<p>A number of commands will be run and objects created. Review the results in the create_db_objects.log file, which is created in your working directory.</p>
<p><strong>Integration and Application Databases</strong>. Object-oriented programming expert Martin Fowler makes a useful distinction between <em>application</em> and <em>integration</em> databases. In general terms, an application database is a database that is used by a single application, while an integration database is accessed and utilized by a number of applications. Rails development is oriented toward the development of applications using an application database. The current project shows an approach to utilizing Rails with an integration database.</p>
<p>In this application, rather than directly accessing the schema using the HR user, a new user is created (identified as hr_rails in this article). Having a unique user dedicated to the Rails application provides visibility to the DBA who needs to differentiate between the applications accessing the database schema in question. In addition, Rails encourages the use of table and column names that conform to standard naming conventions. The new schema will contain views that correspond to the underlying HR tables. These views are inherently updatable rather than query-only and so are used for all insert, update, and delete operations as well. In essence, the implementation strives to create an application database schema that is somewhat independent of the integration database schema (to use Fowler&#8217;s terminology).</p>
<p>The use of Oracle&#8217;s &#8220;Inherently Updatable&#8221; views provides a useful interface for taking advantage of ActiveRecord&#8217;s object-relational capabilities. Again, these views serve to format the table structure and data in a form that is most useful for Rails access. They also isolate the rails application so that there is increased auditing visibility for the Rails database user and other application users that access the HR schema. All the power of Oracle SQL, including Oracle&#8217;s extensions to the language and functions, can be leveraged using find_by_sql.</p>
<p>For reference within the application, a portion of an Entity Relationship Diagram can be found as an image on the About This Site page. There is also a link from this page (as well as from the main page) to a page that queries the Oracle Data Dictionary to display the view names along with column names and types.</p>
<h2>Changes to the HR Schema</h2>
<p>Although the HR schema remains fundamentally unchanged, the application did require some adjustments. I added several sequences that Rails uses to populate primary keys of tables. Sequences of this kind might need to be accessed by other applications and so are included in the HR schema itself.</p>
<p>I modified one trigger that already exists in the HR schema (UPDATE_JOB_HISTORY) to call the add_job_history procedure only if the job or department associated with the employee changes. I made this change to limit the situations when this trigger is called to fields that are actually related to the emplyee&#8217;s job history. I added a second trigger (DELETE_JOB_HISTORY) that deletes the employee&#8217;s job history records when an employee is deleted. This trigger is required to allow the employee to be deleted because of the way the database constraints are set up. For example, in a production application, the JOB_HISTORY might be archived, or an Employee record might have the status &#8220;inactive.&#8221;</p>
<h2>Development Process</h2>
<p>A general outline of the development process used to create the sample application is as follows:</p>
<ul>
<li>Create and update the HR schema.</li>
<li>Create the HR_RAILS user, schema, and database objects.</li>
<li>Create a Rails application by running the following command:
<pre>rails hr</pre>
</li>
<li>Configure the database.yml file so that the development, test, and production connections would connect to the correct database with a valid username and password. The database.yml file included with the application download (found in the \hr\config directory) references a database called XE accessed by the HR_RAILS user using HR_RAILS for the password. These values need to be modified to values that you used when creating the schema. This file is used by the Ruby ActiveRecord class to make database connections.</li>
<li>Generate &#8220;scaffolds&#8221; for the tables. These scaffolds—Ruby models, views, and controllers—provide the ability to view, create, update, and delete records on the underlying tables. These scaffolds were created by running scripts that had been created as part of the Rails application.
<pre>ruby script\generate scaffold &lt;name&gt;</pre>
</li>
<li>Create a layout for the site. This provides the header, navigations on the left, and the footer portions that you see on each page of the site.</li>
<li>Modify the routes.rb configuration so that the first page of the site was mapped (rather than having to enter an extended URL).</li>
<li>Perform multiple iterations involving modifications of models (if additional data is needed), views (trying to make the interface user-friendly and functional), and controllers (to get data to the views). This is the actual manual coding that was completed to change the style of the site and create functionality specific to the application at hand.</li>
</ul>
<p><strong>Scaffolds</strong>. During the development process, a complete Model, View, and Controller for each table was generated. Although the full scaffold was generated for all of the models in use, the final version does not include the full functionality available. A user can view only Region and Country listings. Location, Department, and Employee listings can be viewed as well as inserted, updated, and deleted.</p>
<p><strong>Models</strong>. There are similar features to each of the Model classes. Representative examples are presented below. You can consult the code to see the others in detail.</p>
<p><strong>Input Field Validation</strong>. The Rails framework seeks to centralize validation code in the Model class. There are a number of benefits to this approach, most notably the fact that all insert and update processing that utilizes the Model class will include the constraints defined and will return a consistent message to the user should the validation rule fail. However, the database itself can (and should) also be used to constrain data. This has the advantage of restricting the data entered into the table by <em>any</em> application or SQL statement. In addition, the View layer can be used to enforce validation by its very design. A well designed GUI will restrict the user in such a way that will prevent him from choosing invalid options. A text field with a set length will prevent strings that exceed the maximum allowable length. A drop down box will prevent a user from entering unacceptable entries in a field that is required to contain foreign key entries.</p>
<p>Employee Model validation ensures that the required fields are included, string data fields do not exceed the maximum length, e-mails are unique, and salaries are numeric. (The views implicitly validate the departments and managers by forcing the user to select data from a drop-down).</p>
<pre>validates_presence_of :email, :hire_date, :last_name, :first_name, :phone_number, :salary
validates_uniqueness_of :email
validates_length_of :first_name, :maximum =&gt; 20
validates_length_of :last_name, :maximum =&gt; 25
validates_length_of :email, :maximum =&gt; 25
validates_length_of :phone_number, :maximum =&gt; 20
validates_numericality_of :salary, <img src='http://www.jiramot.info/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> nly_integer =&gt; true</pre>
<p>In addition, there is custom validation code in the Employee model to ensure that the salary and commission are set within a valid range:</p>
<pre>def validate
     if salary != nil
	  if salary &lt; 1
		  errors.add(:salary, "must be positive.")
	  end

	  if salary &gt; 999999
		  errors.add(:salary,"must be less than 999999")
	  end
     end

     if commission !=nil
	  unless commission &gt;= 0 &amp;&amp; commission &lt; 1
			  errors.add(:commission, "must be greater than 0 and less than 1.")
	  end
     end
end</pre>
<p><strong>Queries</strong>. There is no SQL visible in the code related to the INSERT, UPDATE, DELETE, and SELECT * queries that are used by each of the Model classes.This code is generated behind the scenes. However, a common characteristic of legacy schemas is the requirement of complex SQL to retrieve or summarize data. Rails provides a means to execute complex SQL statements by defining a find_by_sql function in the Model class.</p>
<p>The query to construct the corporate hierarchy is as follows:</p>
<pre>SELECT tree.*,
	   LEAD (hierarchy_level) OVER (ORDER BY seq) next_level
FROM (
	 SELECT CONNECT_BY_ROOT last_name top_node_name,
	 		(last_name || ', ' || first_name ||' ('||job_title||')') employee_name,
			emp.id employee_id,
			SYS_CONNECT_BY_PATH (last_name, '-&gt;') node_path,
			LEVEL hierarchy_level,
			ROWNUM seq
	 FROM(
	 	 SELECT e.*, j.job_title
		 FROM employees e, jobs j
		 WHERE e.job_id = j.id
		 ) emp
	 START WITH emp.job_title= 'President'
	 CONNECT BY PRIOR emp.id = manager_id
	 ORDER SIBLINGS BY emp.id
	 ) tree
ORDER BY seq</pre>
<p>This code is an example hierarchical query created using Oracle SQL extensions. It is used to return data in a structure that produces the corporate hierarchy example. The page that displays the results includes JavaScript that allows the user to &#8220;drill down&#8221; through the hierarchy. The LEAD analytic function allows access to more than one row without having to use a self-join. The current row in the result set can effectively &#8220;look ahead&#8221; to the hierarchy level in the next row, which greatly simplifies the JavaScript code used to display the hierarchy.</p>
<table border="0" cellpadding="10">
<tbody>
<tr>
<td><img src="http://www.oracle.com/technology/pub/images/saternos-rails-f6.gif" border="0" alt="Figure 6" width="600" height="450" /></td>
</tr>
<tr>
<td align="center"><span>Figure 6</span></td>
</tr>
</tbody>
</table>
<p>A number of relationships are defined in relation to the Employee model. An employee belongs to a department and reports to a manager. At the database level, foreign key constraints exist that reflect these relationships. The Rails framework also specifies that these relationships are one-to-many. Manager is a field within the Employees table itself.</p>
<pre>belongs_to :department
belongs_to 	:manager,
		:class_name =&gt; "Employee",
		:foreign_key =&gt; "manager_id"
belongs_to :job
has_many :department
has_many :managed_employee,
	     :class_name =&gt; "Employee",
	     :foreign_key =&gt; "manager_id"</pre>
<p>These relationships set up a number of convenience methods that allow the programmer easy access to related data through the model objects.</p>
<p><strong>Controller</strong>. There are relatively few modifications to the generated controller objects. The main controller has methods added for the main and about views. The employee view includes a couple of additional calls to models used to populate manager and department drop-downs. The remaining code is simply a portion of the automatically generated scaffold.</p>
<p>The config\routes.rb file was modified so that http://localhost:3000 maps to the main page for the application.</p>
<p><strong>View</strong>. All of the pages in the site have a common header, left navigation bar, and footer. These are consolidated into a single <em>layout</em> file. By default, Rails looks for a layout called &lt;controller_name&gt;_layout.&lt;xml or rhtml&gt; in the /app/views/layout directory. However if you create a layout called application in the layouts directory, it will be used by controllers that do not have a layout based on the controller name.</p>
<p>The views take advantage of a number of Rails classes designed to minimize the amount of code that appears in a view. The numeric data was formatted as currency using the number_to_currency helper or the number_with_precision helper.</p>
<p>Rails also includes some JavaScript libraries that provide a number of services related to AJAX support and DOM manipulation. Although these are not used extensively, there are visual effects that are used to make the images on most of the pages disappear if they are clicked. A few additional JavaScript functions are included, which allow the mouseover button effects and the corporate hierarchy drill-down.</p>
<h2>Advanced Oracle Functionality</h2>
<p>The sample application takes advantage of the Rails ability to automatically generate the trivial SQL statements that are required to insert, update, and delete by primary key as well as to select * from a table. However, several queries that use Oracle SQL are included as well. The region.rb model contains SQL used to create the regional compensation report (GROUP BY ROLLUP) as well as the schema report that lists the views that the application uses (LAG OVER). The employee.rb model includes the query used to construct the corporate hierarchy. This query uses CONNECT BY to perform a recursive search as well as LEAD OVER.</p>
<h2>Conclusion</h2>
<p>HR will continue to provide a popular schema for the demonstration of SQL functionality. As demonstrated with this application, tt also serves as an example of how Ruby on Rails can be used to create Web applications that utilize legacy schemas.</p>
<p>source: <a target="_blank" rel="nofollow" href="http://www.jiramot.info/goto/http://www.oracle.com/technology/pub/articles/saternos-rails.html" >http://www.oracle.com/technology/pub/articles/saternos-rails.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.jiramot.info/hr-schema-on-rails/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

