<?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>Instructor&#039;s blog</title>
	<atom:link href="http://blog.impartica-training.co.uk/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://blog.impartica-training.co.uk</link>
	<description>Impartica IT Training</description>
	<lastBuildDate>Thu, 01 Jul 2010 04:29:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Date formatting in SQL Server</title>
		<link>http://blog.impartica-training.co.uk/?p=103</link>
		<comments>http://blog.impartica-training.co.uk/?p=103#comments</comments>
		<pubDate>Thu, 01 Jul 2010 04:29:58 +0000</pubDate>
		<dc:creator>dbullen</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Microsoft SQL Server]]></category>

		<guid isPermaLink="false">http://blog.impartica-training.co.uk/?p=103</guid>
		<description><![CDATA[One of the comments that often comes up in the Introduction to SQL course, is that Oracle provides much more in the way of formatting dates than SQL Server. I&#8217;m aware that many people are of the view, &#8220;formatting should be done in the client application, it&#8217;s not the job of the database&#8221;. I agree [...]]]></description>
			<content:encoded><![CDATA[<p>One of the comments that often comes up in the <a href="http://www.impartica-training.co.uk/courses/introduction-to-sql.aspx" target="_blank">Introduction to SQL</a> course, is that Oracle provides much more in the way of formatting dates than SQL Server. I&#8217;m aware that many people are of the view, &#8220;formatting should be done in the client application, it&#8217;s not the job of the database&#8221;. I agree with that to a certain extent &#8211; good practice will often dictate that formatting should be done outside of the database &#8211; but there are times when I get frustrated at the limitations of SQL Server in this area.</p>
<p>For one thing, SQL Server provides the ability to <a href="http://msdn.microsoft.com/en-us/library/ms175887.aspx" target="_blank">send emails</a> from within the database. I would have thought that this alone justifies better formatting than is currently available.</p>
<p>Secondly, we don&#8217;t live in a perfect world where we have the choice to put all code in the correct layer every time.  We might only have control of the data tier, with a presentation tier displaying everything returned from a stored procedure, and we may not be able to change the code in that presentation tier.</p>
<p>And finally, if date formatting should never be done in the database, why bother providing the <a href="http://msdn.microsoft.com/en-us/library/ms187928.aspx" target="_blank">CONVERT</a> function at all? To provide it, but with only a very limited set of formats, seems inconsistent.</p>
<p>So one of the first thing I did when I came to SQL Server from Oracle was to code up a quick and simple date formatting routine, that I wanted to work in a similar way to Oracle&#8217;s <a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/functions188.htm#i1009324" target="_blank">TO_CHAR</a> function for dates. I only included the most basic format support and expected to have to extend it regularly as my requirements got more complex, but in fact I don&#8217;t think I&#8217;ve done much in the way if altering it, it pretty much has met my requirements whenever I&#8217;ve needed it. I still use CONVERT when one of the Microsoft supplied date formats is acceptable, but this allows me a bit more flexibility. Being a user defined function, performance will be affected, so I use it sparingly, but it definitely comes in handy. It&#8217;s designed to accept a date, and then an Oracle-style format, like &#8216;DD MON YY HH:MI&#8217;, and it returns the input date in the specified format, as a string. Alternatively I allow the passing of special strings like &#8216;Standard Date&#8217;, &#8216;Time only&#8217; etc, which can be customised for the requirements of a particular project.</p>
<p>As it was almost the first UDF I wrote, it doesn&#8217;t use best coding practices, and I can now see several improvements I could make, but for the few times I need it, this works fine for me. If it&#8217;s useful for you, feel free to copy it, and maybe make some of those long awaited improvements I never got round to making.</p>
<p>Dean</p>
<p><code>=====================================================================================<br />
-- Author: D Bullen<br />
-- Description: This procedure accepts a date value, formats it, and returns it as a string.<br />
-- The format is passed in as the @Format parameter, and it accepts the following:<br />
-- DD - Date<br />
-- MM - Month number<br />
-- MNTH - Month Name<br />
-- MON - Month Short Name<br />
-- YYYY - 4 digit year<br />
-- YY - 2 digit year<br />
-- HH - Hours<br />
-- MI - Minutes<br />
--<br />
-- Alternatively prefined standard formats can be passed in and translated into basic<br />
-- format types, e.g. 'Standard Date &amp; Time' - translated to 'DD MNTH YYYY at HH:MI'<br />
-- =====================================================================================<br />
CREATE FUNCTION [General].[FormattedDate]<br />
( @DateIn DATETIME<br />
,@Format VARCHAR(100))<br />
RETURNS VARCHAR(100)<br />
AS<br />
BEGIN<br />
DECLARE @FormattedDate VARCHAR(100)<br />
<code><br />
IF @Format = 'Standard Date' SET @Format = 'DD MNTH YYYY'<br />
IF @Format = 'Standard Date &amp; Time' SET @Format = 'DD MNTH YYYY at HH:MI'<br />
IF @Format = 'Short Date' SET @Format = 'DD MON YY'<br />
IF @Format = 'Short Date &amp; Time' SET @Format = 'DD MON YY HH:MI'<br />
IF @Format = 'Time Only' SET @Format = 'HH:MI'<br />
<code><br />
DECLARE @DateNum VARCHAR(2)<br />
SET @DateNum = CASE WHEN LEN(CAST(DATEPART(day, @DateIn) AS VARCHAR)) = 2 THEN CAST(DATEPART(day, @DateIn) AS VARCHAR) ELSE '0' + CAST(DATEPART(day, @DateIn) AS VARCHAR) END<br />
DECLARE @MonthNum VARCHAR(2)<br />
SET @MonthNum = CASE WHEN LEN(CAST(DATEPART(month, @DateIn) AS VARCHAR)) = 2 THEN CAST(DATEPART(month, @DateIn) AS VARCHAR) ELSE '0' + CAST(DATEPART(month, @DateIn) AS VARCHAR) END<br />
DECLARE @MonthName VARCHAR(20)<br />
SET @MonthName = DATENAME(month, @DateIn)<br />
DECLARE @MonthShortName VARCHAR(3)<br />
SET @MonthShortName = SUBSTRING(@MonthName, 1, 3)<br />
DECLARE @YearName VARCHAR(4)<br />
SET @YearName = DATENAME(year, @DateIn)<br />
DECLARE @YearShortName VARCHAR(2)<br />
SET @YearShortName = SUBSTRING(@YearName, 3, 2)<br />
DECLARE @Hours VARCHAR(2)<br />
SET @Hours = CASE WHEN LEN(CAST(DATEPART(hour, @DateIn) AS VARCHAR)) = 2 THEN CAST(DATEPART(hour, @DateIn) AS VARCHAR) ELSE '0' + CAST(DATEPART(hour, @DateIn) AS VARCHAR) END<br />
DECLARE @Minutes VARCHAR(2)<br />
SET @Minutes = CASE WHEN LEN(CAST(DATEPART(minute, @DateIn) AS VARCHAR)) = 2 THEN CAST(DATEPART(minute, @DateIn) AS VARCHAR) ELSE '0' + CAST(DATEPART(minute, @DateIn) AS VARCHAR) END<br />
<code><br />
SET @FormattedDate = @Format<br />
SET @FormattedDate = REPLACE(@FormattedDate, 'DD', @DateNum)<br />
SET @FormattedDate = REPLACE(@FormattedDate, 'MM', @MonthNum)<br />
SET @FormattedDate = REPLACE(@FormattedDate, 'MNTH', @MonthName)<br />
SET @FormattedDate = REPLACE(@FormattedDate, 'MON', @MonthShortName)<br />
SET @FormattedDate = REPLACE(@FormattedDate, 'YYYY', @YearName)<br />
SET @FormattedDate = REPLACE(@FormattedDate, 'YY', @YearShortName)<br />
SET @FormattedDate = REPLACE(@FormattedDate, 'HH', @Hours)<br />
SET @FormattedDate = REPLACE(@FormattedDate, 'MI', @Minutes)<br />
<code><br />
IF @Format = 'Standard Date &amp; Time' AND @FormattedDate LIKE '%at 00:00' SET @FormattedDate = REPLACE(@FormattedDate, 'at 00:00', '')<br />
<code><br />
RETURN @FormattedDate<br />
<code><br />
END<br />
</code></code></code></code></code></code></code></p>
<p><strong>About the poster</strong><br />
<img src="http://www.impartica-training.co.uk/images/deanbullen.jpg" alt="Dean Bullen" /><br />
<em>Dean Bullen is Impartica’s SQL course leader and has been working with SQL since 1998. He previously worked for Oracle and has been working with SQL Server since 2006.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.impartica-training.co.uk/?feed=rss2&amp;p=103</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What changed?</title>
		<link>http://blog.impartica-training.co.uk/?p=61</link>
		<comments>http://blog.impartica-training.co.uk/?p=61#comments</comments>
		<pubDate>Thu, 10 Jun 2010 10:13:33 +0000</pubDate>
		<dc:creator>Dr Chris Brown</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Operating systems]]></category>

		<guid isPermaLink="false">http://blog.impartica-training.co.uk/?p=61</guid>
		<description><![CDATA[Have you ever used a graphical configuration tool on Linux and wondered what it was actually doing behind the scenes? Well, here&#8217;s a tip to help you find which config files were being modified.
First, run the command
$ touch /tmp/now
All we&#8217;re doing here is to create a file with a timestamp of &#8220;right now&#8221;.
Now fire up [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever used a graphical configuration tool on Linux and wondered what it was actually doing behind the scenes? Well, here&#8217;s a tip to help you find which config files were being modified.</p>
<p>First, run the command</p>
<p><code>$ touch /tmp/now</code></p>
<p>All we&#8217;re doing here is to create a file with a timestamp of &#8220;right now&#8221;.</p>
<p>Now fire up your graphical config tool and make whatever change you want. Immediately afterwards, run the command:</p>
<p><code>$ find /etc -newer /tmp/now 2> /dev/null</code></p>
<p>This will show you all the files under the /etc directory (where most system configuration files live) that have been modified since you ran the &#8216;touch&#8217; command. (My assumption is that this is system-wide configuration you were changing, not a per-user setting. All per-user settings, of course, are stored in your home directory, not under /etc.)</p>
<p>The technique isn&#8217;t foolproof &#8212; you may get some false positives (files that changed for some other reason), but it&#8217;s a pretty good guide.</p>
<p>Here&#8217;s an example &#8212; on Ubuntu I used the System -> Administration -> Login Window tool to change the theme used by the login screen. After this, the find command produced output like this:</p>
<p><code><br />
$ find /etc -newer /tmp/now 2> /dev/null<br />
/etc/gdm<br />
/etc/gdm/gdm.conf-custom<br />
</code></p>
<p>Now that we know which file got changed, we can go a step further and investigate which entries in the file were altered. Begin by making a copy of the current configuration:</p>
<p><code>$ cp /etc/gdm/gdm.conf-custom /tmp</code></p>
<p>Now run the Login Window configuration tool again and make another change. Afterwards, display the differences between the original configuration file and the new one:</p>
<p><code><br />
$ diff /etc/gdm/gdm.conf-custom /tmp/gdm.conf-custom<br />
79,82c79<br />
< GraphicalTheme=circles<br />
---<br />
> GraphicalTheme=HumanCircle<br />
</code></p>
<p>Now, you can see exactly which lines within the config file were changed.</p>
<p><img src="http://impartica-training.co.uk/wordpress/wp-content/uploads/2009/12/cbrown1.PNG" height="185px" width="144px" style="float:right;" alt="Chris Brown" /></p>
<p><strong>About the poster</strong></p>
<p><em>Dr Chris Brown is Impartica’s Linux course leader and has been using UNIX for over 30 years. He is author of the book “UNIX Distributed Programming” published by Prentice Hall, and of “SUSE Linux” published by O’Reilly. He also writes a regular column for the UK magazine “Linux Format”.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.impartica-training.co.uk/?feed=rss2&amp;p=61</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Joining tables on values in different records</title>
		<link>http://blog.impartica-training.co.uk/?p=91</link>
		<comments>http://blog.impartica-training.co.uk/?p=91#comments</comments>
		<pubDate>Mon, 01 Mar 2010 18:05:56 +0000</pubDate>
		<dc:creator>dbullen</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Microsoft SQL Server]]></category>

		<guid isPermaLink="false">http://blog.impartica-training.co.uk/?p=91</guid>
		<description><![CDATA[At a recent running of our Introduction to SQL course, a delegate asked me a great question, when we were on the subject of joining multiple tables.  He had a requirement to link two tables, based on values that were not held in different fields of the same record, but in the same field [...]]]></description>
			<content:encoded><![CDATA[<p><em>At a recent running of our <a href="http://www.impartica-training.co.uk/courses/introduction-to-sql.aspx">Introduction to SQL</a> course, a delegate asked me a great question, when we were on the subject of joining multiple tables.  He had a requirement to link two tables, based on values that were not held in different fields of the same record, but in the same field in different records.  The platform was SQL Server 2005.</em></p>
<p><strong>Problem</strong></p>
<p>Specifically, he had a table which held details of stocks traded.  For simplicity, let&#8217;s just image it has two columns &#8211; amount_sold and date_sold.  Such a table might look like this:</p>
<pre>
SELECT amount_sold, date_sold FROM stock_sales 

amount_sold  date_sold
-----------  -----------------------
1700         2010-02-15 00:59:49.190
1900         2010-02-16 05:47:49.203
1400         2010-02-24 20:11:45.873
</pre>
<p>The table he needed to join to held exchange rate values at different points in time.  Again stripped down to the columns relevant to our problem, we could imagine it would look something like this:</p>
<pre>
SELECT rate, effective_date FROM exchange_rate 

rate      effective_date
--------- -----------------------
1.09      2010-01-01 00:00:00.000
1.12      2010-02-17 11:14:00.000
1.2       2010-02-20 13:24:00.000
</pre>
<p>What he wanted to do &#8211; as you can probably already anticipate &#8211; is to find the appropriate exchange rate for each sale, in other words to join the stock_sales table to exchange_rate, where date_sold is greater than or equal to effective_date, but less than effective_date <em>in the next</em> exchange_rate record.</p>
<p>Great problem!  In 12 years I find it difficult to believe I haven&#8217;t come across this type of problem before, but if I have I can&#8217;t remember it!  So it gave me some thinking to do.</p>
<p>Here is my answer to the problem.  Please let me know if you can find a better one!</p>
<p><strong>My solution</strong></p>
<p>My immediate thought was that if the exchange_rate table was in a format that held &#8220;effective from&#8221; and &#8220;effective to&#8221; columns, then the solution would be easy to achieve with a standard non-equijoin.  So if it looked like this:</p>
<pre>
rate    effective_date_from     effective_date_to
------- ----------------------- -----------------------
1.09    2010-01-01 00:00:00.000 2010-02-17 11:14:00.000
1.12    2010-02-17 11:14:00.000 2010-02-20 13:24:00.000
1.2     2010-02-20 13:24:00.000 2010-02-27 14:44:49.830
</pre>
<p>Then this query would give him the data he needed.</p>
<pre>
SELECT amount_sold, date_sold, rate
FROM stock_sales
INNER JOIN exchange_rate
ON (stock_sales.date_sold &gt;= exchange_rate.effective_date_from AND stock_sales.date_sold &lt; exchange_rate.effective_date_to)

amount_sold date_sold               rate
----------- ----------------------- ------
1700        2010-02-15 00:59:49.190 1.09
1900        2010-02-16 05:47:49.203 1.09
1400        2010-02-24 20:11:45.873 1.2
</pre>
<p>So, if I could get my exchange_rate data into that format, then I could use an inline view to get my desired result.  (I could also use a common table expression, and this would be slightly easier, but as these weren&#8217;t covered on the course I was delivering I preferred to stick to inline views).  So how to get my data in the format I wanted?</p>
<p>I thought a good starting point would be to generate two copies of the exchange_rate table data.  If I could then give each one an ID column, then I could join them together, matching each row in the first table to the following row in the second table.  Then the effective_date column from the first table would be my &#8220;effective_date_to&#8221; column, and the same column from the second table would be &#8220;effective_date_from&#8221;.  To generate the &#8220;ID&#8221; column for each, I used the ROW_NUMBER() function.</p>
<p>The query
<pre>SELECT ROW_NUMBER() OVER (ORDER BY effective_date) rownum, rate, effective_date FROM exchange_rate</pre>
<p>gives me my first copy of the data, with a numeric &#8220;key&#8221; against each record, like so:</p>
<pre>
rownum   rate    effective_date
-------- ------- -----------------------
1        1.09    2010-01-01 00:00:00.000
2        1.12    2010-02-17 11:14:00.000
3        1.2     2010-02-20 13:24:00.000
</pre>
<p>I can therefore slightly adapt that, subtracting 1 from the generated number, to provide a second copy of the data:</p>
<pre>
SELECT (ROW_NUMBER() OVER (ORDER BY effective_date))-1 rownum, rate, effective_date FROM exchange_rate 

rownum   rate    effective_date
-------- ------- -----------------------
0        1.09    2010-01-01 00:00:00.000
1        1.12    2010-02-17 11:14:00.000
2        1.2     2010-02-20 13:24:00.000
</pre>
<p>Each of these queries can therefore be made into inline views, and these can then be joined on the rownum column.  This will join together records in the first result set with the next record on in the second.  (If I was happy to use a common table expression I wouldn&#8217;t need to take this second step, I could have declared a CTE from the first query and used it twice.)</p>
<pre>
SELECT exchange_rate1.rate
,      exchange_rate1.effective_date AS effective_date_from
,      exchange_rate2.effective_date AS effective_date_to
FROM
  (  SELECT ROW_NUMBER() OVER (ORDER BY effective_date) rownum, rate, effective_date
     FROM exchange_rate) exchange_rate1
LEFT OUTER JOIN (SELECT (ROW_NUMBER() OVER (ORDER BY effective_date))-1 rownum, rate, effective_date
                 FROM   exchange_rate ) exchange_rate2
ON (exchange_rate1.rownum = exchange_rate2.rownum)

rate   effective_date_from     effective_date_to
------ ----------------------- -----------------------
1.09   2010-01-01 00:00:00.000 2010-02-17 11:14:00.000
1.12   2010-02-17 11:14:00.000 2010-02-20 13:24:00.000
1.2    2010-02-20 13:24:00.000 NULL
</pre>
<p>This is now pretty close to what we want.  I just need to handle trades made since the last exchange_rate became effective &#8211; i.e the NULL that appears at the end of my result set.  There are a couple of ways to do it, but for simplicity I will just use ISNULL to replace the null with any future date.  Any future date is fine, as no future trades are likely to be recorded in my stock_sales table.</p>
<pre>
SELECT exchange_rate1.rate
,      exchange_rate1.effective_date AS effective_date_from
,      ISNULL(exchange_rate2.effective_date, DATEADD(day, 1, getDate())) effective_date_to
FROM
  (  SELECT ROW_NUMBER() OVER (ORDER BY effective_date) rownum, rate, effective_date
     FROM exchange_rate) exchange_rate1
LEFT OUTER JOIN (SELECT (ROW_NUMBER() OVER (ORDER BY effective_date))-1 rownum, rate, DATEADD(millisecond, -1, effective_date) effective_date
                 FROM   exchange_rate ) exchange_rate2
ON (exchange_rate1.rownum = exchange_rate2.rownum)

rate   effective_date_from     effective_date_to
------ ----------------------- -----------------------
1.09   2010-01-01 00:00:00.000 2010-02-17 11:14:00.000
1.12   2010-02-17 11:14:00.000 2010-02-20 13:24:00.000
1.2    2010-02-20 13:24:00.000 2010-02-26 15:38:29.493
</pre>
<p>Having got my data in to the format I was looking for, I can now join in my stock_sales table using a standard non-equijoin:</p>
<pre>
SELECT amount_sold, date_sold, rate FROM stock_sales
INNER JOIN
	(SELECT exchange_rate1.rate
	 ,      exchange_rate1.effective_date AS effective_date_from
	 ,      ISNULL(exchange_rate2.effective_date, DATEADD(minute, 1, getDate())) effective_date_to
	 FROM
	   (  SELECT ROW_NUMBER() OVER (ORDER BY effective_date) rownum, rate, effective_date
 		 FROM exchange_rate) exchange_rate1
 	 LEFT OUTER JOIN (SELECT (ROW_NUMBER() OVER (ORDER BY effective_date))-1 rownum, rate, DATEADD(millisecond, -1, effective_date) effective_date
					 FROM   exchange_rate ) exchange_rate2
	 ON (exchange_rate1.rownum = exchange_rate2.rownum)
	 ) exchange_rates_range
ON (stock_sales.date_sold &gt;= exchange_rates_range.effective_date_from AND stock_sales.date_sold &lt; exchange_rates_range.effective_date_to)

amount_sold date_sold               rate
----------- ----------------------- ----------------------
1700        2010-02-15 00:59:49.190 1.09
1900        2010-02-16 05:47:49.203 1.09
1400        2010-02-24 20:11:45.873 1.2
</pre>
<p><strong>Conclusion</strong></p>
<p>This was a nice little problem, and one which I&#8217;m sure will have many practical uses.  I would be interested in hearing anyone else&#8217;s alternative ways to solve it.</p>
<p>&nbsp;</p>
<p><strong>About the poster</strong></p>
<p><img src="http://www.impartica-training.co.uk/images/deanbullen.jpg" alt="Dean Bullen" /></p>
<p><em>Dean Bullen is Impartica’s SQL course leader and has been working with SQL since 1998. He previously worked for Oracle and has been working with SQL Server since 2006.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.impartica-training.co.uk/?feed=rss2&amp;p=91</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Q &amp; A with RubyOnRails Developer Kris Leech</title>
		<link>http://blog.impartica-training.co.uk/?p=76</link>
		<comments>http://blog.impartica-training.co.uk/?p=76#comments</comments>
		<pubDate>Tue, 19 Jan 2010 14:18:10 +0000</pubDate>
		<dc:creator>impartica</dc:creator>
				<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[ruby rubyonrails rails ror]]></category>

		<guid isPermaLink="false">http://blog.impartica-training.co.uk/?p=76</guid>
		<description><![CDATA[In the latest installment of our trainer&#8217;s blog we interview Kris Leech of Interkonect, who has written and will deliver our new Ruby programming and Ruby on Rails courses.

Can you give a potted history of your coding career?
1987
I started programming BASIC on an BBC Acorn Electron. Something like:
10 print "Kris is Cool "
20 goto 10
1989-1993
After [...]]]></description>
			<content:encoded><![CDATA[<h3>In the latest installment of our trainer&rsquo;s blog we interview Kris Leech of <a href="http://interkonect.com/" target="_blank">Interkonect</a>, who has written and will deliver our new <a href="http://www.impartica-training.co.uk/courses/ruby-programming.aspx" target="_blank">Ruby programming</a> and <a href="http://www.impartica-training.co.uk/courses/ruby-on-rails.aspx" target="_blank">Ruby on Rails</a> courses.<br />
</h3>
<h3>Can you give a potted history of your coding career?</h3>
<p><em>1987</em></p>
<p>I started programming BASIC on an BBC Acorn Electron. Something like:</p>
<p><code>10 print "Kris is Cool "<br />
20 goto 10</code></p>
<p><em>1989-1993</em></p>
<p>After this I remember getting a Commadore 64 and later an Amiga 500 although to be honest I mostly played games until I got an PC (486 with a Turbo button!) running MS-DOS. I picked up BASIC again, this time Microsoft&#8217;s QBasic. This was my first exposure to a debugger and the game Gorillas.</p>
<p><em>1995</em></p>
<p>Shortly after the move from DOS to Windows PC&#8217;s became more affordable and appeared in libraries, cafes and schools. I briefly dabbled with C before being introduced to Borland Delphi (Object Pascal) version 4. This was my first exposure to an Object Orientated language. Shortly afterwards I got some work programming desktop applications before finishing my A-Levels in 1998.</p>
<p><em>2000</em></p>
<p>Within the next few years the Internet became more affordable and I started developing simple static websites using Macromedia Dreamweaver and Fireworks for local businesses.</p>
<p>My natural progression was to pick up PHP and start developing dynamic websites. I did this for many years of web development using PHP like many people blissfully unaware of HTML/CSS standards and best practices in web development. By necessity I also started to get involved in Linux server administration such as installing packages and configuring Apache.</p>
<p><em>2004</em></p>
<p>It was only much later that blogs started to become popular due to open source projects such as WordPress and posts on separation of data (HTML), presentation (CSS) and behaviour (Javascript) caught my eye and a light bulb was illuminated.</p>
<p>This somehow led me to my most exciting discovery to date, the RubyOnRails framework.</p>
<p>I think the first exposure to RubyOnRails was a short video of pre-release Rails where someone, presumably David Heinemeier Hansson, generated a scaffold application which talked to the database and generated HTML allowing you to create, edit and delete records. Pretty basic functionality but what was impressive was it only took a few minutes to complete.</p>
<p>So now I&#8217;ve been working with Rails for around 5 years and have no doubts I made the right choice. </p>
<h3>What was it about RubyOnRails that appealed you?</h3>
<p>At the time I mostly hashed together PHP code, HTML and SQL with no real structure. The most abstraction I managed was putting the database connection code in a separate file. I was not aware of a better way to manage my code base so larger projects quickly became unmanageable. This was not a consequence of using PHP but of the standard practice within the PHP community. Because code was being developed in a ad-hoc manner it made working as part of a team near impossible as each developer had their own way of doing things, there were no conventions and no coding standards. This didn&#8217;t make very good business sense. Projects were costly in terms of time and estimation was difficult in the first place. This uncertainty never inspired much confidence from prospective clients. Because one person held the knowledge needed to fully understand the code base development needed to stop to get a new developer up to speed. Not only that a completely new team could not inherit the project months or years later when the original developer may have moved on. </p>
<p>RubyOnRails changed this, it is a framework. A solid foundation on which to build. Everything has its place. It is modular and works out of the box. I could pick up a Rails application, even a complex one, written by someone else and completely understand it without any supporting documentation in a relatively short amount of time.</p>
<p>Rails abstracts away all the mundane, repetitive jobs that are common to building web applications. This really appeals because not only is coding more enjoyable but you are much more productive. You could get something up and running really quickly. It allows you to concentrate on the unique and challenging aspects of a website. I can show my client a working prototype in a few days instead of a few weeks and respond to change early on in the project.</p>
<p>This was also my first exposure to the highly expressive Ruby language in which Rails is written.</p>
<h3>Has selling Ruby/Rails to clients been difficult?</h3>
<p>Businesses don&#8217;t tend to be interested in which technology you use to develop their website, they are more sensitive about budget. Using Rails enables you to outperform your competitors in terms of time/budget and bonds well with the values of Agile project management techniques such as delivering working software early and often, not only responding to changes in requirements but embracing them. It is the features of Rails which bring these benefits.</p>
<p>Also I&#8217;ve done a lot of sub-contractor work for web design companies. They tend to favour PHP based solutions because there is an abundance of PHP programmers. The market is saturated especially when you consider outsourcing overseas. Of course as mentioned earlier this can be a bit of a false economy for any sizeable project if you become restricted to one developer &#8216;teams&#8217;.</p>
<p>One of the web design companies I was working for had hired me to develop an &#8216;energy analysis&#8217; application for a large aggregates company. We started using PHP and in the second year the code base started to take on a lot of technical debt due to convoluted hacks and bodge jobs which were employed to keep costs down. I had recently discovered Rails and had produced a few basic applications. I introduced the idea of using Rails but it was rejected and we continued on until three months later when I really could not go on. That week I rewrote the entire application in just a couple of weeks in Rails. We never looked back. From then on development proceeded at a much quicker pace and I could answer &#8216;yes&#8217; to new features without having to worry about the code becoming unmaintainable.</p>
<h3>What was the most difficult aspect of learning Rails?</h3>
<p>At first I used Rails without really learning Ruby, the language in which it is written. In the beginning this wasn&#8217;t really a problem because Rails allows you to get up and running straight away with some simple configuration. But once you move past this point of using Rails as is and wanting to do some more advanced stuff that&#8217;s when you need to learn the Ruby language and become familiar with some of the objects in the core and standard libraries.</p>
<p>Ruby also has some features which are unique, such as blocks, which don&#8217;t seem to have a parallel in other languages.</p>
<p>Reading other peoples code was maybe the fastest way I leap frogged my understanding not only of Ruby but the &#8220;Ruby Way&#8221;. It&#8217;s hard to put your finger on exactly what the &#8220;Ruby Way&#8221; is. It&#8217;s kind of a collective best practice as defined by the community which you pick up over time.</p>
<h3>Aside from Ruby and Rails what other software have you been excited about recently?</h3>
<p>Definitely &#8216;Git&#8217;. It&#8217;s a distributed version control system which has become popular in the Rails community. It allows you to manage your source code individually or as part of a distributed team. Git is an open source project and was started by Linus Torvalds to manage the Linux Kernel code base.</p>
<h3>What kind of projects have you been working on with Rails?</h3>
<p>All the websites I code are now written in Rails. We recently delivered the Information Prescriptions project, which is an NHS funded knowledge base covering a wide range of health conditions such as Neurological, Long Term, Heart, Lung and Breathing Conditions. All information is categorised using demographics such as age, gender, and location. The project has been running over 2 years now and we are continually evolving the website to better meet the needs of the people using the site.</p>
<p>Last year we delivered a project, &#8216;Evolve&#8217;, for Nottingham Trent University which allowed students to be matched with charities looking for particular skill sets. It incorporated a lot of Social Media like features such as profiles, messaging, personal blogs and the ability for people to form groups with complementary skills.</p>
<p>Aside from this we have developed a variety of websites in the usual categories such as Online Learning, Customer Management, loads of Content Management Systems, E-commerce Solutions and Web Services.</p>
<p>I have also released a few open source projects for Ruby/Rails. I have written a series of automated tasks to help transparently incorporate non-technical graphic designer&#8217;s work in to our central code repository. This gives us a history of changes to HTML templates, images, CSS and Javascript files. This allows them to work with tools they are used to such as Dreamweaver and FTP. There are also a few experimental ideas on there including a Ruby chat server which keeps a HTTP connection to the browser open permanently allowing the server to push real time data to the browser.</p>
<h3>Difficulty of deployment and scaling have been cited as failings of Rails, whats your take?</h3>
<p>I think deployment was an issue in the very early days when the only option was to use FastCGI which was typically a pain to setup and far from reliable. Now days however we have a wealth of deployment options including standalone servers for Rails, an Apache module which allows you to just upload your code (ala PHP) and thanks to the JRuby project interfaces to Java Application Servers such as JBoss if you need to deploy in a Java only environment.</p>
<p>We also have a number of deployment automation tools which allow us to setup and deploy applications in seconds without having to even log in to the server(s).</p>
<p>The beauty of these tools is that you can start off with a super simple light weight setup and scale up at a later date if required. You can even have your application scale automatically up/down on demand if you are deploying to the cloud such as EC2.</p>
<p>It&#8217;s out of the scope of Rails itself but if you are managing your own server we also have tools such as Deprec and Chef which will provision a vanilla Linux server which an entire Rails stack including the database and web server.</p>
<h3>Can you give some examples of high profile websites which are written in Rails?</h3>
<p>Everybody&#8217;s heard of Twitter, right?</p>
<p>Yell, Scribd and Hulu are other examples of very high traffic sites. There are literally tens of thousands of sites out there both big and small which use Rails.</p>
<h3>Twitter is known to have had issues scaling and this seems to have reflected badly on Rails&#8230;</h3>
<p>To be honest scaling has never been an issue for websites written in Rails, since it scales in the same way as every other website, at the HTTP level. If you are lucky enough to attract enough traffic you start by caching as much as possible, optimising database calls and maybe moving your database on to a separate server. This is all configurable in Rails and standard practice for any website regardless of the technology.</p>
<p>The bottle neck for many high traffic websites is nearly always at the database tier. This was particularly pronounced for Twitter because it accepts real time content from any of its millions of users, peaking at 300 &#8216;tweets&#8217; per second. I believe Twitter now keeps a lot of their data in memory and they wrote their own data storage to handle their unique case.</p>
<h3>You are presenting the Ruby and a Rails courses for ourselves can give us an idea of what delegates will take away with them?</h3>
<p>The courses can be taken individually however they run over consecutive days and are designed to complement each other. I have condensed years of experience into a few days so it&#8217;s pretty action packed. I&#8217;d like to inspire developers and show them things that will make them think &#8216;wow&#8217;. It&#8217;s important that delegates to go away with a practical and working knowledge so we use live coding sessions, participatory discussion and practical examples to collectively explore Ruby and Rails.</p>
<p>The 2 day Ruby course will be an introduction to many of the unique aspects of Ruby which make it really stand out as a general purpose language. It will not be Rails specific.</p>
<p>We will investigate the Ruby language, its object model and how to write solid object orientated code and tools such as package management, automated build tools and documentation which come packaged with Ruby things that really simplifies life as a developer.</p>
<p>We will go on to look at the &#8216;magical&#8217; side of Ruby which allows the Rails framework and many of plugins and libraries to be as concise as they are. This will include a look at advanced topics such as meta-programming, DSL&#8217;s and code evaluation.</p>
<p>The Rails course which is spread over 3 days will start from the premise of never having used Rails before and we cover a lot of ground.</p>
<p>In the first day we will look at each of the core modules which make up Rails and how they are wired together allowing you to easily manage your data, render HTML and send emails. By developing a working application together I hope to demonstrate practical tips and techniques which I have accumulated over many years.</p>
<p>The second day will start with a focus on logins, permissions, security concerns and how these are handled in Rails. This will be followed up with a look at advanced concepts within each of the core modules.</p>
<p>The third day will looks at deployment options, debugging and optimisation, writing your own plugins and alternatives to the default Rails core modules.</p>
<h3>Finally, where do you see the future for Rails?</h3>
<p>Now a lot of initial hype has died down and we are seeing large projects being deployed in Rails with substantial user traffic which are scaling well it has silenced a lot of the unfounded doubt people might have had.</p>
<p>We are seeing healthy competition in the plugin arena in categories such as file upload, XML parsing, authorisation, authentication and the like. There is an abundance of high end well documented plugins.</p>
<p>Ruby 1.9 is just around the corner which looking at the benchmarks will give some great speed improvements. The Rails core team are working hard on gaining compatibility.</p>
<p>I don&#8217;t think the true potential of JRuby has been realised yet. JRuby is an alternative to the standard Ruby interpreter which allows you to run Ruby code on the JVM (Java Virtual Machine) and provides a two way communication between Ruby and Java. Allowing any Java library to be used from within Ruby. This includes as mentioned earlier running a Rails app inside something like Glassfish or JBoss.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.impartica-training.co.uk/?feed=rss2&amp;p=76</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducing Dr Chris Brown</title>
		<link>http://blog.impartica-training.co.uk/?p=48</link>
		<comments>http://blog.impartica-training.co.uk/?p=48#comments</comments>
		<pubDate>Tue, 08 Dec 2009 11:11:54 +0000</pubDate>
		<dc:creator>impartica</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Operating systems]]></category>

		<guid isPermaLink="false">http://impartica-training.co.uk/wordpress/?p=48</guid>
		<description><![CDATA[This week we launched our brand new course: Linux: A Comprehensive Introduction.  This new course has been written by the respected Linux author and columnist Dr. Chris Brown, who will also deliver the course.  Here we take a brief look at Chris&#8217; career so far.

Dr. Chris Brown has been using UNIX as a [...]]]></description>
			<content:encoded><![CDATA[<p><em>This week we launched our brand new course: <a href="http://impartica-training.co.uk/courses/linux-a-comprehensive-introduction.aspx">Linux: A Comprehensive Introduction</a>.  This new course has been written by the respected Linux author and columnist Dr. Chris Brown, who will also deliver the course.  Here we take a brief look at Chris&#8217; career so far.</em></p>
<p><img src="http://impartica-training.co.uk/wordpress/wp-content/uploads/2009/12/cbrown1.PNG" style="float:right; padding:10px;" height="230px" width="172px" alt="Chris Brown" /></p>
<p>Dr. Chris Brown has been using UNIX as a software developer and system administrator since its pioneering days over 30 years ago, and has used Linux professionally and at home for about 10 years. He has extensive experience in curriculum design, and in addition to Linux training he has written hands-on courses in UNIX/Linux system programming, network programming, PHP, and distributed computing, and has edited and provided instructional design support for many others.</p>
<p>In addition to his time as a Research Fellow at Sheffield University, Chris has had a “proper job” as a Product Manager for the training company Learning Tree International, which saw him living and working in Virginia, USA for a while.</p>
<p>Dr. Brown has taught UNIX and Linux extensively for more than 20 years, mostly in Europe and the USA but also in Canada, India, Hong Kong and Brazil. He provided in-depth technical training on SUSE Linux to Novell’s consultants and IT engineers.  He developed training content for Canonical’s “Ubuntu Certified Professional” training and wrote their “Deploying Ubuntu Server” course, and was master trainer for their train-the-trainer program. </p>
<p>He is author of the book “UNIX Distributed Programming” published by Prentice Hall, and of “SUSE Linux” published by O’Reilly. He also writes a regular column for the UK magazine “Linux Format”. </p>
<p>He is an ardent supporter of Linux and the Open Source movement and brings an enthusiasm, experience, depth of knowledge, and humour to the classroom to make for an effective and enjoyable learning experience.</p>
<p>Chris holds a BA in theoretical physics, an MA, and a Ph.D. in particle physics, all from Cambridge University. He also has RedHat RHCE, Novell NCLP and Ubuntu UCP qualifications and is a Ubuntu<br />
Certified Instructor.</p>
<p><strong>Links</strong></p>
<ul>
<li>Chris Brown on <a href="http://www.amazon.com/Chris-Brown/e/B001IQUM94/ref=ntt_athr_dp_pel_pop_1" target="_blank">Amazon.com</a></li>
<li>Read Chris&#8217; column on <a href="http://www.linuxformat.com/" target="_blank">Linux Format</a></li>
<li>Book on <a href="http://impartica-training.co.uk/courses/linux-a-comprehensive-introduction.aspx" target="_blank">Linux: A Comprehensive Introduction</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.impartica-training.co.uk/?feed=rss2&amp;p=48</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Server 2008 row constructors</title>
		<link>http://blog.impartica-training.co.uk/?p=3</link>
		<comments>http://blog.impartica-training.co.uk/?p=3#comments</comments>
		<pubDate>Mon, 18 May 2009 10:14:26 +0000</pubDate>
		<dc:creator>dbullen</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Microsoft SQL Server]]></category>

		<guid isPermaLink="false">http://impartica-training.co.uk/wordpress/?p=3</guid>
		<description><![CDATA[In today&#8217;s blog I&#8217;m going to look at a new feature in SQL Server 2008 which, while it doesn&#8217;t provide any functionality not previously possible, it certainly makes a couple of jobs much easier. Some people are calling this feature row constructors. It has basically two uses.
Firstly, you can insert more than one row into [...]]]></description>
			<content:encoded><![CDATA[<p>In today&#8217;s blog I&#8217;m going to look at a new feature in SQL Server 2008 which, while it doesn&#8217;t provide any functionality not previously possible, it certainly makes a couple of jobs much easier. Some people are calling this feature <strong>row constructors</strong>. It has basically two uses.</p>
<p>Firstly, you can insert more than one row into a table using a single INSERT statement. Here is the syntax:</p>
<p><code>INSERT INTO monthly_sales (office_id, sales_year, sales_month, sales_value)<br />
VALUES (42, '2009', '01', 324877)<br />
, (42, '2009', '02', 329483)<br />
, (42, '2009', '03', 381002)<br />
, (89, '2009', '01', 50228)<br />
, (89, '2009', '02', 49763)<br />
, (89, '2009', '03', 49883)</code></p>
<p>Quite a neat addition, certainly very readable. Of more practical use possibly, the six rows to be inserted now either stand or fall together: if any of the value sets contain invalid data, the whole statement will fail and no rows will be inserted. In situations where this behaviour is desirable, this single statement can replace a potentially complex T-SQL block. (But of course beware that in some cases, you may NOT want each row to rely on others, and this could end up being a curse rather than a blessing).</p>
<p>The second use for row constructors is in formulating an on-the-fly virtual table, of the type you may previously have used a SELECT/UNION combination for.</p>
<p>Consider the following requirement. Using values from the table above, show the monthly sales for office 42 for every month in 2009. Since we only have data for the first three months, we will have to join the table to one we create on the fly. The following statement would probably be the best fit in previous versions of SQL Server:</p>
<p><code>SELECT ilv.month_name, ISNULL(ms.sales_value, 0) AS sales_value<br />
FROM monthly_sales AS ms<br />
RIGHT OUTER JOIN<br />
( SELECT '01' AS month_name<br />
UNION<br />
SELECT '02' AS month_name<br />
UNION<br />
SELECT '03' AS month_name<br />
UNION<br />
SELECT '04' AS month_name<br />
UNION<br />
SELECT '05' AS month_name<br />
UNION<br />
SELECT '06' AS month_name<br />
UNION<br />
SELECT '07' AS month_name<br />
UNION<br />
SELECT '08' AS month_name<br />
UNION<br />
SELECT '09' AS month_name<br />
UNION<br />
SELECT '10' AS month_name<br />
UNION<br />
SELECT '11' AS month_name<br />
UNION<br />
SELECT '12' AS month_name) AS ilv ON (ilv.month_name = ms.sales_month AND ms.office_id = 42 AND ms.sales_year = '2009')<br />
ORDER BY 1</code></p>
<p>Results:</p>
<p><code>01 324877<br />
02 329483<br />
03 381002<br />
04 0<br />
05 0<br />
06 0<br />
07 0<br />
08 0<br />
09 0<br />
10 0<br />
11 0<br />
12 0</code></p>
<p>However the row constructor allows us to use a neater syntax to build up the inline view. Try this:</p>
<p><code>SELECT * FROM (VALUES ('01'),('02'),('03'),('04'),('05'),('06'),('07'),('08'),('09'),('10'),('11'),('12')) AS ilv (month_name)</code></p>
<p>You will see it gives us the same result as the sequence of SELECTs and UNIONs in the main query, i.e. a single column, 12 row table, called ilv, with the column name of month_name. We can then join this into our monthly_sales table as follows:</p>
<p><code>SELECT ilv.month_name, ISNULL(ms.sales_value, 0) AS sales_value<br />
FROM monthly_sales AS ms<br />
RIGHT OUTER JOIN<br />
( VALUES ('01'),('02'),('03'),('04'),('05'),('06'),('07'),('08'),('09'),('10'),('11'),('12')) AS ilv (month_name)<br />
ON (ilv.month_name = ms.sales_month AND ms.office_id = 42 AND ms.sales_year = '2009')<br />
ORDER BY 1</code></p>
<p>Results:</p>
<p><code>01 324877<br />
02 329483<br />
03 381002<br />
04 0<br />
05 0<br />
06 0<br />
07 0<br />
08 0<br />
09 0<br />
10 0<br />
11 0<br />
12 0</code></p>
<p>You are not restricted to one column, that&#8217;s just the example I chose to use.</p>
<p>Although it probably won&#8217;t make a major difference to your SQL life, keep row constructors in mind when working on SQL Server 2008.</p>
<p><strong>About the poster</strong></p>
<p><img src="http://www.impartica-training.co.uk/images/deanbullen.jpg" alt="Dean Bullen" /></p>
<p><em>Dean Bullen is Impartica’s SQL course leader and has been working with SQL since 1998. He previously worked for Oracle and has been working with SQL Server since 2006.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.impartica-training.co.uk/?feed=rss2&amp;p=3</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flashback!</title>
		<link>http://blog.impartica-training.co.uk/?p=12</link>
		<comments>http://blog.impartica-training.co.uk/?p=12#comments</comments>
		<pubDate>Mon, 20 Apr 2009 04:04:10 +0000</pubDate>
		<dc:creator>dbullen</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://impartica-training.co.uk/wordpress/?p=12</guid>
		<description><![CDATA[Welcome to the first offering from Impartica’s trainers’ blog. The mandate here is to introduce you to an advanced or product specific feature that we don’t get time to cover in the courses. In this first posting I’m going to look at a feature of SQL that’s specific to recent versions of Oracle RDBMS, and [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to the first offering from Impartica’s trainers’ blog. The mandate here is to introduce you to an advanced or product specific feature that we don’t get time to cover in the courses. In this first posting I’m going to look at a feature of SQL that’s specific to recent versions of Oracle RDBMS, and it comes under the heading of Flashback SQL.</p>
<p>Not only does this have a cool name, it’s actually a cool feature.</p>
<p>Flashback was originally introduced in Oracle 9<i>i</i>, and improved in 10<i>g</i>. The feature I’m going to demonstrate today – the SELECT .. AS OF TIMESTAMP clause – is available in Oracle 10<i>g</i> Release 2 and higher.</p>
<p>Flashback allows you to view a table as it was at a previous point in time. Easily. Really easily, actually.</p>
<p>Rather than explain that any further I’ll show you the SQL and let you see for yourself. If you’ve never seen this feature before, I predict you’ll be impressed!</p>
<p>First I’ll set up my test table and data:</p>
<p><code>CREATE TABLE staff (full_name VARCHAR(20));<br/>INSERT INTO staff (full_name) VALUES ('Susan Smith');<br/>INSERT INTO staff (full_name) VALUES ('Harry Tomlinson');<br/>INSERT INTO staff (full_name) VALUES ('Stuart Haines');<br/>COMMIT; </code><br />
<br />
<code>SELECT * FROM staff;</code><br />
<br />
<code>FULL_NAME<br/>--------------------<br/>Susan Smith<br/>Harry Tomlinson<br/>Stuart Haines<br/></code></p>
<p>Okay, nothing new so far. But what we’re going to do now is to change the data, commit the changes, but use Flashback SQL to go back and see the data as it is now.</p>
<p>To do this we’re going to use a timestamp, so let’s just capture the current timestamp:</p>
<p><code>SELECT SYSTIMESTAMP FROM DUAL;</code><br />
<br />
<code>SYSTIMESTAMP<br/>-----------------------------------------------<br/>18-APR-09 10.37.31.765000 +01:00</code></p>
<p>Now we’ll change the data and commit the changes:</p>
<p><code>UPDATE staff SET full_name = 'Susan Brown' WHERE full_name = 'Susan Smith';<br/>DELETE FROM staff WHERE full_name = 'Stuart Haines';<br/>UPDATE staff SET full_name = UPPER(full_name);<br/>COMMIT;</code><br />
<br />
<code>SELECT * FROM staff;</code><br />
<br />
<code>FULL_NAME<br/>--------------------<br/>SUSAN BROWN <br/>HARRY TOMLINSON</code></p>
<p>So we’ve changed and committed the data. Now let’s test my claim. I said that Flashback would let us see the data as it was at a previous point in time, and that it would be really easy to do. So let’s try to get a view of the data as it was a few minutes ago, before we made those three changes.</p>
<p>It’s as simple as this:</p>
<p><code>SELECT * FROM staff AS OF TIMESTAMP TO_TIMESTAMP('18-APR-2009 10:37:31AM', 'DD-MON-YYYY HH:MI:SSAM');</code><br />
<br />
<code>FULL_NAME<br/>--------------------<br/>Susan Smith<br/>Harry Tomlinson<br/>Stuart Haines<br/></code></p>
<p>So, all we’ve done is added ‘AS OF TIMESTAMP…’ to our SELECT statement, then used the TO_TIMESTAMP function to specify the time we want to ‘flash back’ to – the timestamp we retrieved just before we made the changes.</p>
<p>Those of you who grew up on earlier versions of Oracle, like me, or with other RDBMSs, I think will be impressed. The simplicity in particular makes it a really useful addition – no set-up needed, it’s right out of the box. </p>
<p>This feature is primarily designed for ‘undo’ functionality, allowing you to check or roll back unintended transactions. But you can probably think of production scenarios where you’d want to use it. You can create views based on Flashback SQL. Performance may not be particularly geared towards that type of usage though – check the documentation for the version of Oracle you are using and speak to your DBA about whether it makes sense to use it.</p>
<p>This is just one small feature of Oracle’s Flashback technology, there are other things you can do in the various RDBMS versions since Oracle 9<i>i</i>. Instead of the TIMESTAMP option you can specify the System Change Number (SCN) – an internal number Oracle uses to keep track of changes. Instead of using the AS OF clause on each SQL statement you can temporarily flash back a table – or even a whole database &#8211; to a point in time for the rest of the session. You can drop a table, and then flash it back to before the drop.</p>
<p>Hopefully this post has given you a flavour of what’s possible and will maybe encourage you to go and research it more yourself.</p>
<p><strong>About the poster</strong></p>
<p><img src="http://www.impartica-training.co.uk/images/deanbullen.jpg" alt="Dean Bullen" /></p>
<p><em>Dean Bullen is Impartica’s SQL course leader and has been working with SQL since 1998. He previously worked for Oracle and has been working with SQL Server since 2006.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.impartica-training.co.uk/?feed=rss2&amp;p=12</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
