<?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>MacLochlainns Weblog</title>
	<atom:link href="http://blog.mclaughlinsoftware.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mclaughlinsoftware.com</link>
	<description>Michael McLaughlin's Technical Blog</description>
	<lastBuildDate>Sun, 14 Mar 2010 02:42:55 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>MySQL Standard Group By</title>
		<link>http://blog.mclaughlinsoftware.com/2010/03/10/mysql-standard-group-by/</link>
		<comments>http://blog.mclaughlinsoftware.com/2010/03/10/mysql-standard-group-by/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 06:54:12 +0000</pubDate>
		<dc:creator>maclochlainn</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[MAMP]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.mclaughlinsoftware.com/?p=3595</guid>
		<description><![CDATA[Teaching SQL is interesting because folks try syntax that experience would tell you shouldn&#8217;t work. It was interesting when I discovered what should be broken from my perspective but was expected behavior in MySQL. It became clearer to me why it&#8217;s there as I did some experimenting with it enabled and disabled.
The reason that I [...]]]></description>
			<content:encoded><![CDATA[<p>Teaching SQL is interesting because folks try syntax that experience would tell you shouldn&#8217;t work. It was interesting when I discovered what should be broken from my perspective but was expected behavior in MySQL. It became clearer to me why it&#8217;s there as I did some experimenting with it enabled and disabled.</p>
<p>The reason that I find that it broken is a matter of perspective not standards. The fact that you can select a set of non-aggregated columns with an aggregated column, and exclude one, more than one, or all of the non-aggregated columns from the <code>GROUP BY</code> clause seemed like a broken behavior. The MySQL behavior is explained in <a href="http://dev.mysql.com/doc/refman/5.1/en/group-by-hidden-columns.html">Chapter 11.12.3 of the MySQL 5.1 Reference</a>. What wasn&#8217;t clear from the documentation when I read it was why the behavior is allowed. Gary&#8217;s comment on the original post made me look more deeply into the behavior.</p>
<p>If you check the referenced documentation, the process is called <code>GROUP BY</code> hidden columns. That label didn&#8217;t immediately resonate with me. That&#8217;s probably of my background with IBM&#8217;s DB2 and Oracle. I&#8217;m so accustom to how they work, that sometimes I think they set the standards but they don&#8217;t. It turns out that the <code>GROUP BY</code> clause in the ANSI SQL standards doesn&#8217;t allow for expressions.</p>
<p>The default configuration of MySQL allows for the expressions (functions) in the <code>GROUP BY</code> clause. The documentation refers to <em>hidden columns</em>, which are in point of fact expressions in the <code>GROUP BY</code> clause. MySQL does support expressions in the <code>GROUP BY</code> by default, and requires, like Oracle, that when you use an expression in the <code>SELECT</code> clause that you mirror it in the <code>GROUP BY</code> clause. This means you group on the result of the expression, not a column in the table or view.</p>
<p>In the default configuration, you have three options. They are determinate results, indeterminate results, and hidden column results. The following cover these components. </p>
<p><span style="font-size:115%"><strong>Determinate Results</strong></span></p>
<p>Determinate results are straight forward. They require that all non-aggregated columns in the <code>SELECT</code> clause are mirrored in the <code>GROUP BY</code> clause. This means that the non-aggregated column values are the key upon which results are aggregated.</p>
<p>An example of determinate results is:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>   key_one
<span style="color: #66cc66;">,</span>        key_two
<span style="color: #66cc66;">,</span>        SUM<span style="color: #66cc66;">&#40;</span>counter<span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">FROM</span>     grouping
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> key_one;</pre></td></tr></table></div>

<p><span style="font-size:115%"><strong>Indeterminate Results</strong></span></p>
<p>Indeterminate results isn&#8217;t straight forward but isn&#8217;t hard to grasp. An indeterminate result set is returned when one or more non-aggregated columns in a <code>SELECT</code> clause aren&#8217;t listed in the <code>GROUP BY</code> clause. The columns listed in the <code>SELECT</code> clause but excluded from the <code>GROUP BY</code> clause return meaningless values because they&#8217;re column values chosen indeterminately from all pre-aggregated rows.  </p>
<p>The following query runs in a generically configured MySQL instance without an error. It returns a meaningless <code>key_two</code> column value from the pre-aggregated row set. In the example, the aggregation column counts the unique <code>key_one</code> column values. This behavior makes <code>key_one</code> a determinate value, and <code>key_two</code> an indeterminate</code> value.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>   key_one
<span style="color: #66cc66;">,</span>        key_two
<span style="color: #66cc66;">,</span>        SUM<span style="color: #66cc66;">&#40;</span>counter<span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">FROM</span>     grouping
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> key_one;</pre></td></tr></table></div>

<p>You can fix this mixed return set by adding the <code>key_two</code> column to the <code>GROUP BY</code> clause, which would return a determinate set. Alternatively, you can prevent the default behavior for the <code>GROUP BY</code> clause <a href="http://dev.mysql.com/doc/refman/5.1/en/server-sql-mode.html">by adding the <code>ONLY_FULL_GROUP_BY</code> mode variable</a> to your <code>SQL_MODE</code> system variable.</p>
<p>After setting the <code>SQL_MODE></codeL variable, a <code>GROUP BY</code> must contain all non-aggregated columns. When you make this change to the <code>SQL_MODE</code> system variable, you also disable any queries that use an expression in their <code>GROUP BY</code> clause. Those queries with expressions in the group by will now raise an <code>ERROR 1055</code> exception, like this:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">ERROR <span style="color: #cc66cc;">1055</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">42000</span><span style="color: #66cc66;">&#41;</span>: <span style="color: #ff0000;">'sampledb.grouping.key_two'</span> isn<span style="color: #ff0000;">'t in GROUP BY</span></pre></div></div>

<p>If you want to prevent indeterminate results and don't use expressions in the <code>GROUP BY</code> clause, you can add the <code>ONLY_FULL_GROUP_BY</code> mode to your <code>SQL_MODE</code> system variable. You can do that during a session with the following syntax:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SET</span> SQL_MODE<span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> CONCAT<span style="color: #66cc66;">&#40;</span>@@sql_mode<span style="color: #66cc66;">,</span><span style="color: #ff0000;">',ONLY_FULL_GROUP_BY'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p>Or, you can start the <code>mysqld</code> with the following option:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">mysqld --sql_mode=<span style="color: #ff0000;">&quot;sql_mode1,sql_mode2, ... ,sql_mode(n+1)&quot;</span></pre></div></div>

<p>A better alternative, is to add it to the <code>my.cnf</code> configuration file on Linux, or <code>my.ini</code> configuration file on Windows. You can add it to this line, which is done at the end of the line.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Set the SQL mode to strict</span>
sql-mode=<span style="color: #ff0000;">&quot;STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY&quot;</span></pre></div></div>

<p>If you opt for changing it at the server configuration file, you must stop and restart the <code>mysqld</code> process. You can do that on Windows from the command line, like this on Windows provide the service name is <code>mysql</code>. If you've set the Windows service to <code>mysql51</code>, then you need to substitute <code>mysql51</code> for <code>mysql</code>.</p>
<p><span style="font-size:115%"><strong>Hidden Column Results</strong></span></p>
<p>A hidden column result, is a result generated by an expression in the <code>GROUP BY</code> clause. The following is a query that lets you sum transactions by the month name. This is supported by the default behavior of <em>hidden columns</em>.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>   il<span style="color: #66cc66;">.</span>month <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;MON-YEAR&quot;</span>
<span style="color: #66cc66;">,</span>        il<span style="color: #66cc66;">.</span>base <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;BASE&quot;</span>
<span style="color: #66cc66;">,</span>        il<span style="color: #66cc66;">.</span>plus10 <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;10_PLUS&quot;</span>
<span style="color: #66cc66;">,</span>        il<span style="color: #66cc66;">.</span>plus20 <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;20_PLUS&quot;</span>
<span style="color: #993333; font-weight: bold;">FROM</span>    <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span>   CONCAT<span style="color: #66cc66;">&#40;</span>UPPER<span style="color: #66cc66;">&#40;</span>SUBSTRING<span style="color: #66cc66;">&#40;</span>MONTHNAME<span style="color: #66cc66;">&#40;</span>t<span style="color: #66cc66;">.</span>transaction_date<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'-'</span><span style="color: #66cc66;">,</span>EXTRACT<span style="color: #66cc66;">&#40;</span>YEAR <span style="color: #993333; font-weight: bold;">FROM</span> t<span style="color: #66cc66;">.</span>transaction_date<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> month
         <span style="color: #66cc66;">,</span>        MONTH<span style="color: #66cc66;">&#40;</span>t<span style="color: #66cc66;">.</span>transaction_date<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> sortkey
         <span style="color: #66cc66;">,</span>        LPAD<span style="color: #66cc66;">&#40;</span>CONCAT<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'$'</span><span style="color: #66cc66;">,</span>FORMAT<span style="color: #66cc66;">&#40;</span>SUM<span style="color: #66cc66;">&#40;</span>t<span style="color: #66cc66;">.</span>transaction_amount<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">1.0</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">' '</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> base
         <span style="color: #66cc66;">,</span>        LPAD<span style="color: #66cc66;">&#40;</span>CONCAT<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'$'</span><span style="color: #66cc66;">,</span>FORMAT<span style="color: #66cc66;">&#40;</span>SUM<span style="color: #66cc66;">&#40;</span>t<span style="color: #66cc66;">.</span>transaction_amount<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">1.1</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">' '</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> plus10
         <span style="color: #66cc66;">,</span>        LPAD<span style="color: #66cc66;">&#40;</span>CONCAT<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'$'</span><span style="color: #66cc66;">,</span>FORMAT<span style="color: #66cc66;">&#40;</span>SUM<span style="color: #66cc66;">&#40;</span>t<span style="color: #66cc66;">.</span>transaction_amount<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">1.2</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">' '</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> plus20
         <span style="color: #993333; font-weight: bold;">FROM</span>     transaction t
         <span style="color: #993333; font-weight: bold;">WHERE</span>    EXTRACT<span style="color: #66cc66;">&#40;</span>YEAR <span style="color: #993333; font-weight: bold;">FROM</span> t<span style="color: #66cc66;">.</span>transaction_date<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">2009</span>
         <span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> CONCAT<span style="color: #66cc66;">&#40;</span>UPPER<span style="color: #66cc66;">&#40;</span>SUBSTRING<span style="color: #66cc66;">&#40;</span>MONTHNAME<span style="color: #66cc66;">&#40;</span>t<span style="color: #66cc66;">.</span>transaction_date<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'-'</span><span style="color: #66cc66;">,</span>EXTRACT<span style="color: #66cc66;">&#40;</span>YEAR <span style="color: #993333; font-weight: bold;">FROM</span> t<span style="color: #66cc66;">.</span>transaction_date<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
         <span style="color: #66cc66;">,</span>        MONTH<span style="color: #66cc66;">&#40;</span>t<span style="color: #66cc66;">.</span>transaction_date<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> il
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> il<span style="color: #66cc66;">.</span>sortkey;</pre></td></tr></table></div>

<p>When you add the <code>ONLY_FULL_GROUP_BY</code> mode to your <code>SQL_MODE</code> system variable, you disallow this type of behavior and the query would no longer work. It would return the following error:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">ERROR <span style="color: #cc66cc;">1055</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">42000</span><span style="color: #66cc66;">&#41;</span>: <span style="color: #ff0000;">'sampledb.t.transaction_date'</span> isn<span style="color: #ff0000;">'t in GROUP BY</span></pre></div></div>

<div class="dropdownbox" style="padding-left:20px;background:#FFFFFF">
<p title="Click to see content ..." class="dropdownclick"><strong><em><span style="font-size:125%">Complete Code Sample</span></em></strong> <span>&darr;</span></p>
<p style="clear: both">
Expand this section to see the sample working code for indeterminate results.</p>
<div>
<p>This builds the <code>GROUPING</code> table, inserts nine rows, and tests it before and after setting the variable in the session. The change reverts after you exit and re-enter the database.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Conditionally drop sample table.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'DROP TABLE IF EXISTS grouping'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Statement&quot;</span>;
<span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> grouping;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create sample table.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'CREATE TABLE grouping'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Statement&quot;</span>;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> grouping
<span style="color: #66cc66;">&#40;</span> key_one   CHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> key_two   CHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> counter   INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Insert nine rows into the sample table.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'INSERT INTO grouping'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Statement&quot;</span>
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> grouping <span style="color: #993333; font-weight: bold;">VALUES</span>
<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'One'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Uno-1'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Two'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Due-1'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Three'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Tre-1'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'One'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Uno-2'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Two'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Due-2'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Three'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Tre-2'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'One'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Uno-3'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Two'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Due-3'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Three'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Tre-3'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Query with hidden columns, no enforcement on non-aggregate columns.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'SELECT non-aggregates FROM grouping with hidden columns'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Statement&quot;</span>;
<span style="color: #993333; font-weight: bold;">SELECT</span> key_one<span style="color: #66cc66;">,</span> key_two<span style="color: #66cc66;">,</span> SUM<span style="color: #66cc66;">&#40;</span>counter<span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">FROM</span>   grouping
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> key_one;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Check current system mode variable assignment.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'SELECT @@sql_mode'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Statement&quot;</span>;
<span style="color: #993333; font-weight: bold;">SELECT</span> @@sql_mode;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Append the mode to the existing system mode variable.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'SET SQL_MODE=(SELECT ...)'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Statement&quot;</span>;
<span style="color: #993333; font-weight: bold;">SET</span> SQL_MODE<span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> CONCAT<span style="color: #66cc66;">&#40;</span>@@sql_mode<span style="color: #66cc66;">,</span><span style="color: #ff0000;">',ONLY_FULL_GROUP_BY'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Check modified system mode variable assignment.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'SELECT @@sql_mode'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Statement&quot;</span>;
<span style="color: #993333; font-weight: bold;">SELECT</span> @@sql_mode;</pre></div></div>

</div>
</div>
<p style="clear:both">
]]></content:encoded>
			<wfw:commentRss>http://blog.mclaughlinsoftware.com/2010/03/10/mysql-standard-group-by/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Wrap a cursor function</title>
		<link>http://blog.mclaughlinsoftware.com/2010/03/07/wrap-a-cursor-function/</link>
		<comments>http://blog.mclaughlinsoftware.com/2010/03/07/wrap-a-cursor-function/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 03:14:55 +0000</pubDate>
		<dc:creator>maclochlainn</dc:creator>
				<category><![CDATA[OPAL]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Oracle XE]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.mclaughlinsoftware.com/?p=3584</guid>
		<description><![CDATA[A Gauss posted a question on my ]]></description>
			<content:encoded><![CDATA[<p>A <em>Gauss</em> posted a question on my <a href="http://blog.mclaughlinsoftware.com/plsql-programming/pipelined-functions-plsql-tables/"pipelined table post</a> from last year&#8217;s Utah Oracle User&#8217;s Group Training Days presentation. If I understood his question correctly, this should help him work with his legacy code. Honestly, as I wrote the example something <a href="http://www.oreillynet.com/pub/au/1056"><em>Bryn Llewellyn</em></a> said kept banging around in my head, &#8220;Just because we can, doesn&#8217;t mean we should.&#8221; He was speaking of writing poorly engineered code.</p>
<p>Sometimes, we don&#8217;t get the opportunity to re-factor existing code. That leaves us with writing wrappers that aren&#8217;t pretty or effective. A realization and preface to showing everyone how to accomplish these tasks, and perhaps a watch out warning if you choose this path. I suspect that there may be a better way but I don&#8217;t know their code tree.</p>
<p>Here&#8217;s the question, as I understand it. They&#8217;ve got a library function in PL/SQL that returns a system reference cursor and is principally consumed by an external Java program. This type of architecture is more or less an Adapter OOAD pattern that I wrote about <a href="http://blog.mclaughlinsoftware.com/2008/10/31/adapter-or-not-adapter-thats-the-question/">here</a>, over a year and a half ago. The question comes to how to you wrap this approach and make it work in PL/SQL natively too.</p>
<p>The answer depends on some earlier posts because I don&#8217;t have a great deal of time to write new examples. It uses a <code>COMMON_LOOKUP</code> table, which is more or less a bunch of small tables grouped into a big table for use in <em>user interaction</em> forms. That way the values don&#8217;t get lost in a large code base and are always consistently maintained. These types of tables exist in all major ERP and CRM applications.</p>
<p>The base code for the example is <a href="http://blog.mclaughlinsoftware.com/2009/03/23/object-record-collections/">found here</a>, where I discussed how you can effectively use object tables &#8211; collections of user-defined object types (Oracle 9iR2 forward if I remember correctly). You can grab the full code at the bottom of the page by clicking the <strong><em>Code Script</em></strong> widget to unfold the code. That code also depends on the <a href="http://www.mhprofessional.com/product.php?isbn=0071494456&#038;cat=112">Oracle Database 11g PL/SQL Programming downloadable code</a>, which you can download by clicking the link to the zip file location.</p>
<p>Here are the steps to wrap a function that returns a PL/SQL reference cursor so that it can also return a PL/SQL associative array.</p>
<ol start="1">
<li>Create a package specification to hold all the components that are required to manage the process. Assuming that they may have anchored the system reference cursor to something other than a table like a shared cursor, which is a cumbersome implementation design. (I actually chose to exclude this from the book because it&#8217;s a stretch as a good coding practice. At least, it is from my perspective. Also, I couldn&#8217;t find an example in the Oracle documentation, which led me to believe they didn&#8217;t think it&#8217;s a great idea either or I could have glossed over it.) You should note that the PL/SQL <code>RECORD</code>, Associative Array (collection), and the <code>REF CURSOR</code> are defined in this package specification.</li>
</ol>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Create a package to hold the PL/SQL record structure.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">REPLACE</span> PACKAGE example <span style="color: #993333; font-weight: bold;">IS</span>
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Force cursors to be read as if empty every time.</span>
  PRAGMA SERIALLY_REUSABLE;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Package-level record structure that mimics SQL object type.</span>
  TYPE common_lookup_record <span style="color: #993333; font-weight: bold;">IS</span> RECORD
  <span style="color: #66cc66;">&#40;</span> common_lookup_id      NUMBER
  <span style="color: #66cc66;">,</span> common_lookup_type    VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">,</span> common_lookup_meaning VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Package-level collection that mimics SQL object table.</span>
  TYPE common_lookup_record_table <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">TABLE</span> OF common_lookup_record
  <span style="color: #993333; font-weight: bold;">INDEX</span> <span style="color: #993333; font-weight: bold;">BY</span> PLS_INTEGER;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Cursor structure to support a strongly-typed reference cursor.</span>
  CURSOR c <span style="color: #993333; font-weight: bold;">IS</span>
    <span style="color: #993333; font-weight: bold;">SELECT</span>   common_lookup_id
    <span style="color: #66cc66;">,</span>        common_lookup_type
    <span style="color: #66cc66;">,</span>        common_lookup_meaning
    <span style="color: #993333; font-weight: bold;">FROM</span>     common_lookup;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Package-level strongly-typed system reference cursor.</span>
  TYPE cursor_lookup <span style="color: #993333; font-weight: bold;">IS</span> REF CURSOR <span style="color: #993333; font-weight: bold;">RETURN</span> c%ROWTYPE;
&nbsp;
END;
<span style="color: #66cc66;">/</span></pre></div></div>

<ol start="2">
<li>Write a function to return a strongly typed system reference cursor that&#8217;s anchored to a cursor defined in the package. This is fairly straightforward when the package specification is done right. You should notice right away that anchoring the original cursor in the package was a <em>horrible</em> practice because you must repeat it all again in the function. In my opinion, you shouldn&#8217;t anchor any system reference cursor explicitly to anything other than a table. The cursor could have used the generic weak cursor data type &#8211; <code>SYS_REFCURSOR</code>. Doing so, saves all the extra lines required by a potential shared cursor.</li>
</ol>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">REPLACE</span> <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_common_lookup_cursor
<span style="color: #66cc66;">&#40;</span> table_name VARCHAR2<span style="color: #66cc66;">,</span> column_name VARCHAR2<span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">RETURN</span> example<span style="color: #66cc66;">.</span>cursor_lookup <span style="color: #993333; font-weight: bold;">IS</span>
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Define a local variable of a strongly-typed reference cursor.</span>
  lv_cursor EXAMPLE<span style="color: #66cc66;">.</span>CURSOR_LOOKUP;
&nbsp;
BEGIN
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Open the cursor from a static cursor</span>
  OPEN lv_cursor <span style="color: #993333; font-weight: bold;">FOR</span>
    <span style="color: #993333; font-weight: bold;">SELECT</span> common_lookup_id
    <span style="color: #66cc66;">,</span>      common_lookup_type
    <span style="color: #66cc66;">,</span>      common_lookup_meaning
    <span style="color: #993333; font-weight: bold;">FROM</span>   common_lookup
    <span style="color: #993333; font-weight: bold;">WHERE</span>  common_lookup_table <span style="color: #66cc66;">=</span> table_name
    <span style="color: #993333; font-weight: bold;">AND</span>    common_lookup_column <span style="color: #66cc66;">=</span> column_name;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Return the cursor handle.</span>
  <span style="color: #993333; font-weight: bold;">RETURN</span> lv_cursor;
&nbsp;
END;
<span style="color: #66cc66;">/</span></pre></div></div>

<ol start="3">
<li>Write a wrapper function that takes the reference cursor as a formal parameter and returns an Associative Array. You should note that this can&#8217;t be called from a SQL context. You must only use it in a PL/SQL context because system reference cursors are PL/SQL only data types.</li>
</ol>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">REPLACE</span> <span style="color: #993333; font-weight: bold;">FUNCTION</span> convert_common_lookup_cursor
<span style="color: #66cc66;">&#40;</span> pv_cursor EXAMPLE<span style="color: #66cc66;">.</span>CURSOR_LOOKUP<span style="color: #66cc66;">&#41;</span> 
<span style="color: #993333; font-weight: bold;">RETURN</span> example<span style="color: #66cc66;">.</span>common_lookup_record_table <span style="color: #993333; font-weight: bold;">IS</span>
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Declare a local counter variable.</span>
  counter INTEGER :<span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Local PL/SQL-only variable.</span>
  out_record  EXAMPLE<span style="color: #66cc66;">.</span>COMMON_LOOKUP_RECORD;
  out_table   EXAMPLE<span style="color: #66cc66;">.</span>COMMON_LOOKUP_RECORD_TABLE;
&nbsp;
BEGIN
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Grab the cursor wrapper and return values to a PL/SQL-only record collection.</span>
  LOOP
    FETCH pv_cursor <span style="color: #993333; font-weight: bold;">INTO</span> out_record;
    EXIT WHEN pv_cursor%NOTFOUND;
&nbsp;
    <span style="color: #808080; font-style: italic;">-- Assign it one row at a time to an associative array.</span>
    out_table<span style="color: #66cc66;">&#40;</span>counter<span style="color: #66cc66;">&#41;</span> :<span style="color: #66cc66;">=</span> out_record;
&nbsp;
    <span style="color: #808080; font-style: italic;">-- Increment the counter.</span>
    counter :<span style="color: #66cc66;">=</span> counter <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span>;
&nbsp;
  END LOOP;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Return the record collection.</span>
  <span style="color: #993333; font-weight: bold;">RETURN</span> out_table;
&nbsp;
END;
<span style="color: #66cc66;">/</span></pre></div></div>

<ol start="4">
<li>You can test the program in an anonymous block, like the one below. It defines a local Associative Array variable and then assigns the system reference cursor through the wrapper.</li>
</ol>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Open the session to see output from PL/SQL blocks.</span>
<span style="color: #993333; font-weight: bold;">SET</span> SERVEROUTPUT <span style="color: #993333; font-weight: bold;">ON</span>
&nbsp;
DECLARE
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Define a local associative array.</span>
  process_table  EXAMPLE<span style="color: #66cc66;">.</span>COMMON_LOOKUP_RECORD_TABLE;
&nbsp;
BEGIN
  <span style="color: #808080; font-style: italic;">-- Print title block.</span>
  dbms_output<span style="color: #66cc66;">.</span>put_line<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Converting a SYS_REFCURSOR to TABLE'</span><span style="color: #66cc66;">&#41;</span>;
  dbms_output<span style="color: #66cc66;">.</span>put_line<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'---------------------------------------------------'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Run the dynamic variables through the cursor generating function and then convert it.</span>
  process_table :<span style="color: #66cc66;">=</span> convert_common_lookup_cursor<span style="color: #66cc66;">&#40;</span>get_common_lookup_cursor<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'ITEM'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'ITEM_TYPE'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Read the content of the Associative array.  </span>
  <span style="color: #993333; font-weight: bold;">FOR</span> i <span style="color: #993333; font-weight: bold;">IN</span> 1<span style="color: #66cc66;">..</span>process_table<span style="color: #66cc66;">.</span>COUNT LOOP
    dbms_output<span style="color: #66cc66;">.</span>put<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'['</span><span style="color: #66cc66;">||</span>process_table<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>common_lookup_id<span style="color: #66cc66;">||</span><span style="color: #ff0000;">']'</span><span style="color: #66cc66;">&#41;</span>;
    dbms_output<span style="color: #66cc66;">.</span>put<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'['</span><span style="color: #66cc66;">||</span>process_table<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>common_lookup_type<span style="color: #66cc66;">||</span><span style="color: #ff0000;">']'</span><span style="color: #66cc66;">&#41;</span>;
    dbms_output<span style="color: #66cc66;">.</span>put_line<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'['</span><span style="color: #66cc66;">||</span>process_table<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>common_lookup_meaning<span style="color: #66cc66;">||</span><span style="color: #ff0000;">']'</span><span style="color: #66cc66;">&#41;</span>;
  END LOOP;
&nbsp;
END;
<span style="color: #66cc66;">/</span></pre></div></div>

<p>I hope this answers Gauss&#8217;s question. While writing it, I could envision another question that might pop-up. How do you convert an object table type to a PL/SQL context. It was an omission not to include it in that <a href="http://blog.mclaughlinsoftware.com/2009/03/23/object-record-collections/">original post on object table types</a>. Here&#8217;s how you wrap an object table type into a PL/SQL scope collection.</p>
<p>You might have guessed. It&#8217;s done with another wrapper function. At least this is the easiest way to convert the SQL data type to a PL/SQL data type that I see. If you&#8217;ve another approach, a better way, let us know.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">REPLACE</span> <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_common_lookup_record_table
<span style="color: #66cc66;">&#40;</span> table_name  VARCHAR2
<span style="color: #66cc66;">,</span> column_name VARCHAR2 <span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">RETURN</span> example<span style="color: #66cc66;">.</span>common_lookup_record_table <span style="color: #993333; font-weight: bold;">IS</span>
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Declare a local counter variable.</span>
  counter INTEGER :<span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Define a dynamic cursor that takes two formal parameters.</span>
  CURSOR c <span style="color: #66cc66;">&#40;</span>table_name_in VARCHAR2<span style="color: #66cc66;">,</span> table_column_name_in VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">IS</span>
    <span style="color: #993333; font-weight: bold;">SELECT</span>   <span style="color: #66cc66;">*</span>
    <span style="color: #993333; font-weight: bold;">FROM</span>     <span style="color: #993333; font-weight: bold;">TABLE</span><span style="color: #66cc66;">&#40;</span>get_common_lookup_object_table<span style="color: #66cc66;">&#40;</span>UPPER<span style="color: #66cc66;">&#40;</span>table_name_in<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>UPPER<span style="color: #66cc66;">&#40;</span>table_column_name_in<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- A local PL/SQL-only collection variable.</span>
  list EXAMPLE<span style="color: #66cc66;">.</span>COMMON_LOOKUP_RECORD_TABLE;
&nbsp;
BEGIN
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Grab the cursor wrapper and return values to a PL/SQL-only record collection.</span>
  <span style="color: #993333; font-weight: bold;">FOR</span> i <span style="color: #993333; font-weight: bold;">IN</span> c<span style="color: #66cc66;">&#40;</span>table_name<span style="color: #66cc66;">,</span> column_name<span style="color: #66cc66;">&#41;</span> LOOP
    list<span style="color: #66cc66;">&#40;</span>counter<span style="color: #66cc66;">&#41;</span> :<span style="color: #66cc66;">=</span> i;
    counter :<span style="color: #66cc66;">=</span> counter <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span>;
  END LOOP;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Return the record collection.</span>
  <span style="color: #993333; font-weight: bold;">RETURN</span> list;
END get_common_lookup_record_table;
<span style="color: #66cc66;">/</span></pre></div></div>

<p>You can then test this in an anonymous block, like so:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Open the session to see output from PL/SQL blocks.</span>
<span style="color: #993333; font-weight: bold;">SET</span> SERVEROUTPUT <span style="color: #993333; font-weight: bold;">ON</span>
&nbsp;
DECLARE
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Declare a local PL/SQL-only collection and assign the value from the function call.</span>
  list EXAMPLE<span style="color: #66cc66;">.</span>COMMON_LOOKUP_RECORD_TABLE;
&nbsp;
  BEGIN
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Print title block.</span>
  dbms_output<span style="color: #66cc66;">.</span>put_line<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Converting a SQL Collection to a PL/SQL Collection'</span><span style="color: #66cc66;">&#41;</span>;
  dbms_output<span style="color: #66cc66;">.</span>put_line<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'---------------------------------------------------'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Assign wrapped SQL collection to a PL/SQL-only collection.</span>
  list :<span style="color: #66cc66;">=</span> get_common_lookup_record_table<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'ITEM'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'ITEM_TYPE'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Call the record wrapper function.</span>
  <span style="color: #993333; font-weight: bold;">FOR</span> i <span style="color: #993333; font-weight: bold;">IN</span> 1<span style="color: #66cc66;">..</span>list<span style="color: #66cc66;">.</span>COUNT LOOP
    dbms_output<span style="color: #66cc66;">.</span>put<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'['</span><span style="color: #66cc66;">||</span>list<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>common_lookup_id<span style="color: #66cc66;">||</span><span style="color: #ff0000;">']'</span><span style="color: #66cc66;">&#41;</span>;
    dbms_output<span style="color: #66cc66;">.</span>put<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'['</span><span style="color: #66cc66;">||</span>list<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>common_lookup_type<span style="color: #66cc66;">||</span><span style="color: #ff0000;">']'</span><span style="color: #66cc66;">&#41;</span>;
    dbms_output<span style="color: #66cc66;">.</span>put_line<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'['</span><span style="color: #66cc66;">||</span>list<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>common_lookup_meaning<span style="color: #66cc66;">||</span><span style="color: #ff0000;">']'</span><span style="color: #66cc66;">&#41;</span>;
  END LOOP;
&nbsp;
END;
<span style="color: #66cc66;">/</span></pre></div></div>

<p>As always, I hope this helps somebody without paying a fee for content. <img src='http://blog.mclaughlinsoftware.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mclaughlinsoftware.com/2010/03/07/wrap-a-cursor-function/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Stable set of rows?</title>
		<link>http://blog.mclaughlinsoftware.com/2010/03/05/stable-set-of-rows/</link>
		<comments>http://blog.mclaughlinsoftware.com/2010/03/05/stable-set-of-rows/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 07:43:20 +0000</pubDate>
		<dc:creator>maclochlainn</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Oracle XE]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.mclaughlinsoftware.com/?p=3573</guid>
		<description><![CDATA[My students are into the upload lab and they&#8217;ve encountered the wonderful ORA-30926 error from a MERGE statement. An example of the MERGE for an upload is in this earlier blog post.
This is the wonderful error message, which doesn&#8217;t seem to have meaning for many. The key is the non-deterministic where clauses phrase. That phrase [...]]]></description>
			<content:encoded><![CDATA[<p>My students are into the upload lab and they&#8217;ve encountered the wonderful <code>ORA-30926</code> error from a <code>MERGE</code> statement. An example of the <code>MERGE</code> for an upload is in <a href="http://blog.mclaughlinsoftware.com/2010/02/23/merge-statement-for-etl/">this earlier blog post</a>.</p>
<p>This is the wonderful error message, which doesn&#8217;t seem to have meaning for many. The key is the <em>non-deterministic where clauses</em> phrase. That phrase means that the the query inside the <code>USING</code> clause returns a non-unique set of rows. The returned rows can&#8217;t be matched uniquely against the target table in the <code>ON</code> clause. The <code>ON</code> clause is where the <code>MERGE</code> statment matches the source query&#8217;s rows against the target table&#8217;s rows.</p>
<p>The problem is very much like when you write what you think is a single-row subquery but find out it&#8217;s actually a multiple-row subquery when it return an <code>ORA-01422</code> error in Oracle.</p>
<p>As a rule, I&#8217;ve found that using the <code>DISTINCT</code> operator in the source <code>SELECT</code> statement fixes it most of the time. Alternatively, you need to re-examine the logic of your <code>WHERE</code> clause.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">Error: ORA<span style="color: #66cc66;">-</span><span style="color: #cc66cc;">30926</span>
Text:  Unable <span style="color: #993333; font-weight: bold;">TO</span> get a stable <span style="color: #993333; font-weight: bold;">SET</span> of rows <span style="color: #993333; font-weight: bold;">IN</span> the source <span style="color: #993333; font-weight: bold;">TABLES</span><span style="color: #66cc66;">.</span>
<span style="color: #808080; font-style: italic;">--------------------------------------------------------------------</span>
Cause:  A stable <span style="color: #993333; font-weight: bold;">SET</span> of rows could <span style="color: #993333; font-weight: bold;">NOT</span> be got because of large dml 
        activity <span style="color: #993333; font-weight: bold;">OR</span> a non<span style="color: #66cc66;">-</span>deterministic <span style="color: #993333; font-weight: bold;">WHERE</span> clause<span style="color: #66cc66;">.</span> 
&nbsp;
Action: Remove any non<span style="color: #66cc66;">-</span>deterministic <span style="color: #993333; font-weight: bold;">WHERE</span> clauses <span style="color: #993333; font-weight: bold;">AND</span> reissue the dml<span style="color: #66cc66;">.</span></pre></div></div>

<p>Hope this helps my students and others &#8230; <img src='http://blog.mclaughlinsoftware.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mclaughlinsoftware.com/2010/03/05/stable-set-of-rows/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VMWare Fusion NAT</title>
		<link>http://blog.mclaughlinsoftware.com/2010/03/01/vmware-fusion-nat/</link>
		<comments>http://blog.mclaughlinsoftware.com/2010/03/01/vmware-fusion-nat/#comments</comments>
		<pubDate>Tue, 02 Mar 2010 05:41:34 +0000</pubDate>
		<dc:creator>maclochlainn</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[VMWare]]></category>

		<guid isPermaLink="false">http://blog.mclaughlinsoftware.com/?p=3564</guid>
		<description><![CDATA[This is to correct an earlier omission and provide instructions for configuring static and dynamic IP addresses for Virtual Machines runing on VMWare Fusion on Mac OS X. The benefit of static IP address is important for those installing multiple development and test instances of Oracle Databases in virtual environments.
Back in September 2008, I blogged [...]]]></description>
			<content:encoded><![CDATA[<p>This is to correct an earlier omission and provide instructions for configuring static and dynamic IP addresses for Virtual Machines runing on VMWare Fusion on Mac OS X. The benefit of static IP address is important for those installing multiple development and test instances of Oracle Databases in virtual environments.</p>
<p>Back in September 2008, I blogged about how to configure the <a href="http://blog.mclaughlinsoftware.com/how-to-configure-mac-os-x-as-an-oracle-client/">Oracle Client 10g on Mac OS X</a>. It&#8217;s been used a lot but in hindsight it could have been organized more effectively. One thing that I noticed (through somebody bringing it to my attention) is that explaining the VMWare Fusion component by itself would have been more helpful then listing the IP ranges for releases through the date of my post. Hopefully, this corrects that omission.</p>
<p><span style="font-size:125%;font-weight:bold">VMWare NAT Configuration</span></p>
<p>There are only a few steps that you must do. These are they:</p>
<ol>
<li>Read the subnet value from the <code>dhcpd.conf</code> file.</li>
<li>Dynamic IP address only require you to set the guest operating system to DHCP.</li>
<li>Static IP addresses require you to set the IP address, subnet, default gateway, and preferred DNS server.</li>
<li>Add assigned IP address and the guest operating system <code>hostname</code> to your Mac OS X <code>/etc/hosts</code> file.</li>
</ol>
<p>The next sections gives the details of where to find all the things that you may want to experiment with. Remember if you make an error that damages these configuration files, you have to fix it or re-install VMWare Fusion.</p>
<p><span style="font-size:125%;font-weight:bold">VMWare NAT Files and Configurations</span></p>
<p>You can find the IP ranges for the Network Address Translation (NAT) here:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">/</span>Library<span style="color: #000000; font-weight: bold;">/</span>Application Support<span style="color: #000000; font-weight: bold;">/</span>VMware Fusion<span style="color: #000000; font-weight: bold;">/</span>vmnet8<span style="color: #000000; font-weight: bold;">/</span>dhcpd.conf</pre></div></div>

<p>You can open the file for editing like this:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">vi</span> <span style="color: #ff0000;">&quot;/Library/Application Support/VMware Fusion/vmnet8/dhcpd.conf&quot;</span></pre></div></div>

<p>The file contains the subnet, which I&#8217;ve found changes with release. You can configure this file and assign fixed addresses in it. However, you don&#8217;t need to install fixed addresses in this file unless you want to reserve addresses in the dynamic range.</p>
<p>The dynamic range is between <code>xxx.xxx.xxx.128</code> and <code>xxx.xxx.xxx.254</code>. The range of <code>xxx.xxx.xxx.3</code> to <code>xxx.xxx.xxx.127</code> is available for static IP addresses. You can set a static IP address inside the native operating system of the VM.</p>
<p>The <code>dhcpd.conf</code> file with it&#8217;s instructions, looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Configuration file for ISC 2.0 vmnet-dhcpd operating on vmnet8.</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># This file was automatically generated by the VMware configuration program.</span>
<span style="color: #666666; font-style: italic;"># See Instructions below if you want to modify it.</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># We set domain-name-servers to make some DHCP clients happy</span>
<span style="color: #666666; font-style: italic;"># (dhclient as configured in SuSE, TurboLinux, etc.).</span>
<span style="color: #666666; font-style: italic;"># We also supply a domain name to make pump (Red Hat 6.x) happy.</span>
<span style="color: #666666; font-style: italic;">#</span>
&nbsp;
<span style="color: #666666; font-style: italic;">###### VMNET DHCP Configuration. Start of &quot;DO NOT MODIFY SECTION&quot; #####</span>
<span style="color: #666666; font-style: italic;"># Modification Instructions: This section of the configuration file contains</span>
<span style="color: #666666; font-style: italic;"># information generated by the configuration program. Do not modify this</span>
<span style="color: #666666; font-style: italic;"># section.</span>
<span style="color: #666666; font-style: italic;"># You are free to modify everything else. Also, this section must start </span>
<span style="color: #666666; font-style: italic;"># on a new line </span>
<span style="color: #666666; font-style: italic;"># This file will get backed up with a different name in the same directory </span>
<span style="color: #666666; font-style: italic;"># if this section is edited and you try to configure DHCP again.</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Written at: 02/18/2010 23:30:54</span>
allow unknown-clients;
default-lease-time <span style="color: #000000;">1800</span>;                <span style="color: #666666; font-style: italic;"># default is 30 minutes</span>
max-lease-time <span style="color: #000000;">7200</span>;                    <span style="color: #666666; font-style: italic;"># default is 2 hours</span>
&nbsp;
subnet 172.16.123.0 netmask 255.255.255.0 <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	range 172.16.123.128 172.16.123.254;
	option broadcast-address 172.16.123.255;
	option domain-name-servers 172.16.123.2;
	option domain-name localdomain;
	default-lease-time <span style="color: #000000;">1800</span>;                <span style="color: #666666; font-style: italic;"># default is 30 minutes</span>
	max-lease-time <span style="color: #000000;">7200</span>;                    <span style="color: #666666; font-style: italic;"># default is 2 hours</span>
	option routers 172.16.123.2;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
host vmnet8 <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	hardware ethernet 00:<span style="color: #000000;">50</span>:<span style="color: #000000;">56</span>:C0:00:08;
	fixed-address 172.16.123.1;
	option domain-name-servers 0.0.0.0;
	option domain-name <span style="color: #ff0000;">&quot;&quot;</span>;
	option routers 0.0.0.0;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #666666; font-style: italic;">####### VMNET DHCP Configuration. End of &quot;DO NOT MODIFY SECTION&quot; #######</span></pre></div></div>

<p>Unless you&#8217;ve changed the location of your VM repository on your Mac OS X, you can set a fixed-address for the virtual machine. You add the following lines at the bottom of the <code>dhcpd.conf</code> file:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">host mclaughlinxp32 <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	hardware ethernet 00:0c:<span style="color: #000000;">29</span>:<span style="color: #000000;">55</span>:<span style="color: #000000;">38</span>:1b;
        fixed-address 172.16.123.21;
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>You pick whichever IP address you&#8217;d like to use. You also need to configure the guest opearting system in the VM with that same IP address. You can find the <em>ethernet hardware</em> value in the following file:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">~<span style="color: #000000; font-weight: bold;">/</span>Documents<span style="color: #000000; font-weight: bold;">/</span>Virtual Machines<span style="color: #000000; font-weight: bold;">/</span>VMName<span style="color: #000000; font-weight: bold;">/</span>VMName.vmx</pre></div></div>

<p>You can open the file and hunt for it, or simply run this command from the directory where the file exists:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">grep</span> ethernet0.generatedAddress <span style="color: #000000; font-weight: bold;">*</span>.vmx</pre></div></div>

<p>As always, I hope this helps some folks.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mclaughlinsoftware.com/2010/03/01/vmware-fusion-nat/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Debugging MySQL Procedures</title>
		<link>http://blog.mclaughlinsoftware.com/2010/02/27/debugging-mysql-procedures/</link>
		<comments>http://blog.mclaughlinsoftware.com/2010/02/27/debugging-mysql-procedures/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 05:01:51 +0000</pubDate>
		<dc:creator>maclochlainn</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[MAMP]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Stored Procedures]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.mclaughlinsoftware.com/?p=3558</guid>
		<description><![CDATA[In my second database class we focus on PL/SQL but we&#8217;ve begun highlighting the alternatives in MySQL and SQL Server. A student asked how they could debug runtime variable values in a MySQL Stored Function or Procedure (or subroutines according to some documentation).
In Oracle, we debug with the DBMS_OUTPUT package. Packages, like DBMS_OUTPUT hold related [...]]]></description>
			<content:encoded><![CDATA[<p>In my second database class we focus on PL/SQL but we&#8217;ve begun highlighting the alternatives in MySQL and SQL Server. A student asked how they could debug runtime variable values in a MySQL Stored Function or Procedure (or subroutines according to some documentation).</p>
<p>In Oracle, we debug with the <code>DBMS_OUTPUT</code> package. Packages, like <code>DBMS_OUTPUT</code> hold related functions and procedures, and are a corollary to <code>System.out.println()</code> in Java.</p>
<p>Before you can see the output at the command-line in Oracle (that is if you&#8217;re not using SQL*Developer or Toad), you must set a SQL*Plus environment variable. These variables don&#8217;t exist in MySQL or SQL Server command-line tools because they never served the function of a report writer like SQL*Plus.</p>
<p>You enable output display in Oracle by setting this in SQL*Plus:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">SQL<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">SET</span> SERVEROUTPUT <span style="color: #993333; font-weight: bold;">ON</span> SIZE <span style="color: #cc66cc;">1000000</span></pre></div></div>

<p>You can test your anonymous or named block. Since MySQL doesn&#8217;t support anonymous named block, the examples using a trivial procedure that prints <em>Hello World!</em> (orginal, right <img src='http://blog.mclaughlinsoftware.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ).</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Create a procedure in Oracle.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">REPLACE</span> PROCEDURE hello_world <span style="color: #993333; font-weight: bold;">IS</span>
BEGIN
  <span style="color: #808080; font-style: italic;">-- Print a word without a line return.</span>
  dbms_output<span style="color: #66cc66;">.</span>put<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Hello '</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #808080; font-style: italic;">-- Print the rest of the phrase and a line return.</span>
  dbms_output<span style="color: #66cc66;">.</span>put_line<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'World!'</span><span style="color: #66cc66;">&#41;</span>;
END;
<span style="color: #66cc66;">/</span>
&nbsp;
<span style="color: #808080; font-style: italic;">-- Call the procedure.</span>
EXECUTE hello_world;</pre></td></tr></table></div>

<p>It&#8217;s seems useless to print the output because it should be evident. MySQL procedures are a bit different because there&#8217;s no <code>OR REPLACE</code> syntax. The equivalent to calling the <code>DBMS_OUTPUT</code> package procedures in MySQL is to simply <em>select a string</em>. Now you can do this with or without the <code>FROM dual</code> clause in MySQL, don&#8217;t we wish we could likewise do that in Oracle. <img src='http://blog.mclaughlinsoftware.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Conditionally drop the procedure.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'DROP PROCEDURE hello_world'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Statement&quot;</span>;
<span style="color: #993333; font-weight: bold;">DROP</span> PROCEDURE <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> hello_world;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Reset the delimiter to write a procedure.</span>
DELIMITER $$
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create a procedure in Oracle.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> PROCEDURE hello_world<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
BEGIN
  <span style="color: #808080; font-style: italic;">-- Print the phrase and a line return.</span>
  <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'Hello World!'</span>;
END;
$$
&nbsp;
<span style="color: #808080; font-style: italic;">-- Reset the delimiter back to a semicolon to work again.</span>
DELIMITER ;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Call the procedure.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'CALL hello_world'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Statement&quot;</span>;
CALL hello_world<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>Originally, I tried to keep this short but somebody wanted an example in a loop. Ouch, loops are so verbose in MySQL. Since I was modifying this post, it seemed like a good idea to put down some guidelines for successful development too.</p>
<p><span style="font-size:125%;font-weight:bold">Guidelines for Development of Procedures</span></p>
<p><em><span style="font-size:110%;font-weight:bold">Declaration Guidelines</span></em></p>
<p>The sequencing of components in MySQL procedures is important. Unlike, PL/SQL, there&#8217;s no declaration block, declarations must be at the top of the execution block. They also must appear in the following order:</p>
<ol start="1">
<li>Variable declarations must go first, you can assign initial values with the <code>DEFAULT</code> keyword. While not required, you should:</li>
</ol>
<div style="padding-left:30px">
<ul>
<li>Consider using something like <code>lv_</code> to identify them as <em>local variables</em> for clarity and support of your code.</li>
<li>Consider grouping local variables that relate to handlers at the bottom of the list of variables.</li>
</ul>
</div>
<ol start="2">
<li>After local variables and before <em>handlers</em>, you put your cursor definitions. You should note that MySQL doesn&#8217;t support explicit dynamic cursors, which means you can&#8217;t define one with a formal signature.</li>
<li>Last in your declaration block, you declare your handler events.</li>
</ol>
<p><em><span style="font-size:110%;font-weight:bold">Execution Guidelines</span></em></p>
<ol start="1">
<li>Variable assignments are made one of two ways:</li>
</ol>
<div style="padding-left:30px">
<ul>
<li>You should start each execution block with a <code>START TRANSACTION</code> and then a <code>SAVEPOINT</code>, which ensures the procedure acts like a cohesive programming unit.</li>
<li>You assign a <code>left_operand = right_operand;</code> as a statement.</li>
<li>You assign a single row cursor output to variables using a <code>SELECT column_list INTO variable_list FROM ...</code>.</li>
</ul>
</div>
<ol start="2">
<li>You must assign values from cursors called in a loop into local variables when you want to use the results in nested SQL statements or loops.</li>
<li>You must reset looping variables, like the <code>fetched</code> control variable at the end of the loop to reuse the handler variable in subsequent loops.</li>
<li>You must assign values to local variables if you want to use them in the exception handler.</li>
<li>If you&#8217;ve started a transaction, don&#8217;t forget to <code>COMMIT</code> your work.</li>
</ol>
<p><em><span style="font-size:110%;font-weight:bold">Exception Guidelines</span></em></p>
<ol start="1">
<li>Leave out the exception handler until you&#8217;ve tested all outcomes, and make sure you document them and add them as potential handlers.</li>
<li>When you deploy exception blocks, they&#8217;re the last element at the bottom of the exception block.</li>
<li>You should consider explicit exception handlers for each error unless the action taken is the same.</li>
<li>You should consider grouping all exception handlers when the action taken is the same.</li>
<li>You should include a <code>ROLLBACK</code> whenever you&#8217;ve performed two or more SQL statements that may modify data.</li>
</ol>
<p>Below is an example for putting debug code inside a loop.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Conditionally drop a sample table.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'DROP TABLE IF EXISTS sample'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Statement&quot;</span>;
<span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> sample;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create a table.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> sample
<span style="color: #66cc66;">&#40;</span> sample_id    INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span>
<span style="color: #66cc66;">,</span> sample_msg   VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Insert into sample.</span>
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> sample <span style="color: #66cc66;">&#40;</span>sample_msg<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span>
 <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Message #1'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Message #2'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Message #3'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Conditionally drop the procedure.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'DROP PROCEDURE debug_loop'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Statement&quot;</span>;
<span style="color: #993333; font-weight: bold;">DROP</span> PROCEDURE <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> debug_loop;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Reset the delimiter to write a procedure.</span>
DELIMITER $$
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create a procedure in Oracle.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> PROCEDURE debug_loop<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
BEGIN
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Declare a counter variable. */</span>
  DECLARE lv_counter INT <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #cc66cc;">1</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Declare local control loop variables. */</span>
  DECLARE lv_sample_id  INT;
  DECLARE lv_sample_msg VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Declare a local variable for a subsequent handler. */</span>
  DECLARE duplicate_key INT <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #cc66cc;">0</span>;
  DECLARE fetched INT <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #cc66cc;">0</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Declare a SQL cursor fabricated from local variables. */</span>  
  DECLARE sample_cursor CURSOR <span style="color: #993333; font-weight: bold;">FOR</span>
    <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> sample;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Declare a duplicate key handler */</span>
  DECLARE CONTINUE HANDLER <span style="color: #993333; font-weight: bold;">FOR</span> <span style="color: #cc66cc;">1062</span> <span style="color: #993333; font-weight: bold;">SET</span> duplicate_key <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Declare a not found record handler to close a cursor loop. */</span>
  DECLARE CONTINUE HANDLER <span style="color: #993333; font-weight: bold;">FOR</span> <span style="color: #993333; font-weight: bold;">NOT</span> FOUND <span style="color: #993333; font-weight: bold;">SET</span> fetched <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Start transaction context. */</span>
  START TRANSACTION;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Set savepoint. */</span>  
  SAVEPOINT all_or_none;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Open a sample cursor. */</span>
  OPEN sample_cursor;
  cursor_sample: LOOP
&nbsp;
    <span style="color: #808080; font-style: italic;">/* Fetch a row at a time. */</span>  
    FETCH sample_cursor
    <span style="color: #993333; font-weight: bold;">INTO</span>  lv_sample_id
    <span style="color: #66cc66;">,</span>     lv_sample_msg;
&nbsp;
    <span style="color: #808080; font-style: italic;">/* Place the catch handler for no more rows found
       immediately after the fetch operation.          */</span>
    <span style="color: #993333; font-weight: bold;">IF</span> fetched <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> THEN LEAVE cursor_sample; END <span style="color: #993333; font-weight: bold;">IF</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">-- Print the cursor values.</span>
    <span style="color: #993333; font-weight: bold;">SELECT</span> CONCAT<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Row #'</span><span style="color: #66cc66;">,</span>lv_counter<span style="color: #66cc66;">,</span><span style="color: #ff0000;">' ['</span><span style="color: #66cc66;">,</span>lv_sample_id<span style="color: #66cc66;">,</span><span style="color: #ff0000;">']['</span><span style="color: #66cc66;">,</span>lv_sample_msg<span style="color: #66cc66;">,</span><span style="color: #ff0000;">']'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Rows&quot;</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">-- Increment counter variable.</span>
    <span style="color: #993333; font-weight: bold;">SET</span> lv_counter <span style="color: #66cc66;">=</span> lv_counter <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span>;
&nbsp;
  END LOOP cursor_sample;
  CLOSE sample_cursor;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* This acts as an exception handling block. */</span>  
  <span style="color: #993333; font-weight: bold;">IF</span> duplicate_key <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> THEN
&nbsp;
    <span style="color: #808080; font-style: italic;">/* This undoes all DML statements to this point in the procedure. */</span>
    ROLLBACK <span style="color: #993333; font-weight: bold;">TO</span> SAVEPOINT all_or_none;
&nbsp;
  END <span style="color: #993333; font-weight: bold;">IF</span>;
&nbsp;
END;
$$
&nbsp;
<span style="color: #808080; font-style: italic;">-- Reset the delimiter back to a semicolon to work again.</span>
DELIMITER ;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Call the procedure.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'CALL debug_loop'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Statement&quot;</span>;
CALL debug_loop<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>This post certainly answers the student question. Hopefully, it also helps other who must migrate Oracle skills to MySQL. Since IBM DB2 has introduced a PL/SQL equivalent, wouldn&#8217;t it be nice if Oracle did that for MySQL. Don&#8217;t tell me if you think that&#8217;s a pipe dream, I&#8217;d like to hope for that change.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mclaughlinsoftware.com/2010/02/27/debugging-mysql-procedures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL Boolean Data Type</title>
		<link>http://blog.mclaughlinsoftware.com/2010/02/26/mysql-boolean-data-type/</link>
		<comments>http://blog.mclaughlinsoftware.com/2010/02/26/mysql-boolean-data-type/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 08:32:16 +0000</pubDate>
		<dc:creator>maclochlainn</dc:creator>
				<category><![CDATA[MAMP]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHPMyAdmin]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.mclaughlinsoftware.com/?p=3544</guid>
		<description><![CDATA[Somebody posted a quick question about the outcome of defining a table with a bool data type in PHPMyAdmin. They were subsequently surprised when they checked the MySQL database and found that it was actually a tinyint(1). The natural question they had was: &#8220;What do you enter &#8211; true/false or 1/0?&#8221;
I promised to post an [...]]]></description>
			<content:encoded><![CDATA[<p>Somebody posted a quick question about the outcome of defining a table with a <code>bool</code> data type in PHPMyAdmin. They were subsequently surprised when they checked the MySQL database and found that it was actually a <code>tinyint(1)</code>. The natural question they had was: &#8220;What do you enter &#8211; true/false or 1/0?&#8221;</p>
<p>I promised to post an answer tonight, and morning counts too. You can enter a <code>true</code> or <code>false</code> because they&#8217;re synonyms for a <code>1</code> or <code>0</code> respectively. <code>TINYINT</code> is the supported data type, and <code>BIT</code>, <code>BOOL</code>, and <code>BOOLEAN</code> are synonyms for the base data type.</p>
<p>Here&#8217;s an example in MySQL:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> data_type <span style="color: #66cc66;">&#40;</span>type bool<span style="color: #66cc66;">&#41;</span>;
&nbsp;
mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">DESCRIBE</span> data_type;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">-------+------------+------+-----+---------+-------+</span>
<span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">FIELD</span> <span style="color: #66cc66;">|</span> Type       <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #66cc66;">|</span> Extra <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">-------+------------+------+-----+---------+-------+</span>
<span style="color: #66cc66;">|</span> type  <span style="color: #66cc66;">|</span> tinyint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">|</span> YES  <span style="color: #66cc66;">|</span>     <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">NULL</span>    <span style="color: #66cc66;">|</span>       <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">-------+------------+------+-----+---------+-------+</span>
&nbsp;
mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> data_type <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span>true<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span>false<span style="color: #66cc66;">&#41;</span>;
&nbsp;
mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> data_type;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">------+</span>
<span style="color: #66cc66;">|</span> type <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">------+</span>
<span style="color: #66cc66;">|</span>    <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">|</span>    <span style="color: #cc66cc;">0</span> <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">------+</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.mclaughlinsoftware.com/2010/02/26/mysql-boolean-data-type/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Aggregation Tutorial</title>
		<link>http://blog.mclaughlinsoftware.com/2010/02/26/sql-aggregation-tutorial/</link>
		<comments>http://blog.mclaughlinsoftware.com/2010/02/26/sql-aggregation-tutorial/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 07:29:46 +0000</pubDate>
		<dc:creator>maclochlainn</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Oracle XE]]></category>
		<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.mclaughlinsoftware.com/?p=3539</guid>
		<description><![CDATA[I&#8217;ve been working on a Basic Aggregation tutorial for my students. I think this might be close to what may benefit them. However, I thought it would be great to put it out there and solicit ideas. If you have some on improving this post, please let me know.
My first take at the post &#8230;
This [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a <em>Basic Aggregation</em> tutorial for my students. I think this might be close to what may benefit them. However, I thought it would be great to put it out there and solicit ideas. If you have some on improving this post, please let me know.</p>
<p>My first take at the post &#8230;</p>
<p>This is a lesson on basic aggregation in SQL. Aggregation in SQL means counting, adding, and grouping by results of counts or sums. Aggregation is a critical part of using the SQL language. At a basic level, aggregation includes the <code>COUNT</code>, <code>SUM</code>, <code>AVERAGE</code>, <code>MAX</code>, and <code>MIN</code> aggregation functions; and the <code>ORDER BY</code>, <code>GROUP BY</code>, and <code>HAVING</code> clauses.</p>
<p>You&#8217;ll find the setup scripts for these examples at the bottom of this blog page. The best way to use this page is to copy the setup code, run it in your database, and then test the examples as you work though them.</p>
<div class="dropdownbox">
<p title="Click to see content ..." class="dropdownclick"><strong><span style="font-size:120%">Data set</span></strong> <span>&darr;</span></p>
<p style="clear: both">
<p>This section discusses the data set. You unfold it by clicking on the bold text above.</p>
<p style="clear: both">
<div style="padding-left:20px">
<p>The illustration of aggregation is a challenge because a trivial set of numbers doesn&#8217;t present much challenge or sometimes relevance but it shows the basic concept. A more applied sample set makes mental calculation and comprehension of functions more difficult. As a result of that trade off, this uses two copies of the ordinal numbers (ordinal numbers are the single digit integers from zero to nine).</p>
<p>After you run the setup script, you can display the data set with the following query.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Oracle only SQL*Plus formatting command to smooth output display.</span>
<span style="color: #993333; font-weight: bold;">SET</span> PAGESIZE <span style="color: #cc66cc;">99</span>
&nbsp;
<span style="color: #808080; font-style: italic;">-- Query ordered by the sets and then the integers in ascending order.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> ordinal <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">4</span>;</pre></div></div>

<p>You could have sorted them more easily by using the <code>ORDINAL_ID</code> surrogate key column but it wouldn&#8217;t demonstrate the <code>ORDER BY</code> clause. In some database, like Oracle and MySQL, the <code>ORDER BY</code> lets you use column names, column aliases, or the position order of the column in the <code>SELECT</code> clause. Unfortunately, this isn&#8217;t true across all databases.</p>
<p>The <code>ORDER BY</code> clause does let you see that you can set nested ordering, like the numbers inside the data sets that are qualified by the <code>LIST_SET</code> column. This is demonstrated in the output below.</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">ORDINAL_ID LIST_SET             LIST_NAME  LIST_VALUE
---------- -------------------- ---------- ----------
         1 Value Set A          Zero                0
         2 Value Set A          One                 1
         3 Value Set A          Two                 2
         4 Value Set A          Three               3
         5 Value Set A          Four                4
         6 Value Set A          Five                5
         7 Value Set A          Six                 6
         8 Value Set A          Seven               7
         9 Value Set A          Eight               8
        10 Value Set A          Nine                9
        11 Value Set A
        12 Value Set B          Zero                0
        13 Value Set B          One                 1
        14 Value Set B          Two                 2
        15 Value Set B          Three               3
        16 Value Set B          Four                4
        17 Value Set B          Five                5
        18 Value Set B          Six                 6
        19 Value Set B          Seven               7
        20 Value Set B          Eight               8
        21 Value Set B          Nine                9
        22 Value Set B</pre></div></div>

</p></div>
</div>
<div class="dropdownbox">
<p title="Click to see content ..." class="dropdownclick"><strong><span style="font-size:120%">Single row aggregation function use</span></strong> <span>&darr;</span></p>
<p style="clear: both">
<p>This section discusses and demonstrates the five aggregation functions in the post. They return a single row of data. Like the other sections, you unfold this by clicking on the bold text above.</p>
<p style="clear: both">
<div style="padding-left:20px">
<p><span style="font-size:115%;font-weight:bold"><em><code>COUNT</code> function</em></span></p>
<p>The <code>COUNT</code> function has two behaviors that may apply. One is when you count rows and the other is when you count values. Both return only a single row.</p>
<p><strong><span style="color:darkblue">Counting by Reference:</span></strong> The following example demonstrates counting rows. In this scenario, the <code>COUNT</code> function takes a single call parameter, which is an asterisk (<code>*</code>). The asterisk actually counts the <em>references</em> to the rows in the table, and in Oracle is equivalent to <code>COUNT(ROWID)</code>. The pseudo column <code>ROWID</code> points to the physical block address where the row is stored in the database. As such, the asterisk acts very much like a <em>pointer</em> in the C or C++ language (that is if you substitute a block address for a memory address).</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">FROM</span> ordinal;</pre></div></div>

<p>It returns</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">  COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #808080; font-style: italic;">----------</span>
        <span style="color: #cc66cc;">22</span></pre></div></div>

<p>When you count rows, you count them whether they contain values or not. It is possible that you could insert a meaningless row with null values for all columns in a table that&#8217;s unconstrained. Moreover, the <code>COUNT</code> function counts all rows no matter whether contain any values.</p>
<p><strong><span style="color:darkblue">Counting by Value: </span></strong>The following examples demonstrate approaches to counting values. It&#8217;s important to note that when you count values, you ignore <em>null</em> values. You can also count distinct things or all things when you count by value.</p>
<p>The <code>LIST_SET</code> column doesn&#8217;t contain any null values (as you can see by inspecting the data set early in this blog page). The following counts the number of values in the <code>LIST_SET</code> column. You could also substitute <code>COUNT(ALL list_set)</code> and it would return the same thing because <code>ALL</code> is the default and always provided unless you override it with a <code>DISTINCT</code> keyword.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> COUNT<span style="color: #66cc66;">&#40;</span>list_set<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">FROM</span> ordinal;</pre></div></div>

<p>It returns:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">  COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #808080; font-style: italic;">----------</span>
        <span style="color: #cc66cc;">22</span></pre></div></div>

<p>Since the <code>LIST_SET</code> column only contains one of two values, you can count that to make sure. You do it with the following syntax:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DISTINCT</span> list_set<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">FROM</span> ordinal;</pre></div></div>

<p>It returns:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">  COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #808080; font-style: italic;">----------</span>
         <span style="color: #cc66cc;">2</span></pre></div></div>

<p>The <code>LIST_NAME</code> and <code>LIST_VALUE</code> both contain two null values. Let&#8217;s see what they return when we count all or distinct values. This example simplifies it a step more by performing both counts side-by-side. This is possible because both columns return a single row.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">ALL</span> list_name<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> name_number
<span style="color: #66cc66;">,</span>      COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DISTINCT</span> list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> value_number
<span style="color: #993333; font-weight: bold;">FROM</span>   ordinal;</pre></div></div>

<p>It returns the twenty total string values found in the first column and the ten unique numeric values found in the second column. The <code>COUNT</code> function with the <code>DISTINCT</code> filter acts like a <code>COUNT</code> function with a <code>GROUP BY</code> clause on the <code>LIST_VALUE</code> column, as you&#8217;ll see later in the discussion.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">NAME_NUMBER VALUE_NUMBER
<span style="color: #808080; font-style: italic;">----------- ------------</span>
         <span style="color: #cc66cc;">20</span>           <span style="color: #cc66cc;">10</span></pre></div></div>

<p><span style="font-size:115%;font-weight:bold"><em><code>SUM</code>, <code>AVERAGE</code>, <code>MAX</code>, and <code>MIN</code> functions</em></span></p>
<p><strong><span style="color:darkblue">Math Operations by Value: </span></strong>These math aggregations are done with the <code>SUM</code>, <code>AVERAGE</code>, <code>MAX</code>, and <code>MIN</code> aggregation functions. They&#8217;re restricted to columns that contain numeric values. Each of them support the default <code>ALL</code> or <code>DISTINCT</code> keywords and they behave much as the <code>COUNT</code> function discussed earlier.</p>
<p>There is a significant difference between their functionality. You can count unique strings but you can&#8217;t sum a column of numbers based on that other column without a <code>GROUP BY</code> clause. You see examples of the <code>GROUP BY</code> in the next part of this post.</p>
<p>Since these behave more or less the same, their examples are grouped together in sections by summing and averaging together, and taking the maximum and minimum values together. For reference, the ordinal numbers sum to 45, two sets of them are naturally 90; and the average of evenly dispersed numbers is half, or 45, and their unique values 4.5.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> SUM<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">ALL</span> list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> sum_all
<span style="color: #66cc66;">,</span>      SUM<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DISTINCT</span> list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> sum_distinct
<span style="color: #66cc66;">,</span>      AVG<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">ALL</span> list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> avg_all
<span style="color: #66cc66;">,</span>      AVG<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DISTINCT</span> list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> avg_distinct
<span style="color: #993333; font-weight: bold;">FROM</span>   ordinal;</pre></div></div>

<p>It returns:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">   SUM_ALL SUM_DISTINCT    AVG_ALL AVG_DISTINCT
<span style="color: #808080; font-style: italic;">---------- ------------ ---------- ------------</span>
        <span style="color: #cc66cc;">90</span>           <span style="color: #cc66cc;">45</span>        <span style="color: #cc66cc;">4.5</span>          <span style="color: #cc66cc;">4.5</span></pre></div></div>

<p>The next section makes the same comparison with the <code>MAX</code>, and <code>MIN</code> functions. The maximum or minimums are the same because they the uniqueness doesn&#8217;t change the minimum or maximum of the sets.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> MIN<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">ALL</span> list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> min_all
<span style="color: #66cc66;">,</span>      MIN<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DISTINCT</span> list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> min_distinct
<span style="color: #66cc66;">,</span>      MAX<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">ALL</span> list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> max_all
<span style="color: #66cc66;">,</span>      MAX<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DISTINCT</span> list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> max_distinct
<span style="color: #993333; font-weight: bold;">FROM</span>   ordinal;</pre></div></div>

<p>It returns:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">   MIN_ALL MIN_DISTINCT    MAX_ALL MAX_DISTINCT
<span style="color: #808080; font-style: italic;">---------- ------------ ---------- ------------</span>
         <span style="color: #cc66cc;">0</span>            <span style="color: #cc66cc;">0</span>          <span style="color: #cc66cc;">9</span>            <span style="color: #cc66cc;">9</span></pre></div></div>

</p></div>
</div>
<p style="clear: both">
<div class="dropdownbox">
<p title="Click to see content ..." class="dropdownclick"><strong><span style="font-size:120%">Multiple row aggregation function use</span></strong> <span>&darr;</span></p>
<p style="clear: both">
<p>This section discusses and demonstrates the five aggregation functions where they return more than a single row of data, which involves grouping by non-aggregated columns. This section covers the <code>GROUP BY</code> and <code>HAVING</code> clauses. Like the other sections, you unfold this by clicking on the bold text above.</p>
<p style="clear: both">
<div style="padding-left:20px">
<p><span style="font-size:115%;font-weight:bold"><em><code>COUNT</code> function</em></span></p>
<p><strong><span style="color:darkblue">Counting by Groups: </span></strong>The following example demonstrates how we can count rows or values by groups. The example counts rows by reference and value, but it does so by grouping the return values on the unique string values in the <code>LIST_SET</code> column.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>   list_set <span style="color: #993333; font-weight: bold;">AS</span> grouping_by_column
<span style="color: #66cc66;">,</span>        COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span>        COUNT<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">FROM</span>     ordinal
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> list_set;</pre></td></tr></table></div>

<p>It returns the following values:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">GROUPING_BY_COLUMN     COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span> COUNT<span style="color: #66cc66;">&#40;</span>LIST_VALUE<span style="color: #66cc66;">&#41;</span>
<span style="color: #808080; font-style: italic;">-------------------- ---------- -----------------</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A                  <span style="color: #cc66cc;">11</span>                <span style="color: #cc66cc;">10</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B                  <span style="color: #cc66cc;">11</span>                <span style="color: #cc66cc;">10</span></pre></div></div>

<p>The results show that there are eleven rows for each set, and that ten of the rows contain values while one holds a null value.</p>
<p>You can also group on columns that contain null values or sets of columns. The following example groups by two columns, where one contains a null value.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>   list_set <span style="color: #993333; font-weight: bold;">AS</span> grouping_by_not_null
<span style="color: #66cc66;">,</span>        list_name <span style="color: #993333; font-weight: bold;">AS</span> group_by_null_too
<span style="color: #66cc66;">,</span>        COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span>        COUNT<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">FROM</span>     ordinal
<span style="color: #993333; font-weight: bold;">WHERE</span>    list_set <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Value Set A'</span>
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> list_set
<span style="color: #66cc66;">,</span>        list_name;</pre></td></tr></table></div>

<p>It returns the following values:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">GROUPING_BY_NOT_NULL GROUP_BY_NULL_TOO   COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span> COUNT<span style="color: #66cc66;">&#40;</span>LIST_VALUE<span style="color: #66cc66;">&#41;</span>
<span style="color: #808080; font-style: italic;">-------------------- ----------------- ---------- -----------------</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Zero                       <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Five                       <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Three                      <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Four                       <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          One                        <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Two                        <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Eight                      <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Nine                       <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Seven                      <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Six                        <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A                                     <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">0</span></pre></div></div>

<p>The last row returned is the one where the grouping by column value and counted column value are null. You should note that the <code>GROUP BY</code> applies to a string column and the return set includes a row grouped by its null value. The count of null column values is always zero.</p>
<p>Another thing that you may have not noticed is that the rows are no longer in ascending numeric order by <code>LIST_NAME</code> or <code>LIST_VALUE</code> columns. There&#8217;s a multiple edge sword when you examine why this occurs. Basically with regard to the <code>LIST_NAME</code> column, Oracle and many other databases use advanced sorting algorithms which may leave non-ordered sets as outcomes. The <code>LIST_VALUE</code> column is not in the <code>GROUP BY</code> clause and therefore can&#8217;t be used as an <code>ORDER BY</code> key.</p>
<p>When you attempt to use a column outside of the <code>GROUP BY</code> clause to order the return set, like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>   list_set <span style="color: #993333; font-weight: bold;">AS</span> grouping_by_not_null
<span style="color: #66cc66;">,</span>        list_name <span style="color: #993333; font-weight: bold;">AS</span> group_by_null_too
<span style="color: #66cc66;">,</span>        COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span>        COUNT<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">FROM</span>     ordinal
<span style="color: #993333; font-weight: bold;">WHERE</span>    list_set <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Value Set A'</span>
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> list_set
<span style="color: #66cc66;">,</span>        list_name
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> list_value;</pre></td></tr></table></div>

<p>You would see the following error in an Oracle Database 10<em>g</em> instance:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> list_value
         <span style="color: #66cc66;">*</span>
ERROR at line <span style="color: #cc66cc;">9</span>:
ORA<span style="color: #66cc66;">-</span>00979: <span style="color: #993333; font-weight: bold;">NOT</span> a <span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> expression</pre></div></div>

<p>You can filter this particular set because the conditions are limited, but this wouldn&#8217;t be a good idea in many other solution sets. However, it certainly highlights some of the potential for extraordinary sorting of result sets.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>   list_set <span style="color: #993333; font-weight: bold;">AS</span> grouping_by_not_null
<span style="color: #66cc66;">,</span>        list_name <span style="color: #993333; font-weight: bold;">AS</span> group_by_null_too
<span style="color: #66cc66;">,</span>        COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span>        COUNT<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">FROM</span>     ordinal
<span style="color: #993333; font-weight: bold;">WHERE</span>    list_set <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Value Set A'</span>
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> list_set
<span style="color: #66cc66;">,</span>        list_name
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> CASE
           WHEN list_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Zero'</span>  THEN <span style="color: #cc66cc;">0</span>
           WHEN list_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'One'</span>   THEN <span style="color: #cc66cc;">1</span>
           WHEN list_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Two'</span>   THEN <span style="color: #cc66cc;">2</span>
           WHEN list_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Three'</span> THEN <span style="color: #cc66cc;">3</span>
           WHEN list_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Four'</span>  THEN <span style="color: #cc66cc;">4</span>
           WHEN list_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Five'</span>  THEN <span style="color: #cc66cc;">5</span>
           WHEN list_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Six'</span>   THEN <span style="color: #cc66cc;">6</span>
           WHEN list_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Seven'</span> THEN <span style="color: #cc66cc;">7</span>
           WHEN list_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Eight'</span> THEN <span style="color: #cc66cc;">8</span>
           WHEN list_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Nine'</span>  THEN <span style="color: #cc66cc;">9</span>
         END;</pre></td></tr></table></div>

<p>It returns the following values:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">GROUPING_BY_NOT_NULL GROUP_BY_NULL_TOO   COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span> COUNT<span style="color: #66cc66;">&#40;</span>LIST_VALUE<span style="color: #66cc66;">&#41;</span>
<span style="color: #808080; font-style: italic;">-------------------- ----------------- ---------- -----------------</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Zero                       <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          One                        <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Two                        <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Three                      <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Four                       <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Five                       <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Six                        <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Seven                      <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Eight                      <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Nine                       <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A                                     <span style="color: #cc66cc;">1</span>                 <span style="color: #cc66cc;">0</span></pre></div></div>

<p>A better way to sort this type of data would involve putting it into an <a href="http://michaelmclaughlin.info/db1/lesson-5-querying-data/inline-views/"><em>inline view</em></a> and then joining it against the base data set. This allows you to use a non-grouping column as the sort key in an <code>ORDER BY</code> clause. Here&#8217;s an example of that approach but note it does take system overhead and should only be done when SQL must perform the sort operation.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>   ilv<span style="color: #66cc66;">.</span>grouping_by_not_null
<span style="color: #66cc66;">,</span>        ilv<span style="color: #66cc66;">.</span>group_by_null_too
<span style="color: #66cc66;">,</span>        ilv<span style="color: #66cc66;">.</span>row_count
<span style="color: #66cc66;">,</span>        ilv<span style="color: #66cc66;">.</span>column_count
<span style="color: #993333; font-weight: bold;">FROM</span>    <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span>   list_set <span style="color: #993333; font-weight: bold;">AS</span> grouping_by_not_null
         <span style="color: #66cc66;">,</span>        list_name <span style="color: #993333; font-weight: bold;">AS</span> group_by_null_too
         <span style="color: #66cc66;">,</span>        COUNT<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> row_count
         <span style="color: #66cc66;">,</span>        COUNT<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> column_count
         <span style="color: #993333; font-weight: bold;">FROM</span>     ordinal
         <span style="color: #993333; font-weight: bold;">WHERE</span>    list_set <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Value Set A'</span>
         <span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> list_set
         <span style="color: #66cc66;">,</span>        list_name<span style="color: #66cc66;">&#41;</span> ilv <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> ordinal o
<span style="color: #993333; font-weight: bold;">ON</span>       ilv<span style="color: #66cc66;">.</span>grouping_by_not_null <span style="color: #66cc66;">=</span> o<span style="color: #66cc66;">.</span>list_set
<span style="color: #993333; font-weight: bold;">AND</span>      ilv<span style="color: #66cc66;">.</span>group_by_null_too <span style="color: #66cc66;">=</span> o<span style="color: #66cc66;">.</span>list_name
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> o<span style="color: #66cc66;">.</span>list_value;</pre></td></tr></table></div>

<p>That returns a perfectly ordered set because the <code>LEFT JOIN</code> lets us capture the null value in the inline view without matching the two columns in the join condition. It returns the following set:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">GROUPING_BY_NOT_NULL GROUP_BY_NULL_TOO  ROW_COUNT COLUMN_COUNT
-------------------- ----------------- ---------- ------------
Value Set A          Zero                       1            1
Value Set A          One                        1            1
Value Set A          Two                        1            1
Value Set A          Three                      1            1
Value Set A          Four                       1            1
Value Set A          Five                       1            1
Value Set A          Six                        1            1
Value Set A          Seven                      1            1
Value Set A          Eight                      1            1
Value Set A          Nine                       1            1
Value Set A                                     1            0</pre></div></div>

<p><span style="font-size:115%;font-weight:bold"><em><code>SUM</code>, <code>AVERAGE</code>, <code>MAX</code>, and <code>MIN</code> functions</em></span></p>
<p><strong><span style="color:darkblue">Math Operations by Groups: </span></strong>These math aggregations are done with the <code>SUM</code>, <code>AVERAGE</code>, <code>MAX</code>, and <code>MIN</code> aggregation functions. Like the previous single row return examples, they&#8217;re restricted to columns that contain numeric values. While they also support the default <code>ALL</code> or <code>DISTINCT</code> keywords, it didn&#8217;t seem necessary to demonstrate more of those behaviors here.</p>
<p>The following sums, averages, and gets both the minimum and maximum value by unique <code>LIST_SET</code> column values:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>   list_set <span style="color: #993333; font-weight: bold;">AS</span> grouping_by_not_null
<span style="color: #66cc66;">,</span>        SUM<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_sum
<span style="color: #66cc66;">,</span>        AVG<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_avg
<span style="color: #66cc66;">,</span>        MIN<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_min
<span style="color: #66cc66;">,</span>        MAX<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_max
<span style="color: #993333; font-weight: bold;">FROM</span>     ordinal
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> list_set;</pre></div></div>

<p>It returns the following two rows:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">GROUPING_BY_NOT_NULL ORDINAL_SUM ORDINAL_AVG ORDINAL_MIN ORDINAL_MAX
<span style="color: #808080; font-style: italic;">-------------------- ----------- ----------- ----------- -----------</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A                   <span style="color: #cc66cc;">45</span>         <span style="color: #cc66cc;">4.5</span>           <span style="color: #cc66cc;">0</span>           <span style="color: #cc66cc;">9</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B                   <span style="color: #cc66cc;">45</span>         <span style="color: #cc66cc;">4.5</span>           <span style="color: #cc66cc;">0</span>           <span style="color: #cc66cc;">9</span></pre></div></div>

<p>Expanding the <code>GROUP BY</code> criteria to include the <code>LIST_NAME</code> column, you see what happens when the <code>SUM</code> and <code>AVG</code> functions work with only null values. They always return null when adding only column values with a null value. This is handy as you&#8217;ll see in the <em>selective aggregation</em> discussion in a subsequent tutorial.</p>
<p>As done in the prior example, this filters out the second value set, to focus on what&#8217;s happening with the rows grouped on two columns.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>    list_set <span style="color: #993333; font-weight: bold;">AS</span> grouping_by_not_null
<span style="color: #66cc66;">,</span>         list_name <span style="color: #993333; font-weight: bold;">AS</span> group_by_null_too
<span style="color: #66cc66;">,</span>         SUM<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_sum
<span style="color: #66cc66;">,</span>         AVG<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_avg
<span style="color: #66cc66;">,</span>         MIN<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_min
<span style="color: #66cc66;">,</span>         MAX<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_max
<span style="color: #993333; font-weight: bold;">FROM</span>      ordinal
<span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">NOT</span> list_set <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Value Set B'</span>
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span>  list_set
<span style="color: #66cc66;">,</span>         list_name;</pre></td></tr></table></div>

<p>It returns the following set of records, which are clearly out of order based on the algorithms that optimize aggregation. It&#8217;s not hard to read because there aren&#8217;t too many rows returned.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">GROUPING_BY_NOT_NULL GROUP_BY_NULL_TOO ORDINAL_SUM ORDINAL_AVG ORDINAL_MIN ORDINAL_MAX
<span style="color: #808080; font-style: italic;">-------------------- ----------------- ----------- ----------- ----------- -----------</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Zero                        <span style="color: #cc66cc;">0</span>           <span style="color: #cc66cc;">0</span>           <span style="color: #cc66cc;">0</span>           <span style="color: #cc66cc;">0</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Five                        <span style="color: #cc66cc;">5</span>           <span style="color: #cc66cc;">5</span>           <span style="color: #cc66cc;">5</span>           <span style="color: #cc66cc;">5</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Three                       <span style="color: #cc66cc;">3</span>           <span style="color: #cc66cc;">3</span>           <span style="color: #cc66cc;">3</span>           <span style="color: #cc66cc;">3</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Four                        <span style="color: #cc66cc;">4</span>           <span style="color: #cc66cc;">4</span>           <span style="color: #cc66cc;">4</span>           <span style="color: #cc66cc;">4</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          One                         <span style="color: #cc66cc;">1</span>           <span style="color: #cc66cc;">1</span>           <span style="color: #cc66cc;">1</span>           <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Two                         <span style="color: #cc66cc;">2</span>           <span style="color: #cc66cc;">2</span>           <span style="color: #cc66cc;">2</span>           <span style="color: #cc66cc;">2</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Eight                       <span style="color: #cc66cc;">8</span>           <span style="color: #cc66cc;">8</span>           <span style="color: #cc66cc;">8</span>           <span style="color: #cc66cc;">8</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Nine                        <span style="color: #cc66cc;">9</span>           <span style="color: #cc66cc;">9</span>           <span style="color: #cc66cc;">9</span>           <span style="color: #cc66cc;">9</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Seven                       <span style="color: #cc66cc;">7</span>           <span style="color: #cc66cc;">7</span>           <span style="color: #cc66cc;">7</span>           <span style="color: #cc66cc;">7</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A          Six                         <span style="color: #cc66cc;">6</span>           <span style="color: #cc66cc;">6</span>           <span style="color: #cc66cc;">6</span>           <span style="color: #cc66cc;">6</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> A</pre></div></div>

<p>If SQL must sort these into numeric order, it can do so like the prior example with the result from the <code>COUNT</code> function. You must instrument a solution for it through an inline view. The following shows you how to do that.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>   ilv<span style="color: #66cc66;">.</span>grouping_by_not_null
<span style="color: #66cc66;">,</span>        ilv<span style="color: #66cc66;">.</span>group_by_null_too
<span style="color: #66cc66;">,</span>        ilv<span style="color: #66cc66;">.</span>ordinal_sum
<span style="color: #66cc66;">,</span>        ilv<span style="color: #66cc66;">.</span>ordinal_avg
<span style="color: #66cc66;">,</span>        ilv<span style="color: #66cc66;">.</span>ordinal_min
<span style="color: #66cc66;">,</span>        ilv<span style="color: #66cc66;">.</span>ordinal_max
<span style="color: #993333; font-weight: bold;">FROM</span>    <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span>   list_set <span style="color: #993333; font-weight: bold;">AS</span> grouping_by_not_null
         <span style="color: #66cc66;">,</span>        list_name <span style="color: #993333; font-weight: bold;">AS</span> group_by_null_too
         <span style="color: #66cc66;">,</span>        SUM<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_sum
         <span style="color: #66cc66;">,</span>        AVG<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_avg
         <span style="color: #66cc66;">,</span>        MIN<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_min
         <span style="color: #66cc66;">,</span>        MAX<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_max
         <span style="color: #993333; font-weight: bold;">FROM</span>     ordinal
         <span style="color: #993333; font-weight: bold;">WHERE</span>    list_set <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Value Set B'</span>
         <span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> list_set
         <span style="color: #66cc66;">,</span>         list_name<span style="color: #66cc66;">&#41;</span> ilv <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> ordinal o
<span style="color: #993333; font-weight: bold;">ON</span>       ilv<span style="color: #66cc66;">.</span>grouping_by_not_null <span style="color: #66cc66;">=</span> o<span style="color: #66cc66;">.</span>list_set
<span style="color: #993333; font-weight: bold;">AND</span>      ilv<span style="color: #66cc66;">.</span>group_by_null_too <span style="color: #66cc66;">=</span> o<span style="color: #66cc66;">.</span>list_name
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> o<span style="color: #66cc66;">.</span>list_value;</pre></td></tr></table></div>

<p>Now you should see an ordered set like this:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">GROUPING_BY_NOT_NULL GROUP_BY_NULL_TOO ORDINAL_SUM ORDINAL_AVG ORDINAL_MIN ORDINAL_MAX
<span style="color: #808080; font-style: italic;">-------------------- ----------------- ----------- ----------- ----------- -----------</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B          Zero                        <span style="color: #cc66cc;">0</span>           <span style="color: #cc66cc;">0</span>           <span style="color: #cc66cc;">0</span>           <span style="color: #cc66cc;">0</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B          One                         <span style="color: #cc66cc;">1</span>           <span style="color: #cc66cc;">1</span>           <span style="color: #cc66cc;">1</span>           <span style="color: #cc66cc;">1</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B          Two                         <span style="color: #cc66cc;">2</span>           <span style="color: #cc66cc;">2</span>           <span style="color: #cc66cc;">2</span>           <span style="color: #cc66cc;">2</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B          Three                       <span style="color: #cc66cc;">3</span>           <span style="color: #cc66cc;">3</span>           <span style="color: #cc66cc;">3</span>           <span style="color: #cc66cc;">3</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B          Four                        <span style="color: #cc66cc;">4</span>           <span style="color: #cc66cc;">4</span>           <span style="color: #cc66cc;">4</span>           <span style="color: #cc66cc;">4</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B          Five                        <span style="color: #cc66cc;">5</span>           <span style="color: #cc66cc;">5</span>           <span style="color: #cc66cc;">5</span>           <span style="color: #cc66cc;">5</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B          Six                         <span style="color: #cc66cc;">6</span>           <span style="color: #cc66cc;">6</span>           <span style="color: #cc66cc;">6</span>           <span style="color: #cc66cc;">6</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B          Seven                       <span style="color: #cc66cc;">7</span>           <span style="color: #cc66cc;">7</span>           <span style="color: #cc66cc;">7</span>           <span style="color: #cc66cc;">7</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B          Eight                       <span style="color: #cc66cc;">8</span>           <span style="color: #cc66cc;">8</span>           <span style="color: #cc66cc;">8</span>           <span style="color: #cc66cc;">8</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B          Nine                        <span style="color: #cc66cc;">9</span>           <span style="color: #cc66cc;">9</span>           <span style="color: #cc66cc;">9</span>           <span style="color: #cc66cc;">9</span>
Value <span style="color: #993333; font-weight: bold;">SET</span> B</pre></div></div>

<p><strong><span style="color:darkblue">Math Operations with the <code>HAVING</code> clause: </span></strong>The <code>HAVING</code> clause is very useful when you want to find rows that duplicate a column or set of column values. It&#8217;s also useful for sorting data sets.</p>
<p>The <code>HAVING</code> clause effects all aggregate rows and acts somewhat like a filter in the <code>WHERE</code> clause of a non-aggregated query. The difference is that the <code>WHERE</code> clause filters the base result set, while the <code>HAVING</code> clause filters the aggregated result set.</p>
<p>The following example captures the sum and average for only the odd <code>LIST_VALUE</code> column values. It does that by using <a href="http://en.wikipedia.org/wiki/Modular_arithmetic">modular (or modulo)</a> mathematics through the <code>MOD</code> function in Oracle&#8217;s SQL implementation. Modulo math works by calculating the remainder of integer division. When you divide any number by two and the result is one, then you have an odd number.</p>
<p>Here&#8217;s the sample program that illustrates the <code>HAVING</code> clause in a <code>CASE</code> statement. The <code>CASE</code> statement only adds the number when it is an odd number. Any even number is zeroed out. The comparison operator ensures that only rows are returned when the <code>SUM</code> is greater than zero, which only happens for odd numbers.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>   list_set <span style="color: #993333; font-weight: bold;">AS</span> grouping_by_not_null
<span style="color: #66cc66;">,</span>        list_name <span style="color: #993333; font-weight: bold;">AS</span> group_by_null_too
<span style="color: #66cc66;">,</span>        SUM<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_sum
<span style="color: #66cc66;">,</span>        AVG<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_avg
<span style="color: #993333; font-weight: bold;">FROM</span>     ordinal
<span style="color: #993333; font-weight: bold;">WHERE</span>    list_set <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Value Set A'</span>
<span style="color: #993333; font-weight: bold;">HAVING</span>   SUM<span style="color: #66cc66;">&#40;</span>CASE
               WHEN MOD<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> THEN list_value ELSE <span style="color: #cc66cc;">0</span>
             END<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">0</span>
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> list_set
<span style="color: #66cc66;">,</span>        list_name;</pre></td></tr></table></div>

<p>The data set, as you&#8217;ve seen with others isn&#8217;t sorted in ascending order because of how the algorithms work. Since there are only five rows returned, it is easy to see that the <code>HAVING</code> clause let us narrow the return set to odd numbers. What we might overlook is that the <code>HAVING</code> is always a filtering statement. This means we need to have a comparative operator tied to the <code>HAVING</code> return value.</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">GROUPING_BY_NOT_NULL GROUP_BY_NULL_TOO ORDINAL_SUM ORDINAL_AVG
-------------------- ----------------- ----------- -----------
Value Set A          Five                        5           5
Value Set A          Three                       3           3
Value Set A          One                         1           1
Value Set A          Nine                        9           9
Value Set A          Seven                       7           7</pre></div></div>

<p>As you&#8217;ve seen in early examples, you can also put this inside an inline view and sort the aggregated results. Here&#8217;s the code to accomplish that.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>   ilv<span style="color: #66cc66;">.</span>grouping_by_not_null
<span style="color: #66cc66;">,</span>        ilv<span style="color: #66cc66;">.</span>group_by_null_too
<span style="color: #66cc66;">,</span>        ilv<span style="color: #66cc66;">.</span>ordinal_sum
<span style="color: #66cc66;">,</span>        ilv<span style="color: #66cc66;">.</span>ordinal_avg
<span style="color: #993333; font-weight: bold;">FROM</span>    <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span>   list_set <span style="color: #993333; font-weight: bold;">AS</span> grouping_by_not_null
         <span style="color: #66cc66;">,</span>        list_name <span style="color: #993333; font-weight: bold;">AS</span> group_by_null_too
         <span style="color: #66cc66;">,</span>        SUM<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_sum
         <span style="color: #66cc66;">,</span>        AVG<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> ordinal_avg
         <span style="color: #993333; font-weight: bold;">FROM</span>     ordinal
         <span style="color: #993333; font-weight: bold;">WHERE</span>    list_set <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Value Set A'</span>
         <span style="color: #993333; font-weight: bold;">HAVING</span>   SUM<span style="color: #66cc66;">&#40;</span>CASE
                        WHEN MOD<span style="color: #66cc66;">&#40;</span>list_value<span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> THEN list_value ELSE <span style="color: #cc66cc;">0</span>
                      END<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">0</span>
         <span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> list_set
         <span style="color: #66cc66;">,</span>        list_name<span style="color: #66cc66;">&#41;</span> ilv <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> ordinal o
<span style="color: #993333; font-weight: bold;">ON</span>       ilv<span style="color: #66cc66;">.</span>grouping_by_not_null <span style="color: #66cc66;">=</span> o<span style="color: #66cc66;">.</span>list_set
<span style="color: #993333; font-weight: bold;">AND</span>      ilv<span style="color: #66cc66;">.</span>group_by_null_too <span style="color: #66cc66;">=</span> o<span style="color: #66cc66;">.</span>list_name
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> o<span style="color: #66cc66;">.</span>list_value;</pre></td></tr></table></div>

<p>It naturally returns the ordered set of aggregated results from only odd numbers in the base set of values.</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">GROUPING_BY_NOT_NULL GROUP_BY_NULL_TOO ORDINAL_SUM ORDINAL_AVG
-------------------- ----------------- ----------- -----------
Value Set A          One                         1           1
Value Set A          Three                       3           3
Value Set A          Five                        5           5
Value Set A          Seven                       7           7
Value Set A          Nine                        9           9</pre></div></div>

</p></div>
</div>
<p style="clear: both">
<div class="dropdownbox">
<p title="Click to see content ..." class="dropdownclick"><strong><span style="font-size:120%">Setup Script</span></strong> <span>&darr;</span></p>
<p style="clear: both">
<p>The drop down items, unfold with source code to seed the examples.</p>
<p style="clear: both">
<div style="padding-left:20px">
<div class="dropdownbox">
<p title="Click to see content ..." class="dropdownclick"><strong><span style="font-size:120%">Oracle SQL Join Supporting Script</span></strong> <span>&darr;</span></p>
<p style="clear: both">
<p>This has the setup script for the example tables.</p>
<div style="padding-left:20px">
<p style="clear: both">

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Conditionally drop the table and sequence.</span>
BEGIN
  <span style="color: #993333; font-weight: bold;">FOR</span> i <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> table_name
            <span style="color: #993333; font-weight: bold;">FROM</span>   user_tables
            <span style="color: #993333; font-weight: bold;">WHERE</span>  table_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'ORDINAL'</span><span style="color: #66cc66;">&#41;</span> LOOP
    EXECUTE IMMEDIATE <span style="color: #ff0000;">'DROP TABLE '</span><span style="color: #66cc66;">||</span>i<span style="color: #66cc66;">.</span>table_name;
  END LOOP;
  <span style="color: #993333; font-weight: bold;">FOR</span> i <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> sequence_name
            <span style="color: #993333; font-weight: bold;">FROM</span>   user_sequences
            <span style="color: #993333; font-weight: bold;">WHERE</span>  sequence_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'ORDINAL_S1'</span><span style="color: #66cc66;">&#41;</span> LOOP
    EXECUTE IMMEDIATE <span style="color: #ff0000;">'DROP SEQUENCE '</span><span style="color: #66cc66;">||</span>i<span style="color: #66cc66;">.</span>sequence_name;
  END LOOP;
END;
<span style="color: #66cc66;">/</span>
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create the aggregation sample table and sequence.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> ordinal
<span style="color: #66cc66;">&#40;</span> ordinal_id  NUMBER
<span style="color: #66cc66;">,</span> list_set    VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> list_name   VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> list_value  NUMBER<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> SEQUENCE ordinal_s1;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Seeding values in the aggregation sample table.</span>
DECLARE
  <span style="color: #808080; font-style: italic;">-- Define local types.</span>
  TYPE listg <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">TABLE</span> OF VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>;
  TYPE listn <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">TABLE</span> OF NUMBER;
  TYPE lists <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">TABLE</span> OF VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Declare local variables.</span>
  groups LISTG :<span style="color: #66cc66;">=</span> listg<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Value Set A'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set B'</span><span style="color: #66cc66;">&#41;</span>;
  labels LISTS :<span style="color: #66cc66;">=</span> lists<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Zero'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'One'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Two'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Three'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Four'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Five'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Six'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Seven'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Eight'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Nine'</span><span style="color: #66cc66;">&#41;</span>;
  valuen LISTN :<span style="color: #66cc66;">=</span> listn<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">4</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">5</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">6</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">7</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">8</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">9</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
BEGIN
  <span style="color: #808080; font-style: italic;">-- Outer loop sets the group level.</span>
  <span style="color: #993333; font-weight: bold;">FOR</span> i <span style="color: #993333; font-weight: bold;">IN</span> 1<span style="color: #66cc66;">..</span>groups<span style="color: #66cc66;">.</span>COUNT LOOP
    <span style="color: #808080; font-style: italic;">-- Inner loop sets the row level.</span>
    <span style="color: #993333; font-weight: bold;">FOR</span> j <span style="color: #993333; font-weight: bold;">IN</span> 1<span style="color: #66cc66;">..</span>labels<span style="color: #66cc66;">.</span>COUNT LOOP
      <span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> ordinal
      <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span>ordinal_s1<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">NEXTVAL</span><span style="color: #66cc66;">,</span>groups<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>labels<span style="color: #66cc66;">&#40;</span>j<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>valuen<span style="color: #66cc66;">&#40;</span>j<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
    END LOOP;
&nbsp;
    <span style="color: #808080; font-style: italic;">-- Insert the null values for each group.</span>
    <span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> ordinal
    <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span>ordinal_s1<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">NEXTVAL</span><span style="color: #66cc66;">,</span>groups<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span>;
  END LOOP;
  COMMIT;
END;
<span style="color: #66cc66;">/</span>
&nbsp;
<span style="color: #808080; font-style: italic;">-- Commit the inserts.</span>
COMMIT;</pre></div></div>

<p style="clear: both">
</p></div>
</p></div>
<p style="clear: both">
<div class="dropdownbox">
<p title="Click to see content ..." class="dropdownclick"><strong><span style="font-size:120%">MySQL SQL Join Supporting Script</span></strong> <span>&darr;</span></p>
<p style="clear: both">
<p>This has the setup script for the example tables.</p>
<div style="padding-left:20px">
<p style="clear: both">

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Conditionally drop the table.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'DROP TABLE ordinal'</span> <span style="color: #993333; font-weight: bold;">AS</span> Statement;
<span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> ordinal;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create the table.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'CREATE TABLE ordinal'</span> <span style="color: #993333; font-weight: bold;">AS</span> Statement;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> ordinal
<span style="color: #66cc66;">&#40;</span> ordinal_id  INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span>
<span style="color: #66cc66;">,</span> list_set    VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> list_name   VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> list_value  INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Seed the row values.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'INSERT INTO ordinal'</span> <span style="color: #993333; font-weight: bold;">AS</span> Statement;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> ordinal
<span style="color: #993333; font-weight: bold;">VALUES</span>
 <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set A'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Zero'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'0'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set A'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'One'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set A'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Two'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'2'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set A'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Three'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'3'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set A'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Four'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'4'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set A'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Five'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'5'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set A'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Six'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'6'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set A'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Seven'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'7'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set A'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Eight'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'8'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set A'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Nine'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'9'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set A'</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set B'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Zero'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'0'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set B'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'One'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set B'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Two'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'2'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set B'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Three'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'3'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set B'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Four'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'4'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set B'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Five'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'5'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set B'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Six'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'6'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set B'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Seven'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'7'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set B'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Eight'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'8'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set B'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Nine'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'9'</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Value Set B'</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Commit the inserts.</span>
COMMIT;</pre></div></div>

<p style="clear: both">
</p></div>
</p></div>
</p></div>
</div>
<p style="clear: both">
]]></content:encoded>
			<wfw:commentRss>http://blog.mclaughlinsoftware.com/2010/02/26/sql-aggregation-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Multi-row Merge in MySQL</title>
		<link>http://blog.mclaughlinsoftware.com/2010/02/24/multi-row-merge-in-mysql/</link>
		<comments>http://blog.mclaughlinsoftware.com/2010/02/24/multi-row-merge-in-mysql/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 15:15:07 +0000</pubDate>
		<dc:creator>maclochlainn</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Stored Procedures]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.mclaughlinsoftware.com/?p=3530</guid>
		<description><![CDATA[After I wrote the post for students on the multiple row MERGE statement for an upload through an external table in Oracle, I thought to check how it might be done with MySQL. More or less because I try to keep track of how things are done in several databases.
MySQL&#8217;s equivalent to a MERGE statement [...]]]></description>
			<content:encoded><![CDATA[<p>After I wrote the post for students on the multiple row <code>MERGE</code> statement for an upload through an external table in Oracle, I thought to check how it might be done with MySQL. More or less because I try to keep track of how things are done in several databases.</p>
<p>MySQL&#8217;s equivalent to a <code>MERGE</code> statement is an <code>INSERT</code> statement with an <code>ON DUPLICATE KEY</code> clause, which I <a href="http://blog.mclaughlinsoftware.com/2009/05/25/mysql-merge-gone-awry/">blogged about a while back</a>. It was interesting to note that you can&#8217;t use an <code>INSERT</code> statement with the <code>ON DUPLICATE KEY</code> clause except in a <code>VALUES</code> clause. While you can do multiple row inserts in the <code>VALUES</code> clause in MySQL, like SQL Server or IBM&#8217;s DB2, you can&#8217;t do it with the <code>ON DUPLICATE KEY</code> clause. There&#8217;s also no support for that clause when you attempt to perform an <code>INSERT</code> statement with a subquery.</p>
<p>The workaround was to write a <em>stored procedure</em> with two cursor loops, explicitly pass the values from the cursor to local variables, and then put the local variables in the <code>VALUES</code> clause. On parity, clearly Oracle&#8217;s <code>MERGE</code> statement (<a href="http://blog.mclaughlinsoftware.com/2010/02/23/merge-statement-for-etl/">shown here</a>) is far superior than MySQL&#8217;s approach.</p>
<p><span style="font-size:125%;font-weight:bold">Demonstration</span></p>
<p>Here are the steps to accomplish an import/upload with the <code>INSERT</code> statement and <code>ON DUPLICATE KEY</code> clause. In this example, you upload data from a flat file, or Comma Separated Value (CSV) file to a denormalized table (actually in unnormalized form). This type of file upload transfers information that doesn&#8217;t have surrogate key values. You have to create those in the scope of the transformation to the normalized tables.</p>
<p style="clear:both">
<p><span style="font-size:115%;font-weight:bold">Step #1 : Position your CSV file in the physical directory</span></p>
<p>After creating the virtual directory, copy the following contents into a file named <code>kingdom_mysql_import.csv</code> in the <code>C:\Data\Download</code> directory or folder. If you have Windows UAC enabled in Windows Vista or 7, you should disable it before performing this step.</p>
<p>Place the following in the <code>kingdom_mysql_import.csv</code> file. The trailing commas are meaningful in MySQL and avoid problems when reading CSV files.</p>
<p style="clear:both">

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">Narnia<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">77600</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Peter the Magnificent'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">12720320</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">12920609</span><span style="color: #66cc66;">,</span>
Narnia<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">77600</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Edmund the Just'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">12720320</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">12920609</span><span style="color: #66cc66;">,</span>
Narnia<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">77600</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Susan the Gentle'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">12720320</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">12920609</span><span style="color: #66cc66;">,</span>
Narnia<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">77600</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Lucy the Valiant'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">12720320</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">12920609</span><span style="color: #66cc66;">,</span>
Narnia<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">42100</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Peter the Magnificent'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">15310412</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">15310531</span><span style="color: #66cc66;">,</span>
Narnia<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">42100</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Edmund the Just'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">15310412</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">15310531</span><span style="color: #66cc66;">,</span>
Narnia<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">42100</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Susan the Gentle'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">15310412</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">15310531</span><span style="color: #66cc66;">,</span>
Narnia<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">42100</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Lucy the Valiant'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">15310412</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">15310531</span><span style="color: #66cc66;">,</span>
Camelot<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">15200</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'King Arthur'</span><span style="color: #66cc66;">,</span>06310310<span style="color: #66cc66;">,</span>06861212<span style="color: #66cc66;">,</span>
Camelot<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">15200</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Sir Lionel'</span><span style="color: #66cc66;">,</span>06310310<span style="color: #66cc66;">,</span>06861212<span style="color: #66cc66;">,</span>
Camelot<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">15200</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Sir Bors'</span><span style="color: #66cc66;">,</span>06310310<span style="color: #66cc66;">,</span>06351212<span style="color: #66cc66;">,</span>
Camelot<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">15200</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Sir Bors'</span><span style="color: #66cc66;">,</span>06400310<span style="color: #66cc66;">,</span>06861212<span style="color: #66cc66;">,</span>
Camelot<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">15200</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Sir Galahad'</span><span style="color: #66cc66;">,</span>06310310<span style="color: #66cc66;">,</span>06861212<span style="color: #66cc66;">,</span>
Camelot<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">15200</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Sir Gawain'</span><span style="color: #66cc66;">,</span>06310310<span style="color: #66cc66;">,</span>06861212<span style="color: #66cc66;">,</span>
Camelot<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">15200</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Sir Tristram'</span><span style="color: #66cc66;">,</span>06310310<span style="color: #66cc66;">,</span>06861212<span style="color: #66cc66;">,</span>
Camelot<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">15200</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Sir Percival'</span><span style="color: #66cc66;">,</span>06310310<span style="color: #66cc66;">,</span>06861212<span style="color: #66cc66;">,</span>
Camelot<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">15200</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'Sir Lancelot'</span><span style="color: #66cc66;">,</span>06700930<span style="color: #66cc66;">,</span>06821212<span style="color: #66cc66;">,</span></pre></div></div>

<p><span style="font-size:115%;font-weight:bold">Step #2 : Connect as the <code>student</code> user</span></p>
<p>Disconnect and connect as the student user, or reconnect as the student user. The reconnect syntax that protects your password is:</p>
<p style="clear:both">

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql <span style="color: #66cc66;">-</span>ustudent <span style="color: #66cc66;">-</span>p</pre></div></div>

<p>Connect to the <code>sampledb</code> database, like so:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">USE</span> sampledb;</pre></div></div>

<p style="clear:both">
<p><span style="font-size:115%;font-weight:bold">Step #3 : Run the script that creates tables and sequences</span></p>
<p>Copy the following into a <code>create_mysql_kingdom_upload.sql</code> file within a directory of your choice. Then, run it as the <code>student</code> account.</p>
<p style="clear:both">

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- This enables dropping tables with foreign key dependencies.</span>
<span style="color: #808080; font-style: italic;">-- It is specific to the InnoDB Engine.</span>
<span style="color: #993333; font-weight: bold;">SET</span> FOREIGN_KEY_CHECKS <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span>; 
&nbsp;
<span style="color: #808080; font-style: italic;">-- Conditionally drop objects.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'KINGDOM'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Drop Table&quot;</span>;
<span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> KINGDOM;
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'KNIGHT'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Drop Table&quot;</span>;
<span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> KNIGHT;
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'KINGDOM_KNIGHT_IMPORT'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Drop Table&quot;</span>;
<span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> KINGDOM_KNIGHT_IMPORT;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create normalized kingdom table.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'KINGDOM'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Create Table&quot;</span>;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> kingdom
<span style="color: #66cc66;">&#40;</span> kingdom_id    INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span>
<span style="color: #66cc66;">,</span> kingdom_name  VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> population    INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span><span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>INNODB;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create normalized knight table.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'KNIGHT'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Create Table&quot;</span>;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> knight
<span style="color: #66cc66;">&#40;</span> knight_id             INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span>
<span style="color: #66cc66;">,</span> knight_name           VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">24</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> kingdom_allegiance_id INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span>
<span style="color: #66cc66;">,</span> allegiance_start_date DATE
<span style="color: #66cc66;">,</span> allegiance_end_date   DATE
<span style="color: #66cc66;">,</span> CONSTRAINT fk_kingdom <span style="color: #993333; font-weight: bold;">FOREIGN</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span>kingdom_allegiance_id<span style="color: #66cc66;">&#41;</span>
  <span style="color: #993333; font-weight: bold;">REFERENCES</span> kingdom <span style="color: #66cc66;">&#40;</span>kingdom_id<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>INNODB;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create external import table in memory only - disappears after rebooting the mysqld service.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'KINGDOM_KNIGHT_IMPORT'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Create Table&quot;</span>;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> kingdom_knight_import
<span style="color: #66cc66;">&#40;</span> kingdom_name          VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> population            INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span>
<span style="color: #66cc66;">,</span> knight_name           VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">24</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> allegiance_start_date DATE
<span style="color: #66cc66;">,</span> allegiance_end_date   DATE<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>MEMORY;</pre></td></tr></table></div>

<p><span style="font-size:115%;font-weight:bold">Step #4 : Load the data into your target upload table</span></p>
<p>There a number of things that could go wrong but when you choose <code>LOCAL</code> there generally aren&#8217;t any problems. Run the following query from the <code>student</code> account while <em>using</em> the <code>sampledb</code> database, and check whether or not you can access the <code>kingdom_import.csv</code> file.</p>
<p style="clear:both">

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">LOAD</span> <span style="color: #993333; font-weight: bold;">DATA</span> <span style="color: #993333; font-weight: bold;">LOCAL</span> <span style="color: #993333; font-weight: bold;">INFILE</span> <span style="color: #ff0000;">'c:/Data/kingdom_mysql_import.csv'</span>
<span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #993333; font-weight: bold;">TABLE</span> kingdom_knight_import
<span style="color: #993333; font-weight: bold;">FIELDS</span> TERMINATED <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #ff0000;">','</span>
<span style="color: #993333; font-weight: bold;">ENCLOSED</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #ff0000;">'&quot;'</span>
<span style="color: #993333; font-weight: bold;">ESCAPED</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #ff0000;">'<span style="color: #000099; font-weight: bold;">\\</span>'</span>
<span style="color: #993333; font-weight: bold;">LINES</span> TERMINATED <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #ff0000;">'<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>'</span>;</pre></td></tr></table></div>

<p><span style="font-size:115%;font-weight:bold">Step #5 : Create the upload procedure</p>
<p>Copy the following into a <code>create_mysql_upload_procedure.sql</code> file within a directory of your choice. You should note that unlike Oracle&#8217;s <code>MERGE</code> statement, this is done with the <code>ON DUPLICATE KEY</code> clause and requires actual values not a source query. This presents few options other than a stored routine, known as a stored procedure. As you can see from the code, there&#8217;s a great deal of complexity to the syntax and a much more verbose implementation than Oracle&#8217;s equivalent PL/SQL.</p>
<p>Then, run it as the <code>student</code> account. As you look at the structure to achieve this simple thing, the long standing complaint about PL/SQL being a verbose language comes to mind. Clearly, stored procedures are new to MySQL but they&#8217;re quite a bit more verbose than PL/SQL.</p>
<p style="clear:both">

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Conditionally drop the procedure.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'UPLOAD_KINGDOM'</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Drop Procedure&quot;</span>;
<span style="color: #993333; font-weight: bold;">DROP</span> PROCEDURE <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> upload_kingdom;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Reset the execution delimiter to create a stored program.</span>
DELIMITER $$
&nbsp;
<span style="color: #808080; font-style: italic;">-- The parentheses after the procedure name must be there or the MODIFIES SQL DATA raises an compile time exception.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> PROCEDURE upload_kingdom<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> MODIFIES SQL <span style="color: #993333; font-weight: bold;">DATA</span>
&nbsp;
BEGIN
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Declare local variables. */</span>
  DECLARE lv_kingdom_id            INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span>;
  DECLARE lv_kingdom_name          VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>;
  DECLARE lv_population            INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span>;
  DECLARE lv_knight_id             INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span>;
  DECLARE lv_knight_name           VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">24</span><span style="color: #66cc66;">&#41;</span>;
  DECLARE lv_kingdom_allegiance_id INT <span style="color: #993333; font-weight: bold;">UNSIGNED</span>;
  DECLARE lv_allegiance_start_date DATE;
  DECLARE lv_allegiance_end_date   DATE;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Declare a handler variables. */</span>
  DECLARE duplicate_key INT <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #cc66cc;">0</span>;
  DECLARE foreign_key   INT <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #cc66cc;">0</span>;
  DECLARE fetched       INT <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #cc66cc;">0</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Cursors must come after variables and before event handlers. */</span>
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Declare a SQL cursor with a left join on the natural key. */</span>  
  DECLARE kingdom_cursor CURSOR <span style="color: #993333; font-weight: bold;">FOR</span>
    <span style="color: #993333; font-weight: bold;">SELECT</span>   <span style="color: #993333; font-weight: bold;">DISTINCT</span>
             k<span style="color: #66cc66;">.</span>kingdom_id
    <span style="color: #66cc66;">,</span>        kki<span style="color: #66cc66;">.</span>kingdom_name
    <span style="color: #66cc66;">,</span>        kki<span style="color: #66cc66;">.</span>population
    <span style="color: #993333; font-weight: bold;">FROM</span>     kingdom_knight_import kki <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> kingdom k
    <span style="color: #993333; font-weight: bold;">ON</span>       kki<span style="color: #66cc66;">.</span>kingdom_name <span style="color: #66cc66;">=</span> k<span style="color: #66cc66;">.</span>kingdom_name
    <span style="color: #993333; font-weight: bold;">AND</span>      kki<span style="color: #66cc66;">.</span>population <span style="color: #66cc66;">=</span> k<span style="color: #66cc66;">.</span>population; 
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Declare a SQL cursor with a join on the natural key. */</span>  
  DECLARE knight_cursor CURSOR <span style="color: #993333; font-weight: bold;">FOR</span>
    <span style="color: #993333; font-weight: bold;">SELECT</span>   kn<span style="color: #66cc66;">.</span>knight_id
    <span style="color: #66cc66;">,</span>        kki<span style="color: #66cc66;">.</span>knight_name
    <span style="color: #66cc66;">,</span>        k<span style="color: #66cc66;">.</span>kingdom_id
    <span style="color: #66cc66;">,</span>        kki<span style="color: #66cc66;">.</span>allegiance_start_date <span style="color: #993333; font-weight: bold;">AS</span> start_date
    <span style="color: #66cc66;">,</span>        kki<span style="color: #66cc66;">.</span>allegiance_end_date <span style="color: #993333; font-weight: bold;">AS</span> end_date
    <span style="color: #993333; font-weight: bold;">FROM</span>     kingdom_knight_import kki <span style="color: #993333; font-weight: bold;">INNER</span> <span style="color: #993333; font-weight: bold;">JOIN</span> kingdom k
    <span style="color: #993333; font-weight: bold;">ON</span>       kki<span style="color: #66cc66;">.</span>kingdom_name <span style="color: #66cc66;">=</span> k<span style="color: #66cc66;">.</span>kingdom_name
    <span style="color: #993333; font-weight: bold;">AND</span>      kki<span style="color: #66cc66;">.</span>population <span style="color: #66cc66;">=</span> k<span style="color: #66cc66;">.</span>population <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> knight kn 
    <span style="color: #993333; font-weight: bold;">ON</span>       k<span style="color: #66cc66;">.</span>kingdom_id <span style="color: #66cc66;">=</span> kn<span style="color: #66cc66;">.</span>kingdom_allegiance_id
    <span style="color: #993333; font-weight: bold;">AND</span>      kki<span style="color: #66cc66;">.</span>knight_name <span style="color: #66cc66;">=</span> kn<span style="color: #66cc66;">.</span>knight_name
    <span style="color: #993333; font-weight: bold;">AND</span>      kki<span style="color: #66cc66;">.</span>allegiance_start_date <span style="color: #66cc66;">=</span> kn<span style="color: #66cc66;">.</span>allegiance_start_date
    <span style="color: #993333; font-weight: bold;">AND</span>      kki<span style="color: #66cc66;">.</span>allegiance_end_date <span style="color: #66cc66;">=</span> kn<span style="color: #66cc66;">.</span>allegiance_end_date; 
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Event handlers must always be last in the declaration section. */</span>
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Declare a duplicate key handler */</span>
  DECLARE CONTINUE HANDLER <span style="color: #993333; font-weight: bold;">FOR</span> <span style="color: #cc66cc;">1062</span> <span style="color: #993333; font-weight: bold;">SET</span> duplicate_key <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;
  DECLARE CONTINUE HANDLER <span style="color: #993333; font-weight: bold;">FOR</span> <span style="color: #cc66cc;">1216</span> <span style="color: #993333; font-weight: bold;">SET</span> foreign_key <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Declare a not found record handler to close a cursor loop. */</span>
  DECLARE CONTINUE HANDLER <span style="color: #993333; font-weight: bold;">FOR</span> <span style="color: #993333; font-weight: bold;">NOT</span> FOUND <span style="color: #993333; font-weight: bold;">SET</span> fetched <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* ---------------------------------------------------------------------- */</span>
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Start transaction context. */</span>
  START TRANSACTION;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Set savepoint. */</span>  
  SAVEPOINT both_or_none;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Open a local cursor. */</span>  
  OPEN kingdom_cursor;
  cursor_kingdom: LOOP
&nbsp;
    FETCH kingdom_cursor
    <span style="color: #993333; font-weight: bold;">INTO</span>  lv_kingdom_id
    <span style="color: #66cc66;">,</span>     lv_kingdom_name
    <span style="color: #66cc66;">,</span>     lv_population;
&nbsp;
    <span style="color: #808080; font-style: italic;">/* Place the catch handler for no more rows found
       immediately after the fetch operation.          */</span>
    <span style="color: #993333; font-weight: bold;">IF</span> fetched <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> THEN LEAVE cursor_kingdom; END <span style="color: #993333; font-weight: bold;">IF</span>;
&nbsp;
    <span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> kingdom
    <span style="color: #993333; font-weight: bold;">VALUES</span>
    <span style="color: #66cc66;">&#40;</span> lv_kingdom_id
    <span style="color: #66cc66;">,</span> lv_kingdom_name
    <span style="color: #66cc66;">,</span> lv_population <span style="color: #66cc66;">&#41;</span> 
    <span style="color: #993333; font-weight: bold;">ON</span> DUPLICATE <span style="color: #993333; font-weight: bold;">KEY</span>
    <span style="color: #993333; font-weight: bold;">UPDATE</span> kingdom_name <span style="color: #66cc66;">=</span> lv_kingdom_name;
&nbsp;
  END LOOP cursor_kingdom;
  CLOSE kingdom_cursor;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Reset the continue handler to zero. */</span>
  <span style="color: #993333; font-weight: bold;">SET</span> fetched <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span>;  
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Open a local cursor. */</span>  
  OPEN knight_cursor;
  cursor_knight: LOOP
&nbsp;
    <span style="color: #808080; font-style: italic;">/* Fetch records until they're all read, and a NOT FOUND SET is returned. */</span>  
    FETCH knight_cursor
    <span style="color: #993333; font-weight: bold;">INTO</span>  lv_knight_id
    <span style="color: #66cc66;">,</span>     lv_knight_name
    <span style="color: #66cc66;">,</span>     lv_kingdom_allegiance_id
    <span style="color: #66cc66;">,</span>     lv_allegiance_start_date
    <span style="color: #66cc66;">,</span>     lv_allegiance_end_date;
&nbsp;
    <span style="color: #808080; font-style: italic;">/* Place the catch handler for no more rows found
       immediately after the fetch operation.          */</span>
    <span style="color: #993333; font-weight: bold;">IF</span> fetched <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> THEN LEAVE cursor_knight; END <span style="color: #993333; font-weight: bold;">IF</span>;
&nbsp;
    <span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> knight
    <span style="color: #993333; font-weight: bold;">VALUES</span>
    <span style="color: #66cc66;">&#40;</span> lv_knight_id
    <span style="color: #66cc66;">,</span> lv_knight_name
    <span style="color: #66cc66;">,</span> lv_kingdom_allegiance_id
    <span style="color: #66cc66;">,</span> lv_allegiance_start_date
    <span style="color: #66cc66;">,</span> lv_allegiance_end_date <span style="color: #66cc66;">&#41;</span> 
    <span style="color: #993333; font-weight: bold;">ON</span> DUPLICATE <span style="color: #993333; font-weight: bold;">KEY</span>
    <span style="color: #993333; font-weight: bold;">UPDATE</span> knight_name <span style="color: #66cc66;">=</span> lv_knight_name;
&nbsp;
  END LOOP cursor_knight;
  CLOSE knight_cursor;
&nbsp;
  <span style="color: #808080; font-style: italic;">/* Reset the continue handler to zero. */</span>
  <span style="color: #993333; font-weight: bold;">SET</span> fetched <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span>;  
&nbsp;
  <span style="color: #808080; font-style: italic;">/* ---------------------------------------------------------------------- */</span>
&nbsp;
  <span style="color: #808080; font-style: italic;">/* This acts as an exception handling block. */</span>  
  <span style="color: #993333; font-weight: bold;">IF</span> duplicate_key <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">OR</span> foreign_key <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> THEN
&nbsp;
    <span style="color: #808080; font-style: italic;">/* This undoes all DML statements to this point in the procedure. */</span>
    ROLLBACK <span style="color: #993333; font-weight: bold;">TO</span> SAVEPOINT both_or_none;
&nbsp;
  ELSE
&nbsp;
    <span style="color: #808080; font-style: italic;">/* This commits the writes. */</span>
    COMMIT;
&nbsp;
  END <span style="color: #993333; font-weight: bold;">IF</span>;
&nbsp;
END;
$$
&nbsp;
<span style="color: #808080; font-style: italic;">-- Reset the delimiter to the default.</span>
DELIMITER ;</pre></td></tr></table></div>

<p style="clear:both">
<p><span style="font-size:115%;font-weight:bold">Step #6 : Run the upload procedure</span></p>
<p>You can run the file by calling the <a href="http://michaelmclaughlin.info/db1/lesson-4-inserting-data/transaction-management/">stored procedure</a> built by the script. The procedure ensures that records are inserted or updated into their respective tables.</p>
<p style="clear:both">

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">CALL upload_kingdom;</pre></div></div>

<p style="clear:both">
<p><span style="font-size:115%;font-weight:bold">Step #7 : Test the results of the upload procedure</span></p>
<p>You can test whether or not it worked by running the following queries.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Check the kingdom table.</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> kingdom;
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> knight;</pre></div></div>

<p>It should display the following information:</p>
<p style="clear:both">

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">+------------+--------------+------------+
| kingdom_id | kingdom_name | population |
+------------+--------------+------------+
|          1 | Narnia       |      77600 |
|          2 | Narnia       |      42100 |
|          3 | Camelot      |      15200 |
+------------+--------------+------------+
&nbsp;
+-----------+-------------------------+-----------------------+-----------------------+---------------------+
| knight_id | knight_name             | kingdom_allegiance_id | allegiance_start_date | allegiance_end_date |
+-----------+-------------------------+-----------------------+-----------------------+---------------------+
|         1 | 'Peter the Magnificent' |                     1 | 1272-03-20            | 1292-06-09          |
|         2 | 'Edmund the Just'       |                     1 | 1272-03-20            | 1292-06-09          |
|         3 | 'Susan the Gentle'      |                     1 | 1272-03-20            | 1292-06-09          |
|         4 | 'Lucy the Valiant'      |                     1 | 1272-03-20            | 1292-06-09          |
|         5 | 'Peter the Magnificent' |                     2 | 1531-04-12            | 1531-05-31          |
|         6 | 'Edmund the Just'       |                     2 | 1531-04-12            | 1531-05-31          |
|         7 | 'Susan the Gentle'      |                     2 | 1531-04-12            | 1531-05-31          |
|         8 | 'Lucy the Valiant'      |                     2 | 1531-04-12            | 1531-05-31          |
|         9 | 'King Arthur'           |                     3 | 0631-03-10            | 0686-12-12          |
|        10 | 'Sir Lionel'            |                     3 | 0631-03-10            | 0686-12-12          |
|        11 | 'Sir Bors'              |                     3 | 0631-03-10            | 0635-12-12          |
|        12 | 'Sir Bors'              |                     3 | 0640-03-10            | 0686-12-12          |
|        13 | 'Sir Galahad'           |                     3 | 0631-03-10            | 0686-12-12          |
|        14 | 'Sir Gawain'            |                     3 | 0631-03-10            | 0686-12-12          |
|        15 | 'Sir Tristram'          |                     3 | 0631-03-10            | 0686-12-12          |
|        16 | 'Sir Percival'          |                     3 | 0631-03-10            | 0686-12-12          |
|        17 | 'Sir Lancelot'          |                     3 | 0670-09-30            | 0682-12-12          |
+-----------+-------------------------+-----------------------+-----------------------+---------------------+</pre></div></div>

<p style="clear:both">
<p>You can rerun the procedure to check that it doesn&#8217;t alter any information, then you could add a new knight to test the insertion portion.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mclaughlinsoftware.com/2010/02/24/multi-row-merge-in-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Merge Statement for ETL</title>
		<link>http://blog.mclaughlinsoftware.com/2010/02/23/merge-statement-for-etl/</link>
		<comments>http://blog.mclaughlinsoftware.com/2010/02/23/merge-statement-for-etl/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 08:28:26 +0000</pubDate>
		<dc:creator>maclochlainn</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Oracle XE]]></category>
		<category><![CDATA[Stored Procedures]]></category>
		<category><![CDATA[pl/sql]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.mclaughlinsoftware.com/?p=3522</guid>
		<description><![CDATA[While working through examples for my students on uploading data, I thought it would be interesting to demonstrate how to create a re-runnable upload. Especially when chatting with a friend who was unaware that you could use joins inside the source element of a MERGE statement. Naturally, the MERGE statement  seemed like the best [...]]]></description>
			<content:encoded><![CDATA[<p>While working through examples for my students on uploading data, I thought it would be interesting to demonstrate how to create a re-runnable upload. Especially when chatting with a friend who was unaware that you could use joins inside the source element of a <code>MERGE</code> statement. Naturally, the <code>MERGE</code> statement  seemed like the best approach in an Oracle database because with my criteria:</p>
<ul>
<li>The source file would not include any surrogate key values.</li>
<li>The source file would have denormalized record sets with data that should belong to <em>parent</em> and <em>child</em> tables, technically unnormalized form (UNF).</li>
<li>Primary and foreign key values would be determined on load to the tables.</li>
<li>There could be a one-to-many relationship between the <em>parent</em> and <em>child</em> tables in the original source.</li>
<li>Subsequent data sets may replicate data already seeded or not in the tables.</li>
<li>Avoid any complex PL/SQL structures.</li>
</ul>
<p><span style="font-size:125%;font-weight:bold">Step #1 : Create a Virtual Directory</span></p>
<p>You can create a virtual directory without a physical directory but it won&#8217;t work when you try to access it. Therefore, you should create the physical directory first. Assuming you&#8217;ve created a <code>C:\Data\Download</code> file directory on the Windows platform, you can then create a virtual directory and grant permissions to the <code>student</code> user as the <code>SYS</code> privileged user. The syntax for these steps is:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> DIRECTORY download <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">'C:<span style="color: #000099; font-weight: bold;">\D</span>ata<span style="color: #000099; font-weight: bold;">\D</span>ownload'</span>;
<span style="color: #993333; font-weight: bold;">GRANT</span> <span style="color: #993333; font-weight: bold;">READ</span><span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">WRITE</span> <span style="color: #993333; font-weight: bold;">ON</span> DIRECTORY download <span style="color: #993333; font-weight: bold;">TO</span> student;</pre></div></div>

<p>If you want more detail on these steps, check <a href="http://blog.mclaughlinsoftware.com/oracle-sql-programming/creating-an-external-table-that-uses-sqlloader/">this older post on the blog</a>.</p>
<p><span style="font-size:125%;font-weight:bold">Step #2 : Create the Target and External Tables</span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Conditionally drop tables and sequences.</span>
BEGIN
  <span style="color: #993333; font-weight: bold;">FOR</span> i <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> table_name
            <span style="color: #993333; font-weight: bold;">FROM</span>   user_tables
            <span style="color: #993333; font-weight: bold;">WHERE</span>  table_name <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'KINGDOM'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'KNIGHT'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'KINGDOM_KNIGHT_IMPORT'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> LOOP 
    EXECUTE IMMEDIATE <span style="color: #ff0000;">'DROP TABLE '</span><span style="color: #66cc66;">||</span>i<span style="color: #66cc66;">.</span>table_name<span style="color: #66cc66;">||</span><span style="color: #ff0000;">' CASCADE CONSTRAINTS'</span>;
  END LOOP;
  <span style="color: #993333; font-weight: bold;">FOR</span> i <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> sequence_name
            <span style="color: #993333; font-weight: bold;">FROM</span>   user_sequences
            <span style="color: #993333; font-weight: bold;">WHERE</span>  sequence_name <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'KINGDOM_S1'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'KNIGHT_S1'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> LOOP 
    EXECUTE IMMEDIATE <span style="color: #ff0000;">'DROP SEQUENCE '</span><span style="color: #66cc66;">||</span>i<span style="color: #66cc66;">.</span>sequence_name;
  END LOOP;
END;
<span style="color: #66cc66;">/</span>
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create normalized kingdom table.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> kingdom
<span style="color: #66cc66;">&#40;</span> kingdom_id    NUMBER
<span style="color: #66cc66;">,</span> kingdom_name  VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> population    NUMBER<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create a sequence for the kingdom table.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> SEQUENCE kingdom_s1;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create normalized knight table.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> knight
<span style="color: #66cc66;">&#40;</span> knight_id             NUMBER
<span style="color: #66cc66;">,</span> knight_name           VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">24</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> kingdom_allegiance_id NUMBER
<span style="color: #66cc66;">,</span> allegiance_start_date DATE
<span style="color: #66cc66;">,</span> allegiance_end_date   DATE<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create a sequence for the knight table.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> SEQUENCE knight_s1;
&nbsp;
<span style="color: #808080; font-style: italic;">-- Create external import table.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> kingdom_knight_import
<span style="color: #66cc66;">&#40;</span> kingdom_name          VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> population            NUMBER
<span style="color: #66cc66;">,</span> knight_name           VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">24</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span> allegiance_start_date DATE
<span style="color: #66cc66;">,</span> allegiance_end_date   DATE<span style="color: #66cc66;">&#41;</span>
  ORGANIZATION EXTERNAL
  <span style="color: #66cc66;">&#40;</span> TYPE oracle_loader
    <span style="color: #993333; font-weight: bold;">DEFAULT</span> DIRECTORY download
    ACCESS PARAMETERS
    <span style="color: #66cc66;">&#40;</span> RECORDS DELIMITED <span style="color: #993333; font-weight: bold;">BY</span> NEWLINE CHARACTERSET US7ASCII
      BADFILE     <span style="color: #ff0000;">'DOWNLOAD'</span>:<span style="color: #ff0000;">'kingdom_import.bad'</span>
      DISCARDFILE <span style="color: #ff0000;">'DOWNLOAD'</span>:<span style="color: #ff0000;">'kingdom_import.dis'</span>
      LOGFILE     <span style="color: #ff0000;">'DOWNLOAD'</span>:<span style="color: #ff0000;">'kingdom_import.log'</span>
      <span style="color: #993333; font-weight: bold;">FIELDS</span> TERMINATED <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #ff0000;">','</span>
      <span style="color: #993333; font-weight: bold;">OPTIONALLY</span> <span style="color: #993333; font-weight: bold;">ENCLOSED</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #ff0000;">&quot;'&quot;</span>
      MISSING <span style="color: #993333; font-weight: bold;">FIELD</span> <span style="color: #993333; font-weight: bold;">VALUES</span> ARE <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">&#41;</span>
    LOCATION <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'kingdom_import.csv'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
REJECT <span style="color: #993333; font-weight: bold;">LIMIT</span> UNLIMITED;</pre></td></tr></table></div>

<p><span style="font-size:125%;font-weight:bold">Step #3 : Create a Procedure to ensure an all or nothing transaction</span></p>
<p>The procedure ensures that an <em>all or nothing</em> transaction occurs to both tables. Inside the procedure you have two <a href="http://blog.mclaughlinsoftware.com/2009/05/25/mysql-merge-gone-awry/"><code>MERGE</code> statements</a>.</p>
<p>The first <code>MERGE</code> statement uses a <code>LEFT JOIN</code> to ensure that any new <code>kingdom_name</code> will be added to the <code>kingdom</code> table. The <code>kingdom_name</code> and <code>population</code> columns are the <em>natural key</em> in this model. The second <code>MERGE</code> statement uses an <code>INNER JOIN</code> to ensure that <code>knight</code> rows are only inserted when they belong to an existing <code>kingdom_name</code>. Naturally, the primary key capture occurs in this statement and it maps the primary key to the foreign key column in the <code>knight</code> table.</p>
<p>The complete procedure code follows:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- Create a procedure to wrap the transaction.</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">REPLACE</span> PROCEDURE upload_kingdom <span style="color: #993333; font-weight: bold;">IS</span> 
BEGIN
  <span style="color: #808080; font-style: italic;">-- Set save point for an all or nothing transaction.</span>
  SAVEPOINT starting_point;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Insert or update the table, which makes this rerunnable when the file hasn't been updated.  </span>
  MERGE <span style="color: #993333; font-weight: bold;">INTO</span> kingdom target
  <span style="color: #993333; font-weight: bold;">USING</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span>   <span style="color: #993333; font-weight: bold;">DISTINCT</span>
                  k<span style="color: #66cc66;">.</span>kingdom_id
         <span style="color: #66cc66;">,</span>        kki<span style="color: #66cc66;">.</span>kingdom_name
         <span style="color: #66cc66;">,</span>        kki<span style="color: #66cc66;">.</span>population
         <span style="color: #993333; font-weight: bold;">FROM</span>     kingdom_knight_import kki <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> kingdom k
         <span style="color: #993333; font-weight: bold;">ON</span>       kki<span style="color: #66cc66;">.</span>kingdom_name <span style="color: #66cc66;">=</span> k<span style="color: #66cc66;">.</span>kingdom_name
         <span style="color: #993333; font-weight: bold;">AND</span>      kki<span style="color: #66cc66;">.</span>population <span style="color: #66cc66;">=</span> k<span style="color: #66cc66;">.</span>population<span style="color: #66cc66;">&#41;</span> source
  <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #66cc66;">&#40;</span>target<span style="color: #66cc66;">.</span>kingdom_id <span style="color: #66cc66;">=</span> source<span style="color: #66cc66;">.</span>kingdom_id<span style="color: #66cc66;">&#41;</span>
  WHEN MATCHED THEN
  <span style="color: #993333; font-weight: bold;">UPDATE</span> <span style="color: #993333; font-weight: bold;">SET</span> kingdom_name <span style="color: #66cc66;">=</span> source<span style="color: #66cc66;">.</span>kingdom_name
  WHEN <span style="color: #993333; font-weight: bold;">NOT</span> MATCHED THEN
  <span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">VALUES</span>
  <span style="color: #66cc66;">&#40;</span> kingdom_s1<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">NEXTVAL</span>
  <span style="color: #66cc66;">,</span> source<span style="color: #66cc66;">.</span>kingdom_name
  <span style="color: #66cc66;">,</span> source<span style="color: #66cc66;">.</span>population<span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Insert or update the table, which makes this rerunnable when the file hasn't been updated.  </span>
  MERGE <span style="color: #993333; font-weight: bold;">INTO</span> knight target
  <span style="color: #993333; font-weight: bold;">USING</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span>   k<span style="color: #66cc66;">.</span>kingdom_id
         <span style="color: #66cc66;">,</span>        kki<span style="color: #66cc66;">.</span>knight_name
         <span style="color: #66cc66;">,</span>        kki<span style="color: #66cc66;">.</span>allegiance_start_date <span style="color: #993333; font-weight: bold;">AS</span> start_date
         <span style="color: #66cc66;">,</span>        kki<span style="color: #66cc66;">.</span>allegiance_end_date <span style="color: #993333; font-weight: bold;">AS</span> end_date
         <span style="color: #993333; font-weight: bold;">FROM</span>     kingdom_knight_import kki <span style="color: #993333; font-weight: bold;">INNER</span> <span style="color: #993333; font-weight: bold;">JOIN</span> kingdom k
         <span style="color: #993333; font-weight: bold;">ON</span>       kki<span style="color: #66cc66;">.</span>kingdom_name <span style="color: #66cc66;">=</span> k<span style="color: #66cc66;">.</span>kingdom_name
         <span style="color: #993333; font-weight: bold;">AND</span>      kki<span style="color: #66cc66;">.</span>population <span style="color: #66cc66;">=</span> k<span style="color: #66cc66;">.</span>population<span style="color: #66cc66;">&#41;</span> source
  <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #66cc66;">&#40;</span>target<span style="color: #66cc66;">.</span>kingdom_allegiance_id <span style="color: #66cc66;">=</span> source<span style="color: #66cc66;">.</span>kingdom_id<span style="color: #66cc66;">&#41;</span>
  WHEN MATCHED THEN
  <span style="color: #993333; font-weight: bold;">UPDATE</span> <span style="color: #993333; font-weight: bold;">SET</span> allegiance_start_date <span style="color: #66cc66;">=</span> source<span style="color: #66cc66;">.</span>start_date
  <span style="color: #66cc66;">,</span>          allegiance_end_date <span style="color: #66cc66;">=</span> source<span style="color: #66cc66;">.</span>end_date
  WHEN <span style="color: #993333; font-weight: bold;">NOT</span> MATCHED THEN
  <span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">VALUES</span>
  <span style="color: #66cc66;">&#40;</span> knight_s1<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">NEXTVAL</span>
  <span style="color: #66cc66;">,</span> source<span style="color: #66cc66;">.</span>knight_name
  <span style="color: #66cc66;">,</span> source<span style="color: #66cc66;">.</span>kingdom_id
  <span style="color: #66cc66;">,</span> source<span style="color: #66cc66;">.</span>start_date
  <span style="color: #66cc66;">,</span> source<span style="color: #66cc66;">.</span>end_date<span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Save the changes.</span>
  COMMIT;
&nbsp;
EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK <span style="color: #993333; font-weight: bold;">TO</span> starting_point;
    <span style="color: #993333; font-weight: bold;">RETURN</span>;
END;
<span style="color: #66cc66;">/</span></pre></td></tr></table></div>

<p><span style="font-size:125%;font-weight:bold">Step #4 : Test the Process</span></p>
<p>You can test it by calling the procedure. Rerunning it will demonstrate that it doesn&#8217;t violate any of the rules.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">EXECUTE upload_kingdom;</pre></div></div>

<p>As always, I hope this is useful to somebody besides me.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mclaughlinsoftware.com/2010/02/23/merge-statement-for-etl/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP Binding a Wildcard</title>
		<link>http://blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard/</link>
		<comments>http://blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 07:13:31 +0000</pubDate>
		<dc:creator>maclochlainn</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[MAMP]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.mclaughlinsoftware.com/?p=3515</guid>
		<description><![CDATA[Somebody asked me about how you bind a parameter in mysqli when a multiple character wildcard needs to be next to the variable value. They&#8217;d found that it worked when creating a SQL statement by concatenation (string gluing), like this:

$sql = &#34;SELECT item_title FROM item WHERE item_title LIKE '%&#34;.$title.&#34;%'&#34;;

However, they tried to bind the variable [...]]]></description>
			<content:encoded><![CDATA[<p>Somebody asked me about how you bind a parameter in <code>mysqli</code> when a multiple character wildcard needs to be next to the variable value. They&#8217;d found that it worked when creating a SQL statement by concatenation (string gluing), like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT item_title FROM item WHERE item_title LIKE '%&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$title</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;%'&quot;</span><span style="color: #339933;">;</span></pre></div></div>

<p>However, they tried to bind the variable following the same pattern, and found that it failed. They used the following type of syntax:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT item_title FROM item WHERE item_title LIKE '%?%'&quot;</span><span style="color: #339933;">;</span></pre></div></div>

<p>It raised the following error:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">Warning<span style="color: #339933;">:</span> <span style="color: #990000;">mysqli_stmt_bind_param</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#91;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #339933;">.</span>mysqli<span style="color: #339933;">-</span>stmt<span style="color: #339933;">-</span>bind<span style="color: #339933;">-</span>param<span style="color: #009900;">&#93;</span><span style="color: #339933;">:</span> Number of variables doesn<span style="color: #0000ff;">'t match number of parameters in prepared statement in program_name on line #</span></pre></div></div>

<p>The reason is the parser, it expects variables to be independent tokens in the SQL string. You can&#8217;t bind a string into the shell of an apostrophe delimited string. You could naturally, make an assignment to the local PHP variable before binding it to the variable, like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$title</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'%'</span><span style="color: #339933;">.</span><span style="color: #000088;">$title</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'%'</span><span style="color: #339933;">;</span></pre></div></div>

<p>It&#8217;s actually a better idea to concatenate the multiple character wildcard operator inside the SQL statement. The correct syntax requires that you use the <code>CONCAT()</code> function. You could reset to use piped concatenation but generally you should avoid that on the MySQL platform (see <a href="http://blog.mclaughlinsoftware.com/2009/03/09/sql-concatenation-blues/">this post</a> for an explanation of SQL concatenation on Oracle, MySQL, and SQL Server).</p>
<p>This is the required statement when using a MySQL database:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT item_title FROM item WHERE item_title LIKE CONCAT('%',?,'%')&quot;</span><span style="color: #339933;">;</span></pre></div></div>

<div class="dropdownbox" style="padding-left:20px;background:#FFFFFF">
<p title="Click to see content ..." class="dropdownclick"><strong><em><span style="font-size:125%">Complete Code Sample</span></em></strong> <span>&darr;</span></p>
<p style="clear: both">
Expand this section to see the complete working code sample.</p>
<div>
<p>The first component for this program is an include file for the database credentials:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
  <span style="color: #666666; font-style: italic;">// Connection variables.</span>
  <span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HOSTNAME'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;localhost&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'USERNAME'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;student&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'PASSWORD'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;student&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'DATABASE'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;sampledb&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Once you&#8217;ve placed the credentials in your directory, you can put this in the same directory and then call it from your browser. At least, you can provided you&#8217;ve created the user with the required password, and the database on the standard <code>3306</code> port.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
  <span style="color: #666666; font-style: italic;">// Set database credentials.</span>
  <span style="color: #b1b100;">include_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;MySQLCredentials.inc&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Return successful attempt to connect to the database.</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$c</span> <span style="color: #339933;">=</span> <span style="color: #339933;">@</span><span style="color: #990000;">mysqli_connect</span><span style="color: #009900;">&#40;</span>HOSTNAME<span style="color: #339933;">,</span>USERNAME<span style="color: #339933;">,</span>PASSWORD<span style="color: #339933;">,</span>DATABASE<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Print user message.</span>
    <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;Sorry! The connection to the database failed. Please try again later.&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Assign the OCI error and format double and single quotes.</span>
    <span style="color: #b1b100;">print</span> <span style="color: #990000;">mysqli_error</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Kill the resource.</span>
    <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Declare input variables.</span>
    <span style="color: #000088;">$title</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'title'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'title'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$title</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;RoboCop&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    query_insert<span style="color: #009900;">&#40;</span><span style="color: #000088;">$title</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Query results afret an insert.</span>
  <span style="color: #000000; font-weight: bold;">function</span> query_insert<span style="color: #009900;">&#40;</span><span style="color: #000088;">$title</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Return successful attempt to connect to the database.</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$c</span>  <span style="color: #339933;">=</span> <span style="color: #339933;">@</span><span style="color: #990000;">mysqli_connect</span><span style="color: #009900;">&#40;</span>HOSTNAME<span style="color: #339933;">,</span>USERNAME<span style="color: #339933;">,</span>PASSWORD<span style="color: #339933;">,</span>DATABASE<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">// Print user message.</span>
      <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;Sorry! The connection to the database failed. Please try again later.&quot;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #666666; font-style: italic;">// Assign the OCI error and format double and single quotes.</span>
      <span style="color: #b1b100;">print</span> <span style="color: #990000;">mysqli_error</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #666666; font-style: italic;">// Kill the resource.</span>
      <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
&nbsp;
      <span style="color: #666666; font-style: italic;">// Initialize a statement in the scope of the connection.</span>
      <span style="color: #000088;">$stmt</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysqli_stmt_init</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$c</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #666666; font-style: italic;">// Declare a SQL SELECT statement returning a CLOB.</span>
      <span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT item_title FROM item WHERE item_title LIKE CONCAT('%',?,'%')&quot;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #666666; font-style: italic;">// Prepare statement.</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">mysqli_stmt_prepare</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$stmt</span><span style="color: #339933;">,</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #990000;">mysqli_stmt_bind_param</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$stmt</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;s&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$title</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Execute it and print success or failure message.</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">mysqli_stmt_execute</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$stmt</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
          <span style="color: #666666; font-style: italic;">// Store result.</span>
          <span style="color: #990000;">mysqli_stmt_store_result</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$stmt</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
          <span style="color: #666666; font-style: italic;">// Bind result to local variable.</span>
          <span style="color: #990000;">mysqli_stmt_bind_result</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$stmt</span><span style="color: #339933;">,</span><span style="color: #000088;">$item_title</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
          <span style="color: #666666; font-style: italic;">// Open HTML table and print header.</span>
          <span style="color: #000088;">$out</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'&lt;table border=&quot;1&quot; cellpadding=&quot;3&quot; cellspacing=&quot;0&quot;&gt;'</span><span style="color: #339933;">;</span>
          <span style="color: #000088;">$out</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;tr&gt;'</span><span style="color: #339933;">;</span>
          <span style="color: #000088;">$out</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;th align=&quot;center&quot; style=&quot;font-weight:bold;padding:2px;margin:1px;background:#8DB3E2;width:300px&quot;&gt;Item Title&lt;/th&gt;'</span><span style="color: #339933;">;</span>
          <span style="color: #000088;">$out</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;/tr&gt;'</span><span style="color: #339933;">;</span>
&nbsp;
          <span style="color: #666666; font-style: italic;">// Read result.</span>
          <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">mysqli_stmt_fetch</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$stmt</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$out</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;tr&gt;'</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$out</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;td style=&quot;padding:2px;margin:1px;background:#DBE5F1;&quot;&gt;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$item_title</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&lt;/td&gt;'</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$out</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;/tr&gt;'</span><span style="color: #339933;">;</span>
          <span style="color: #009900;">&#125;</span>
&nbsp;
          <span style="color: #666666; font-style: italic;">// Close the HTML table.</span>
          <span style="color: #000088;">$out</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;/table&gt;'</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
          <span style="color: #666666; font-style: italic;">// Print the HTML table.</span>
          <span style="color: #b1b100;">print</span> <span style="color: #000088;">$out</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #666666; font-style: italic;">// Free system resources.</span>
      <span style="color: #990000;">mysqli_stmt_free_result</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$stmt</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #666666; font-style: italic;">// Disconnect from database.</span>
      <span style="color: #990000;">mysqli_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$c</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
