<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8832291873344926372</id><updated>2012-05-21T12:05:35.594-07:00</updated><category term='elevate-db'/><category term='delphi-nugget'/><category term='date-stuff'/><category term='sql-nugget'/><category term='stored-procedure'/><category term='report-builder'/><category term='survery'/><category term='musings'/><title type='text'>Cape Cod Gunny Does Delphi</title><subtitle type='html'>The trials, tribulations, tips, snares and thougts of a Delphi Programmer running a one person Micro ISV who happens to be a retired USMC Gunnery Sergeant.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>23</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-6653238536066380744</id><published>2012-05-13T12:17:00.000-07:00</published><updated>2012-05-13T12:41:50.623-07:00</updated><title type='text'>Plan Ahead When It Comes To FireMonkey &amp; iOS</title><content type='html'>I don't intend to move to XE2 or XE(next) anytime soon, I have my hands full just porting over my old applications from D5 to D2010. However, I would like to take advantage of FireMonkey and the iOS market when the time is right so I'm planning ahead and so can you.&lt;br /&gt;&lt;br /&gt;I am currently working on adding Inifile support to my application to keep track of window sizes and position.&amp;nbsp;I asked on &lt;a href="http://stackoverflow.com/questions/10564505/" target="_blank"&gt;StackOverflow&lt;/a&gt; if &lt;em&gt;&lt;strong&gt;FireMonkey has anything similar to GetSystemMetrics&lt;/strong&gt;&lt;/em&gt;. &lt;a href="http://stackoverflow.com/users/596852/whiler" target="_blank"&gt;Whiler&lt;/a&gt; posted a snice snippet of code that uses FX.Platform. (Merci Beaucoup Whiler)&lt;br /&gt;&lt;br /&gt;My first thought was it's too bad I can't use this piece of code today. Then I had one of those aha moments. I thought to myself, &lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;strong&gt;&lt;em&gt;"Why not add this as a comment in your Delphi code." &lt;/em&gt;&lt;/strong&gt;&lt;/blockquote&gt;So that's what I did.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #999999;"&gt;Begin Code Snippet &lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #38761d;"&gt;{&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;FireMonkey Consideration:&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;Question asked on stackoverflow:&lt;br /&gt;http://stackoverflow.com/questions/10564505&lt;br /&gt;I'm rewriting an old application using Delphi 2010 and I'd like&lt;br /&gt;to put placeholders in my code for when I port it over to XE2.&lt;br /&gt;Just curious if FireMonkey has an equivilent to GetSystemMetrics.&lt;br /&gt;I'm specifically interested in:&lt;br /&gt;&lt;br /&gt;GetSystemMetrics(SM_CXSCREEN)&lt;br /&gt;GetSystemMetrics(SM_CYSCREEN)&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;If you just need the main monitor size, and not the desktop size&lt;br /&gt;(n monitors sum), you can use this:&lt;br /&gt;&lt;br /&gt;uses ..., FMX.Platform;&lt;br /&gt;&lt;br /&gt;var   p: TPointF;&lt;br /&gt;begin&lt;br /&gt;  p := Platform.GetScreenSize;&lt;br /&gt;  ShowMessage(Format('X: %f' + LineFeed + 'Y: %f', [p.X, p.Y]));&lt;br /&gt;&lt;br /&gt;From: Whiler&lt;br /&gt;http://blogs.wittwer.fr/whiler/&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;strong&gt;&lt;span style="color: blue;"&gt;unit&lt;/span&gt;&lt;/strong&gt; IniFileStuff;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="color: blue;"&gt;interface&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;&lt;strong&gt;uses&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;  Windows, SysUtils, Forms, IniFiles;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="color: blue;"&gt;type&lt;/span&gt;&lt;br /&gt;&lt;/strong&gt;  TScreenType  = (MainScreen, PreviewScreen);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;&lt;strong&gt;Procedure&lt;/strong&gt;&lt;/span&gt; InitializeIniFile();&lt;br /&gt;&lt;strong&gt;&lt;span style="color: blue;"&gt;Procedure&lt;/span&gt;&lt;/strong&gt; ResetScreenSection(ScreenType:TScreenType);&lt;br /&gt;&lt;strong&gt;&lt;span style="color: blue;"&gt;Function&lt;/span&gt;&lt;/strong&gt; WindowStateToInt(WSType:TWindowState):integer;&lt;br /&gt;&lt;strong&gt;&lt;span style="color: blue;"&gt;Function&lt;/span&gt;&lt;/strong&gt; IntToWindowState(WSInt:integer):TWindowState;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: #999999;"&gt;End Code Snippet &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So, even though I'm not using FireMonkey today, I've documented my code so when I do go to use FireMonkey I'll have a decent head start.&lt;br /&gt;&lt;br /&gt;Don't keep it - Pass it on.&lt;br /&gt;Semper Fi - Gunny Mike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-6653238536066380744?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/6653238536066380744/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/plan-ahead-when-it-comes-to-firemonkey.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/6653238536066380744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/6653238536066380744'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/plan-ahead-when-it-comes-to-firemonkey.html' title='Plan Ahead When It Comes To FireMonkey &amp; iOS'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-713645639566714079</id><published>2012-05-09T20:15:00.000-07:00</published><updated>2012-05-13T10:27:05.081-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='delphi-nugget'/><title type='text'>Keeping Screen Resolution in Mind</title><content type='html'>I'm redoing an old Delph 5 app that forced a screen resolution of 640 x 480 on the users. At the time this application was deveopled that screen resolution was acceptable but not anymore. Todays endless arrays of screen resolutions brings on new challenges. One of the things I plan on doing at application start is interrogate the current screen resolution and set my application screen size to a ratio of 80%.&lt;br /&gt;&lt;br /&gt;I'm amazed at how much information is available. Here is a nice graph that shows the top 10 screen resolutions in use from 2008 through 2012.&lt;br /&gt;&lt;br /&gt;&lt;div height="400" id="resolution-ww-yearly-2008-2012-bar" style="height: 400px; width: 600px;" width="600"&gt;&lt;/div&gt;Source: &lt;a href="http://gs.statcounter.com/#resolution-ww-yearly-2008-2012-bar"&gt;StatCounter Global Stats - Screen Resolution Market Share&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;script src="http://www.statcounter.com/js/FusionCharts.js" type="text/javascript"&gt;&lt;/script&gt;&lt;script src="http://gs.statcounter.com/chart.php?resolution-ww-yearly-2008-2012-bar" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;Add&lt;span style="background-color: #eeeeee; color: black;"&gt; &lt;strong&gt;MultiMon&lt;/strong&gt; &lt;/span&gt;to the uses clause The button click event lets you move the program between two monitors to get the screen resolution. &lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="background-color: #eeeeee;"&gt;procedure TScreenResolution.Button1Click(Sender: TObject);&lt;br /&gt;var&lt;br /&gt;  MonInfo: TMonitorInfo;&lt;br /&gt;  ScreenW, ScreenH : integer;&lt;br /&gt;begin&lt;br /&gt;  MonInfo.cbSize := SizeOf(MonInfo);&lt;br /&gt;  GetMonitorInfo(MonitorFromWindow(Handle, MONITOR_DEFAULTTONEAREST), @MonInfo);&lt;br /&gt;  ScreenW :=  MonInfo.rcMonitor.Right  - MonInfo.rcMonitor.Left;&lt;br /&gt;  ScreenH :=  MonInfo.rcMonitor.Bottom - MonInfo.rcMonitor.Top;&lt;br /&gt;  Label2.Caption := IntToStr(ScreenW);&lt;br /&gt;  Label4.Caption := IntToStr(ScreenH);&lt;br /&gt;end;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Semper Fi - Gunny Mike&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;FireMonkey Update - 05/13/2012:&lt;/h4&gt;I'd like to thank &lt;a href="http://stackoverflow.com/users/596852/whiler" target="_blank"&gt;Whiler&lt;/a&gt; from StackOverflow for a FireMonkey example using FX.Platform:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/10564505/" target="_blank"&gt;Does FireMonkey have anything similar to GetSystemMetrics?&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-713645639566714079?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/713645639566714079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/keeping-screen-resolution-in-mind.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/713645639566714079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/713645639566714079'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/keeping-screen-resolution-in-mind.html' title='Keeping Screen Resolution in Mind'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-8463373319930191132</id><published>2012-05-06T19:07:00.000-07:00</published><updated>2012-05-06T19:12:44.433-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='report-builder'/><title type='text'>Print to File Options Supported by ReportBuilder</title><content type='html'>Wow, I'm really impressed with the out of the box, &lt;strong&gt;Print to File&lt;/strong&gt; options that come with ReportBuilder. All you do is set the &lt;strong&gt;AllowPrintToFile&lt;/strong&gt; to &lt;strong&gt;True&lt;/strong&gt; and you are done!&lt;br /&gt;&lt;br /&gt;The default Print to File option is PDF. But there are several others. The image formats create one image per page. The HTML option creates an *_htm_images folder for any images that might be on the report.&lt;br /&gt;&lt;br /&gt;﻿ &lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-xtbqihsI0dY/T6csEYE4gpI/AAAAAAAAAEs/roNnWmEbjPg/s1600/PrintToFileOptions.jpg" imageanchor="1" style="clear: left; cssfloat: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" mea="true" src="http://3.bp.blogspot.com/-xtbqihsI0dY/T6csEYE4gpI/AAAAAAAAAEs/roNnWmEbjPg/s1600/PrintToFileOptions.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;span style="color: black;"&gt;Image modifed to show all Type options&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;﻿ &lt;div class="separator" style="clear: both; text-align: left;"&gt;Print to File&amp;nbsp;accepts the Page Range options as well. I even tried breaking it by printing page 3 of a 2 page report. No errors popped up and no output file was created.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;I am extremely pleased with my purchase. ReportBuilder has proven to be everything I expected it to be and more. &lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Semper Fi - Gunny Mike&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;﻿&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-8463373319930191132?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/8463373319930191132/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/print-to-file-options-supported-by.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/8463373319930191132'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/8463373319930191132'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/print-to-file-options-supported-by.html' title='Print to File Options Supported by ReportBuilder'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-xtbqihsI0dY/T6csEYE4gpI/AAAAAAAAAEs/roNnWmEbjPg/s72-c/PrintToFileOptions.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-1046566711447903628</id><published>2012-05-06T13:37:00.001-07:00</published><updated>2012-05-06T13:37:44.481-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='musings'/><title type='text'>A Simple Way to Learn About Methods and Properties</title><content type='html'>I've decided this time around with Delphi, I'm going to do&amp;nbsp;things as best as I possibly can.&amp;nbsp;A long time ago I&amp;nbsp;met Jeff Duntemann (&lt;a href="http://www.contrapositivediary.com/" target="_blank"&gt;here's his blog&lt;/a&gt;). If you know Jeff, you know he has an astounding vocabulary. I asked him about that once and he responded:&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;em&gt;"Michael, the reason for my vocabulary is simple, my parents. When I asked for the definition of&amp;nbsp;a particular word&amp;nbsp;they told me to look it up in the dictionary. And while you are reading about that word, read about every word on both facing pages."&lt;/em&gt;&lt;/blockquote&gt;Jeff developed this habit when he was young and he still carrys it with him today. What a simple concept. I have decided to use this idea when I go looking up a the reference to a property or method&amp;nbsp;of a Delph object. Not only am I going to read about the property I was intially interested in, I will read about all the other properties and methods. &lt;br /&gt;&lt;br /&gt;Thank you Jeff, I finally figured out how to use your dictionary lookup idea!&lt;br /&gt;&lt;br /&gt;Semper Fi - Gunny Mike&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-1046566711447903628?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/1046566711447903628/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/simple-way-to-learn-about-methods-and.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/1046566711447903628'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/1046566711447903628'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/simple-way-to-learn-about-methods-and.html' title='A Simple Way to Learn About Methods and Properties'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-8258522646012090325</id><published>2012-05-06T11:03:00.001-07:00</published><updated>2012-05-06T12:32:29.425-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='delphi-nugget'/><category scheme='http://www.blogger.com/atom/ns#' term='elevate-db'/><title type='text'>How to get the DBDemos Database into ElevatdDB</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: left;"&gt;There are several Delphi tutorials out there that use&amp;nbsp;the DBDemos database that ships with Delphi. I tend to learn much better if I actually perform the tasks outlined in these tutorials rather than just reading or viewing them. However, I'd much rather perform these tasks using&amp;nbsp;ElevateDB, since this is the database I have chosen for all my new applications.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;I started looking around to see if someone has done this already. I was looking for a .zip file out there in internet land. I posted to the ElevateDB support group hoping someone had a .zip file I could get my hands on. What I found was much more valuable.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;blockquote class="tr_bq"&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;em&gt;One of the regulars, Roy, said why don't you just use the "built-in BDE migrator" that comes with ElevateDB.&lt;/em&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;This is one of the coolest things I have done with ElevateDB. I learned so much more going through this process then I would have if I simply downloaded some .zip&amp;nbsp;off the internet.This whole process takes less than 5 minutes from start to finish. It looks very complicated but believe me it's not.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 class="separator" style="clear: both; text-align: left;"&gt;Step 1 -&amp;nbsp;Create a Session Called DBDemos&lt;/h3&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Make sure you have the ElevateDB Manager up and running. &lt;em&gt;&lt;strong&gt;Right-Click&lt;/strong&gt;&lt;/em&gt; on ElevateDB Manager and then choose&amp;nbsp;&lt;strong&gt;Create New Session&lt;/strong&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://1.bp.blogspot.com/-WTQu2Msdd-Q/T6aQIi5EEhI/AAAAAAAAAC8/9n-3wWLbkbs/s1600/CreateSession.png" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img alt="" border="0" mea="true" src="http://1.bp.blogspot.com/-WTQu2Msdd-Q/T6aQIi5EEhI/AAAAAAAAAC8/9n-3wWLbkbs/s1600/CreateSession.png" title="" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h4 class="separator" style="clear: both; text-align: left;"&gt;General Tab&lt;/h4&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;There are two things that need to be done inside the General tab.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;&lt;span style="color: #3d85c6;"&gt;&lt;span style="color: #3d85c6;"&gt;Name:&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&amp;nbsp;&lt;strong&gt;DBDemos&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;span style="color: #3d85c6;"&gt;Description:&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;DBDemos database that ships with Delphi&lt;/strong&gt;&lt;/strong&gt;&lt;/li&gt;&lt;/ol&gt;&lt;strong&gt;&lt;span style="color: #cc0000;"&gt;DO NOT CLICK OK . . Switch to the Local tab&lt;/span&gt;&lt;/strong&gt;&lt;a href="http://4.bp.blogspot.com/-iua1BsINcTw/T6aSO2iIKfI/AAAAAAAAADE/IwjeROJNhbM/s1600/General.png" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" mea="true" src="http://4.bp.blogspot.com/-iua1BsINcTw/T6aSO2iIKfI/AAAAAAAAADE/IwjeROJNhbM/s1600/General.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4 class="separator" style="clear: both; text-align: left;"&gt;Local&amp;nbsp;Tab&lt;/h4&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;There are two things that need to be done inside the Local tab.&lt;/div&gt;&lt;ol&gt;&lt;li&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;span style="color: #3d85c6;"&gt;&lt;strong&gt;&lt;span style="color: #3d85c6;"&gt;File Folder:&lt;/span&gt;&amp;nbsp;&lt;/strong&gt;&lt;/span&gt;&amp;nbsp;Enter the location&amp;nbsp;for configuration file for this&amp;nbsp;session. Don't worry if this folder doesn't exist, it will get created for you later on.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;span style="color: #3d85c6;"&gt;&lt;strong&gt;Large File Support&lt;span style="color: black;"&gt;:&lt;/span&gt; &lt;/strong&gt;&lt;/span&gt;&amp;nbsp;Make sure this box is &lt;strong&gt;checked&lt;/strong&gt;.&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;span style="color: #cc0000;"&gt;&lt;strong&gt;DO NOT CLICK OK . . Switch to the Login tab&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-m1hSe2Do6Ic/T6aVh7pv5hI/AAAAAAAAADQ/Ms8k7oo7NoQ/s1600/LocalTab.png" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" mea="true" src="http://3.bp.blogspot.com/-m1hSe2Do6Ic/T6aVh7pv5hI/AAAAAAAAADQ/Ms8k7oo7NoQ/s1600/LocalTab.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4 class="separator" style="clear: both; text-align: left;"&gt;Login Tab&lt;/h4&gt;&lt;br /&gt;&lt;div&gt;There are three things that need to be done inside the Login tab.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="color: #3d85c6;"&gt;&lt;strong&gt;User Name:&lt;/strong&gt;&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Administrator&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color: #3d85c6;"&gt;&lt;strong&gt;Password: Enter:&lt;/strong&gt;&lt;/span&gt;&amp;nbsp; &lt;strong&gt;EDBDefault&lt;/strong&gt;&lt;/li&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;li&gt;&lt;span style="color: #3d85c6;"&gt;Confirm Password:&lt;/span&gt;&amp;nbsp; &lt;strong&gt;EDBDefault&lt;/strong&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="color: #cc0000;"&gt;&lt;strong&gt;NOW CLICK OK&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-OGwMLZPvJ58/T6acU0PHUXI/AAAAAAAAADc/eq2YCmdf1Gg/s1600/LoginTab.png" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" mea="true" src="http://1.bp.blogspot.com/-OGwMLZPvJ58/T6acU0PHUXI/AAAAAAAAADc/eq2YCmdf1Gg/s1600/LoginTab.png" /&gt;&lt;/a&gt;&lt;br /&gt;﻿ &lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-b2ljNNfbEm0/T6ad8XUtUHI/AAAAAAAAADk/YnRiNSPvFhM/s1600/Confirm1.png" imageanchor="1" style="clear: left; cssfloat: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" mea="true" src="http://2.bp.blogspot.com/-b2ljNNfbEm0/T6ad8XUtUHI/AAAAAAAAADk/YnRiNSPvFhM/s1600/Confirm1.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;strong&gt;&lt;span style="color: #cc0000;"&gt;Click Yes if prompted to create folder.&lt;/span&gt;&lt;/strong&gt; &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;﻿ &lt;br /&gt;&lt;h3 class="separator" style="clear: both; text-align: left;"&gt;Step 2 - Create Database Migrators&lt;/h3&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Now we need to add the database Migrators that come with ElevateDB to the DBMemos session. &lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Expand the ElevateDB Manager by clicking on the + (Plus) &lt;/li&gt;&lt;li&gt;You will see the DBDemos session we just created&lt;/li&gt;&lt;li&gt;Expand the DBDemos session by clicking on the + (Plus)&lt;/li&gt;&lt;li&gt;Right-Click on DBDemos&lt;/li&gt;&lt;li&gt;Choose Create Database Migrators&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-ouDGwi0uX3I/T6ai2FyUGVI/AAAAAAAAADw/SjUhC9earxo/s1600/CreateMigrators.png" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" mea="true" src="http://2.bp.blogspot.com/-ouDGwi0uX3I/T6ai2FyUGVI/AAAAAAAAADw/SjUhC9earxo/s1600/CreateMigrators.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3&gt;Step 3 - Create an Empty DBDemos database&lt;/h3&gt;Now we need to add the database Migrators that come with ElevateDB to the DBMemos session. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Expand the ElevateDB Manager by clicking on the + (Plus) &lt;/li&gt;&lt;li&gt;Expand the DBDemos session by clicking on the + (Plus)&lt;/li&gt;&lt;li&gt;Right-Click on Databases&lt;/li&gt;&lt;li&gt;Choose Create&amp;nbsp;New Database...﻿&lt;/li&gt;&lt;/ul&gt;﻿&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;a href="http://1.bp.blogspot.com/-UPWJGun25Hg/T6aoxrG5SxI/AAAAAAAAAD8/O6vKIS19cOE/s1600/CreateNewDatabase.png" imageanchor="1" style="clear: left; cssfloat: left; margin-bottom: 1em;"&gt;&lt;img border="0" mea="true" src="http://1.bp.blogspot.com/-UPWJGun25Hg/T6aoxrG5SxI/AAAAAAAAAD8/O6vKIS19cOE/s1600/CreateNewDatabase.png" /&gt;&lt;/a&gt;&lt;/div&gt;﻿&lt;br /&gt;There are three things that need to be done on the General tab&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;&lt;span style="color: #3d85c6;"&gt;Name&lt;/span&gt;&lt;/strong&gt;:&lt;strong&gt;DBDemos&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;span style="color: #3d85c6;"&gt;Description&lt;/span&gt;&lt;/strong&gt;: &lt;strong&gt;DBDemos Database that ships with Delphi&lt;/strong&gt;&lt;/li&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;li&gt;&lt;span style="color: #3d85c6;"&gt;&lt;strong&gt;Folder&lt;/strong&gt;:&lt;/span&gt; Enter the location where you want the database files to reside. In my example I simply use a&amp;nbsp;DB folder in the&amp;nbsp;same location as the session folder.&lt;/li&gt;&lt;/ol&gt;&lt;strong&gt;&lt;span style="color: #cc0000;"&gt;CLICK OK WHEN DONE&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;﻿﻿ &lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-CHCDzDxdjc8/T6atGmQrejI/AAAAAAAAAEI/VWITPvDcmag/s1600/CreateNewDatabase2.png" imageanchor="1" style="clear: left; cssfloat: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" mea="true" src="http://1.bp.blogspot.com/-CHCDzDxdjc8/T6atGmQrejI/AAAAAAAAAEI/VWITPvDcmag/s1600/CreateNewDatabase2.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;strong&gt;&lt;span style="color: #cc0000;"&gt;Click OK when Done&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;﻿﻿ &lt;br /&gt;&lt;h3 class="separator" style="clear: both; text-align: left;"&gt;Step 4 - Migrate the DBDemos Database and Into ElevateDB&lt;/h3&gt;&amp;nbsp;We are almost done, this is the final step.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Expand&amp;nbsp;ElevateDB Manager by clicking on the + (Plus) &lt;/li&gt;&lt;li&gt;Expand&amp;nbsp;DBDemosseaaion by clicking on the + (Plus)&lt;/li&gt;&lt;li&gt;Expand&amp;nbsp;Databases&amp;nbsp;by clicking on the + (Plus)&lt;/li&gt;&lt;li&gt;Right-Click on DBDemos database&lt;/li&gt;&lt;li&gt;Choose&amp;nbsp;Migrate Database...﻿&lt;/li&gt;&lt;/ul&gt;﻿﻿﻿﻿﻿﻿ &lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;a href="http://2.bp.blogspot.com/-_TUa4To9noI/T6axiMu9F2I/AAAAAAAAAEU/CsgN_A6qZgk/s1600/Migrate1.png" imageanchor="1" style="clear: left; cssfloat: left; margin-bottom: 1em;"&gt;&lt;img border="0" mea="true" src="http://2.bp.blogspot.com/-_TUa4To9noI/T6axiMu9F2I/AAAAAAAAAEU/CsgN_A6qZgk/s1600/Migrate1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;There are seven things that need to be done on the Migrate Database&amp;nbsp;Source tab.&lt;/div&gt;&lt;ol&gt;&lt;li&gt;&lt;div style="text-align: left;"&gt;&lt;span style="color: #3d85c6;"&gt;&lt;strong&gt;Migrator:&lt;/strong&gt;&lt;/span&gt; Choose &lt;strong&gt;BDE&lt;/strong&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: left;"&gt;&lt;span style="color: #3d85c6;"&gt;&lt;strong&gt;Ckeckbox:&lt;/strong&gt;&lt;/span&gt; Make sure &lt;strong&gt;Include Table Data&lt;/strong&gt; is checked&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: left;"&gt;&lt;strong&gt;&lt;span style="color: #3d85c6;"&gt;Parameters Grid:&lt;/span&gt;&lt;/strong&gt;&amp;nbsp;Click &lt;strong&gt;DatabaseName&lt;/strong&gt; to highlight the grid row&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: left;"&gt;&lt;strong&gt;&lt;span style="color: #3d85c6;"&gt;Value&lt;/span&gt;&lt;/strong&gt;: Enter &lt;strong&gt;DBDemos&lt;/strong&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: left;"&gt;&lt;span style="color: black;"&gt;Click &lt;strong&gt;&lt;u&gt;S&lt;/u&gt;et Paramter Value&lt;/strong&gt; button&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: left;"&gt;&lt;span style="color: #cc0000;"&gt;Veify&amp;nbsp;the Parameter Grid shows &lt;strong&gt;DBDemos&lt;/strong&gt; for the &lt;strong&gt;DatabaseName&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="text-align: left;"&gt;&amp;nbsp;Click &lt;strong&gt;&lt;u&gt;O&lt;/u&gt;K&lt;/strong&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;﻿﻿ ﻿&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;a href="http://1.bp.blogspot.com/-mv_youtnB-4/T6a2ECEMFhI/AAAAAAAAAEg/9oOniYQrxd0/s1600/Migrate2.png" imageanchor="1" style="clear: left; cssfloat: left; margin-bottom: 1em;"&gt;&lt;img border="0" mea="true" src="http://1.bp.blogspot.com/-mv_youtnB-4/T6a2ECEMFhI/AAAAAAAAAEg/9oOniYQrxd0/s1600/Migrate2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Congratulations. You now have an ElevatdDB version of the DBDemos database you can use to follow along with all the Delphi tutorials out there.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Enjoy!&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Semper Fi - Gunny Mike﻿﻿﻿﻿﻿﻿&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-8258522646012090325?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/8258522646012090325/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/how-to-get-dbdemos-database-into.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/8258522646012090325'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/8258522646012090325'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/how-to-get-dbdemos-database-into.html' title='How to get the DBDemos Database into ElevatdDB'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-WTQu2Msdd-Q/T6aQIi5EEhI/AAAAAAAAAC8/9n-3wWLbkbs/s72-c/CreateSession.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-4370158437461755341</id><published>2012-05-03T18:46:00.000-07:00</published><updated>2012-05-05T05:52:48.018-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='stored-procedure'/><category scheme='http://www.blogger.com/atom/ns#' term='elevate-db'/><category scheme='http://www.blogger.com/atom/ns#' term='report-builder'/><title type='text'>Rethinking the Use of Stored Procedures</title><content type='html'>As I mentioned in a previous post, I was absent from Delphi programming for about 7 years. During that time I worked 50-60 hours a week on custom database driven websites using ASP and Microsoft SQL Server. I estimate that this resulted in 200 (plus/minus) websites.  &lt;br&gt;&lt;br&gt; Programming for the web taught me about statelessness, bandwith conservation, and the biggie, SQL Injection. Being the lead programmer I developed standards for the use of stored procedures in everything we did. I learned a lot, made my fair share of mistakes, and developed a deep admiration for stored procedures. &lt;br&gt;&lt;br&gt; The focus became take a request from a webpage, go to the server, do as much on the server as possible while you are there, and return the results to the webpage. Works great. &lt;br&gt;&lt;br&gt; So, now I'm back into Delphi and rewriting a desktop application that hasn't been updated since 2004. The jump from D5E to D2010 in itself, has been a challenge. I'm also going from a non-database application to a databse application. The database I have chosen to use is ElevateDB. &lt;br&gt;&lt;br&gt; One of the reasons I chose ElevateDB was it offers stored procedures. I love stored procedures, they are like black boxes. As long as the interface doesn't change they are good-to-go and offer awesome power.  &lt;br&gt;&lt;br&gt; So, I'm taking all this thinking I developed throughout those web years and applying it straight to Delphi and the application rewrite I'm doing. I know that a stand alone desktop application doesn't have to worry about statelessness, or bandwith conservation, and for the most part SQL injection. But it's hard to re-learn to think... until the rubber meets the road. &lt;br&gt;&lt;br&gt; The rubber met the road when I decided to build my first report using ReportBuilder. I've never truely had a reporting tool before... even in my web days I built everything from scratch. So, I took the amortization schedule I built as an &lt;a href="http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-5.html"&gt;ElevateDB stored procedure&lt;/a&gt; and made that my first report. Everything is going well, the report looks professional, I'm having fun. &lt;br&gt;&lt;br&gt; Then I start thinking... wow it wouldn't be nice to add a a percentage of payment next to the principal column. Wouldn't it be nice to show the percentage of interest also. And it would be totally awesome to bunch them by the year the payment is due. So, I decide to add two calculated fields to my report, no big deal. PrinPct is simply Payment divided by Principal. &lt;br&gt;&lt;br&gt; Then I realized... &lt;ul&gt;&lt;li&gt;You can't add a calculated value from a stored procedure column&lt;/li&gt;&lt;li&gt;You can't do a group by based on the the year of the payment&lt;/li&gt;&lt;li&gt;Wow, building a report based on the result set of a stored procedure is not the best approach&lt;/li&gt;&lt;/ul&gt; &lt;blockquote&gt;&lt;i&gt;"My first thought was, great ReportBuilder doesn't let me do what I want to do. This sucks." &lt;/i&gt;&lt;/blockquote&gt; Then I realized... &lt;blockquote&gt;&lt;i&gt;"It's not ReportBuilder, it's me. My thinking is wrong. Stored procedures are not meant to be reported on... they are meant to do the heavy lifting that makes the data easy to report against" &lt;/i&gt;&lt;/blockquote&gt; I'm glad that this happened to me early on in the process. I would have been quite upset had I created a total database with 30-40 stored procedures all built on the assumption that they could be used as datasets for reporting.  &lt;br&gt;&lt;br&gt; Back to the drawing board... another lesson learned. &lt;br&gt;&lt;br&gt;Semper Fi, Gunny Mike &lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-4370158437461755341?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/4370158437461755341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/rethinking-use-of-stored-procedures.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/4370158437461755341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/4370158437461755341'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/rethinking-use-of-stored-procedures.html' title='Rethinking the Use of Stored Procedures'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-8577850829280127937</id><published>2012-05-02T16:28:00.001-07:00</published><updated>2012-05-05T05:53:58.009-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='survery'/><title type='text'>Reporting Tool Survey</title><content type='html'>Here is an unsophisticated poll to see which Delphi reporting toll is used. Please only vote once.  &lt;br&gt;&lt;br&gt;(Participation in this poll requires a Linkedin account)  &lt;br&gt;&lt;br&gt;&lt;iframe src='http://polls.linkedin.com/vote/307238/wixje' marginheight='0' marginwidth='0' topmargin='0' leftmargin='0' allowtransparency='true' frameborder='0' height='250' scrolling='no' width='300' readonly='readonly'&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-8577850829280127937?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/8577850829280127937/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/reporting-tool-survey.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/8577850829280127937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/8577850829280127937'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2012/05/reporting-tool-survey.html' title='Reporting Tool Survey'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-3972774269587461209</id><published>2012-04-26T19:17:00.001-07:00</published><updated>2012-05-05T05:54:45.574-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='report-builder'/><title type='text'>Composite Reporting With Mixed Orientation</title><content type='html'>&lt;p&gt;I have spent the last two weeks researching different reporting tools for Delphi. I currently own Delphi 2010 Professional which comes with &lt;b&gt;Rave &lt;/b&gt;built into the IDE. My customers have asked me for a "one-click" printing solution. Instead of previewing and printing each report one-at-a-time, they would like to simply press the &lt;b&gt;[ Print ]&lt;/b&gt; buttton once and "presto" all the reports get printed. That is a fairly reasonable request. &lt;/p&gt;&lt;p&gt;&lt;h3&gt;Rave&lt;/h3&gt;So, I tried firing up the built in &lt;b&gt;Rave&lt;/b&gt; tool. My first impression was tremendous anxiety. I literally felt like I was in the cockpit of an airplane staring at all these unrecognizable controls. The database product I use is &lt;a href="http://www.elevatesoft.com/products?category=edb" target="_blank"&gt;ElevateDB&lt;/a&gt; and I had failed at several attempts to get hooked up to an active dataset. Finally, I somehow stumbled into a control that produced live data. I felt like on was on track. &lt;/p&gt;&lt;p&gt;So, now I'm looking to see how I can create a composite report. I like the idea of providing my customers with a "one-click" solution. However, the reports I need to create are a combination of portrait and landscape orientations. Now, the task has just gotten a little more trickier. &lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;i&gt;&lt;blockquote&gt;I need to create a composite report that allows a combination of portrait and landscape orientations. &lt;/blockquote&gt;&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I begin my quest for knowledge like I always do... StackOverflow. I quickly came across the following post regarding &lt;b&gt;Rave&lt;/b&gt;. &lt;a href="http://stackoverflow.com/q/10007457/195983" target="_blank"&gt;Migrating from QuickReport to FastReport, Rave Reports or what?&lt;/a&gt; This sounded interesting seeing how my older programs used Quick Reports. After reading some of the comments it further drove me away from &lt;b&gt;Rave&lt;/b&gt;. &lt;/p&gt;&lt;p&gt;&lt;h3&gt;Quick Reports&lt;/h3&gt;I'm familiar with &lt;b&gt;Quick Reports&lt;/b&gt; I even purchased the profession version when I was using Delphi 5 Enterprise. I know &lt;b&gt;Quick Reports&lt;/b&gt; lets you create composite reports but does it allow for the mixing of portrait and lanscape orientations withing a single report. The answer is no. Here is the response I received from the developer: &lt;p&gt;&lt;b&gt;&lt;i&gt;&lt;blockquote&gt;Hi, &lt;br&gt;&lt;br&gt;It can't be done with the present code. I'm not sure why but mixing  report orientations just doesn't work. &lt;br&gt;&lt;br&gt;Regards,  QBS Software Ltd &lt;/blockquote&gt;&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;So, &lt;b&gt;Quick Reports&lt;/b&gt; is out. That's too bad because I have already spent several hours with that tool even though it was eight years ago.&lt;/p&gt;&lt;p&gt;&lt;h3&gt;FastReport&lt;/h3&gt;Now this looks promising. &lt;b&gt;FastReport&lt;/b&gt; comes bundled with Delphi XE2 (which I will be upgrading to fairly soon). So far so good. I'm still waiting to here from them wether they support mixed orientation within a composit report. I'll update this post when I find out. &lt;/p&gt;&lt;p&gt;&lt;h3&gt;Report Builder (Digital Metaphors)&lt;/h3&gt;This is the reason I am writing. The answer is &lt;b&gt;YES&lt;/b&gt;. &lt;b&gt;Report Builder&lt;/b&gt; supports a composite report with mixed orientation. I sent three emails and received three emails from the sales and support team at Digital Metaphors within a 1 hour span. Not only did they answer my question, they gave me a link to Delphi code that shows an example of how to do this very thing. But wait there's more. . . &lt;br&gt;&lt;br&gt;Here is their mission statement lifted right off the website...  &lt;b&gt;&lt;i&gt;&lt;blockquote&gt;At Digital Metaphors Corporation we believe that our existence is guaranteed only when we successfully complete the actions listed below on a daily basis:&lt;br&gt;&lt;br&gt;&lt;li&gt;Create software of the highest quality&lt;/li&gt;&lt;li&gt;Ensure that customers receive the maximum possible value from our software&lt;/li&gt;&lt;li&gt;Go the extra mile in every phase of the software business&lt;/li&gt;&lt;li&gt;Make things go right&lt;/li&gt;&lt;li&gt;Regardless of circumstances, use intelligence, common sense, and inspiration to create results which are a service to both our customers and our fellow employees&lt;/li&gt;&lt;/blockquote&gt;&lt;/i&gt;&lt;/b&gt; I started looking around their website for some nuggets and I came across a download called &lt;a href="http://www.digital-metaphors.com/download/learning_reportbuilder.html" target="_blank"&gt;&lt;b&gt;Learning ReportBuilder&lt;/b&gt;&lt;/a&gt;. This is a hands-on learning experience. It combines a 145 page &lt;b&gt;step-by-step&lt;/b&gt; guide with a report builder tool that thoroughly teaches you how to use their product. &lt;br&gt;&lt;br&gt;I definitely felt like I was in the cockpit of an airplane looking at all the controls except this time, there was an instructor sitting right by my side guiding me through each maneuver. The controls will look familiar to any Delphi programmer. If you are in the market for a reporting tool, I urge you to download the &lt;b&gt;Learning ReportBuilder&lt;/b&gt; hands-on tutorial before you make a decision. It's that good.&lt;br&gt;&lt;br&gt; I want to thank &lt;b&gt;David Cornelius&lt;/b&gt; from &lt;a href="http://corneliusconcepts.com/" target="_blank"&gt;cornelius concepts&lt;/a&gt; for telling me about Report Builder. &lt;/p&gt;&lt;p&gt;Semper Fi,&lt;br&gt;Gunny Mike  &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-3972774269587461209?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/3972774269587461209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2012/04/composite-reporting-with-mixed.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/3972774269587461209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/3972774269587461209'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2012/04/composite-reporting-with-mixed.html' title='Composite Reporting With Mixed Orientation'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-5451227047454798726</id><published>2012-01-01T06:48:00.000-08:00</published><updated>2012-05-05T06:21:59.658-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='musings'/><title type='text'>Wisdom: Rekindle That Enthusiasm</title><content type='html'>&lt;b&gt;Happy New Year!&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;I was thinking about my software the other day. I have a piece of software I created over 20 years ago and it still sells today. Somewhere along the line I lost my enthusiasm for this product. Maybe I got busy on other stuff, maybe sales weren't as robust as I thought they should have been. Anyway for whatever reason I seem to have lost enthusiasm for my software... until now.&lt;br /&gt;&lt;br /&gt;A few weeks ago I was watching a show on TV about singers and songwriters who created hits back in the 1960s. And when these artists got up to perform their songs even though these songs are more than 50 years old they sang them with enthusiam and gusto. This got me thinking that I'm missing the boat here with my software.&lt;br /&gt;&lt;br /&gt;If you're like me and you have a software product that's been selling for twenty years and it's still selling today, that tells you people like your stuff. I'm going to say that again. If you have a software product that's been selling for twenty years and it's still selling today, that tells you people like your stuff. So take it from me don't become complacent. Don't take that fact for granted.&lt;br /&gt;&lt;br /&gt;So this year starting today January 1, 2012, a brand-new year, I'm changing the attitude I have about my software. I will treat my software as though it were a hit song. My software is a hit. If you're in the same boat as me I want you to recognize the fact that you have a hit as well. Hits don't come along that often, in fact there are some songwriters who are known as one-hit wonders. They spend their entire lives creating songs and for just one, single solitary moment, everything came together just right and they produced a hit. &lt;br /&gt;&lt;br /&gt;Why is this important and what difference does it make? As you talk about your product are you enthused? People can tell. I need to be more enthused. If I'm not excited how can I expect my customers to get excited. When describing  product features and benefits do you sound monotone or are you enthused? If you're not it is fair to expect people to get enthused. And believe it or not there's a group of people out there who have never seen your product before.&lt;br /&gt;&lt;br /&gt;My last assignment for the Marine Corps was Marine barracks Washington DC. And from Memorial Day until Labor Day every Friday night from five o'clock until midnight we were put on our dress blues and entertained the crowd who came to see the parade and the Marine Corps Silent Drill Team. &lt;br /&gt;&lt;br /&gt;The first three or four weeks of every new parade season was exciting. We haven't done this for a while. We get all dressed up in pretty clothes and we walk around representing the Marine Corps's finest. And then the thought of the long, dreaded season would set in. I remember the first time this happened to me and I thought "oh my goodness I have four more months of this."&lt;br /&gt;&lt;br /&gt;So from that point on I told myself, "Michael you are going to meet somebody tonight that has never been to Washington D.C. before. Not only has this person never been to D.C. before, but this is the only time this person will ever come to Washington D.C. in their entire life. You don't know who that person is. So treat each person that you meet tonight as though it's that person."&lt;br /&gt;&lt;br /&gt;If I can do that for the entire Marine Corps parade season, I can do that for my product and so can you. You are going to talk to somebody and your website will meet somebody, who has never seen your product before. This could be a one time shot. You don't know who this person is, so treat everybody as though it's that person.&lt;br /&gt;&lt;br /&gt;Semper Fi,&lt;br /&gt;Gunny Mike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-5451227047454798726?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/5451227047454798726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2012/01/wisdome-rekindle-that-enthusiasm.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/5451227047454798726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/5451227047454798726'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2012/01/wisdome-rekindle-that-enthusiasm.html' title='Wisdom: Rekindle That Enthusiasm'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-7840044374732506873</id><published>2011-10-10T18:42:00.000-07:00</published><updated>2012-05-05T05:49:08.081-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='date-stuff'/><category scheme='http://www.blogger.com/atom/ns#' term='elevate-db'/><title type='text'>ElevateDB: Function isDate()</title><content type='html'>I am without a doubt spoiled by some of Microsoft SQL Server's built in functions. One such built in function that I have used many times is the isDATE function. This function let's you test whether a data value represents a date.&lt;br /&gt;&lt;br /&gt;ElevateDB does not have an isDATE function, so I built one and will show you the process I went through to make one.&lt;br /&gt;&lt;br /&gt;First I fired up the EDB Manager and created a new script that I could code and test as I went. I decided to see if I could use a BEGIN ... EXCEPTION ... END block to build this function. According to the documentation&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;Use these statements to declare a block of statements for execution in a procedure or function with an associated exception block of statements for handling any exceptions that may occur in the block of statements.&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;My intent was to &lt;b&gt;&lt;i&gt;"force an error"&lt;/i&gt;&lt;/b&gt; by trying to cast a string as a date and trap for an error if the string did not represent a date. It worked. The only gotcha was this, when I executed the code inside an EDB Manager script window, EDB Manager stopped execution to tell me that there was a conversion error with the line&lt;br /&gt;&lt;br /&gt;&lt;b&gt;SET TestDate = CAST(strDate as Date);&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#777777"&gt;ElevateDB Error #1011 An error occurred with the value 12345678 (A conversion error occurred)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;I will use the error number 1011 in the exception handling.&lt;br /&gt;&lt;br /&gt;I fully expected an error to occur but I didn't know the error number ahead of time. I then clicked continue and the program stopped at the breakpoint I had set for SET X = 1; When I inspected the local variables, I saw that the script had done exactly what I asked. It set the isDATE value to 0 (meaning not a date). When I toggle between commenting one of the SET strDate = ... lines, the script perfoms correctly.&lt;br /&gt;&lt;br /&gt;Copy this code into a new SCRIPT window inside EDB Manager and set a break point at the line&lt;br /&gt;&lt;font color="#E56717"&gt;&lt;b&gt;SET X = 1;&lt;/b&gt;&lt;/font&gt;. &lt;br /&gt;&lt;br /&gt;Notice the second SET strDate statement has been commented out&lt;br /&gt;&lt;i&gt;&lt;font color="#008000"&gt;--SET strDate = '1959-03-23'; commented out.&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;You can toggle between commenting out both of these SET strDate statements to see how EDB Manager handles good and bad date data.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;SCRIPT&lt;br /&gt;BEGIN&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- X is used set a breakpoint within ED Manager&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;DECLARE X INTEGER;&lt;br /&gt;&lt;br /&gt;DECLARE strDate varchar(20);&lt;br /&gt;DECLARE TestDate DATE;&lt;br /&gt;DECLARE isDATE INTEGER;&lt;br /&gt;DECLARE ErrCode Integer;&lt;br /&gt;&lt;br /&gt;SET isDATE = 1;&lt;br /&gt;SET strDate = '12345678';&lt;br /&gt;&lt;i&gt;&lt;font color="#008000"&gt;--SET strDate = '1959-03-23';&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;SET ErrCode = 0;&lt;br /&gt;&lt;br /&gt;BEGIN&lt;br /&gt;SET TestDate = CAST(strDate as Date);&lt;br /&gt;EXCEPTION&lt;br /&gt;   SET ErrCode = ERRORCODE();&lt;br /&gt;   IF ERRORCODE()=1011 THEN&lt;br /&gt;     SET isDATE = 0;&lt;br /&gt;   END IF;&lt;br /&gt;END;&lt;br /&gt;&lt;br /&gt;&lt;font color="#E56717"&gt;&lt;b&gt;SET X = 1;&lt;/b&gt;&lt;/font&gt;&lt;br /&gt;END&lt;/pre&gt;&lt;/code&gt;Converting the above script into an actual function is pretty straight forward. From inside EDB Manager open a new SQL window and copy the following code:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;CREATE FUNCTION "isDate"  (INOUT "DateStr" VARCHAR(20) COLLATE UNI)&lt;br /&gt;RETURNS INTEGER&lt;br /&gt;&lt;br /&gt;BEGIN&lt;br /&gt;DECLARE TestDate DATE;&lt;br /&gt;DECLARE ValidDate INTEGER;&lt;br /&gt;&lt;br /&gt;SET DateStr = COALESCE(DateStr,'');&lt;br /&gt;SET ValidDate = 1;&lt;br /&gt;&lt;br /&gt;BEGIN&lt;br /&gt;SET TestDate = CAST(DateStr as Date);&lt;br /&gt;EXCEPTION&lt;br /&gt;   IF ERRORCODE()=1011 THEN&lt;br /&gt;     SET ValidDate = 0;&lt;br /&gt;   END IF;&lt;br /&gt;END;&lt;br /&gt;&lt;br /&gt;RETURN ValidDate;&lt;br /&gt;END&lt;/pre&gt;&lt;/code&gt;This ElevateDB isDATE function is not as robust as the MS SQL Server function but it does allow you to test whether the date value passed in represents a date. Enjoy.&lt;br /&gt;&lt;br /&gt;Semper Fi,&lt;br /&gt;Gunny Mike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-7840044374732506873?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/7840044374732506873/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2011/10/elevatedb-function-isdate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/7840044374732506873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/7840044374732506873'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2011/10/elevatedb-function-isdate.html' title='ElevateDB: Function isDate()'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-1391539265125617360</id><published>2011-09-21T14:23:00.000-07:00</published><updated>2012-05-05T06:17:19.108-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='date-stuff'/><category scheme='http://www.blogger.com/atom/ns#' term='elevate-db'/><title type='text'>ElevatdDB: Date Math 2</title><content type='html'>Let me start off by mentioning a couple things. I'm not an expert at ElevateDB by any means and I don't claim to be one either. I purchased ElevateDB three weeks ago on 09/01/2011, and have only been using it for about ten days within that three week period.&lt;br /&gt;&lt;br /&gt;I'm sharing my ElevateDB experiences with you as they are happening. So, I'm blogging about what I'm learning along the way. As I get more proficient with ElevateDB I hope to reflect that proficiency in my postings about ElevateDB.&lt;br /&gt;&lt;br /&gt;Before I get to the Date Math stuff I need to tell you about the SQL query tool that comes with ElevateDB. It's called ElevateDB Manager. If you are familiar with Microsoft's SQL Server Management Studio or Microsoft's SQL Query Analyzer you should feel pretty comfortable with this tool. As of this writing it does not come with it's own manual. You can learn by doing or reading some of the &lt;a href="http://www.elevatesoft.com/forums?category=edb"&gt;support forum&lt;/a&gt; posts. &lt;br /&gt;&lt;br /&gt;All the stuff I have been doing so far has been done from within a script window inside the the ElevateDB Manager. You open a new script window by clicking &lt;b&gt;New|Script&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-kkneT6vecWQ/TnpMmbDvEsI/AAAAAAAAACM/F8ZrGmA6DAs/s1600/EDBManagerNewScript.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="144" src="http://1.bp.blogspot.com/-kkneT6vecWQ/TnpMmbDvEsI/AAAAAAAAACM/F8ZrGmA6DAs/s320/EDBManagerNewScript.png" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You can also set what are called "&lt;b&gt;Breakpoints&lt;/b&gt;". Breakpoints do exactly what they sound like they do, they break in and stop execution of a script as a specific point. To set a break point within a script you click inside the grey margin next to the line where you want the script execution to stop.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-cBa4WwEUCos/TnpNfNzu3SI/AAAAAAAAACU/_cNuN9Azp98/s1600/EDBManagerBreakPoint.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="146" src="http://3.bp.blogspot.com/-cBa4WwEUCos/TnpNfNzu3SI/AAAAAAAAACU/_cNuN9Azp98/s320/EDBManagerBreakPoint.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Breakpoints are very cool. They let you see the current value of all the local variable that have been declared within the script at the very spot of the breakpoint. I set the breakpoint at the line&lt;br&gt;&lt;b&gt;SET X = 1;&lt;/b&gt;&lt;br&gt; which is a do nothing statement purely for the purpose of letting me view the local variables.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-W3dthbZywW4/TnpOTp3nPUI/AAAAAAAAACY/6JdV712w3Ns/s1600/EDBManagerLocalVariables.png" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" hca="true" height="192" src="http://1.bp.blogspot.com/-W3dthbZywW4/TnpOTp3nPUI/AAAAAAAAACY/6JdV712w3Ns/s320/EDBManagerLocalVariables.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I'm metioning these items because that is how I tested and viewed the results of the date math code I'm about to share with you.&lt;br /&gt;&lt;br /&gt;How many times have you had to use a &lt;strong&gt;Start Date&lt;/strong&gt; and &lt;strong&gt;End Date&lt;/strong&gt; within your SQL queries? How many times have you had to set the &lt;strong&gt;Start Date&lt;/strong&gt; equal to the &lt;span style="color: #cc0000;"&gt;&lt;strong&gt;first day&lt;/strong&gt;&lt;/span&gt; of the current month and the &lt;strong&gt;End Date&lt;/strong&gt; to the &lt;span style="color: #cc0000;"&gt;&lt;strong&gt;last day&lt;/strong&gt;&lt;/span&gt; of the current month? How about the &lt;span style="color: #cc0000;"&gt;&lt;strong&gt;first&lt;/strong&gt;&lt;/span&gt; and &lt;span style="color: #cc0000;"&gt;&lt;strong&gt;last&lt;/strong&gt;&lt;/span&gt; days of the &lt;strong&gt;previous month&lt;/strong&gt;, or the &lt;strong&gt;following month&lt;/strong&gt;. &lt;br /&gt;&lt;br /&gt;I'm about to show you a simple, sure fire way to set these dates so they work everytime, no matter what. You don't need to worry about going backwards or forwards&amp;nbsp;a year. You don't need to worry whether there are 30 or 31 days in a month. You don't need to worry about February having 28 or 29 days. It's that simple.&lt;br /&gt;&lt;br /&gt;Just copy and past this code into an ElevateDB Script. Set a breakpoint at the line mentioned above and your all set. There's only one line that needs to be inserted into the bottom two examples that makes them different from the first example. I've colored them red.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How to set the StartDate and EndDate for the Current Month&lt;/h3&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;SCRIPT&lt;br /&gt;BEGIN&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- This snippet of code sets the StartDate and EndDate to the &lt;br /&gt;-- first day  and last day of the current month&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;DECLARE Today     DATE;&lt;br /&gt;DECLARE YYYY      INTEGER;&lt;br /&gt;DECLARE MM        INTEGER;&lt;br /&gt;DECLARE DateStr   VARCHAR(10);&lt;br /&gt;DECLARE WorkDate  DATE;&lt;br /&gt;DECLARE StartDate DATE;&lt;br /&gt;DECLARE EndDate   DATE;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- X is used set a breakpoint within ED Manager&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;DECLARE X INTEGER;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- Get the current Year and Month&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET Today = Current_Date;&lt;br /&gt;SET YYYY  = EXTRACT(YEAR FROM Today);&lt;br /&gt;SET MM    = EXTRACT(Month FROM Today);&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- Set the WorkDate equal to the first day of the current month&lt;br /&gt;-- by building a date string from the extracted date parts&lt;br /&gt;-- Example: YYYY-MM-01&lt;br /&gt;-- WHERE YYYY is the extracted Year&lt;br /&gt;-- AND   MM   is the extracted Month&lt;br /&gt;-- Make sure to pad any month less than 10 with a leading zero&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET DateStr = '';&lt;br /&gt;SET DateStr = DateStr + CAST(YYYY as VARCHAR);&lt;br /&gt;SET DateStr = DateStr + '-';&lt;br /&gt;IF MM &amp;lt; 10 THEN&lt;br /&gt;  SET DateStr = DateStr + '0';&lt;br /&gt;END IF;&lt;br /&gt;SET DateStr = DateStr + CAST(MM as VARCHAR);&lt;br /&gt;SET DateStr = DateStr + '-01';&lt;br /&gt;SET WorkDate  = CAST(DateStr as DATE);&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- Set StartDate equal to the first day of the month and create&lt;br /&gt;-- the EndDate by performing two simple date math operations&lt;br /&gt;-- 1. Add one Month to the WorkDate&lt;br /&gt;-- 2. Subtract one Day from the WorkDate&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET StartDate = WorkDate;&lt;br /&gt;SET WorkDate  = WorkDate + Interval  '1' MONTH;&lt;br /&gt;SET WorkDate  = WorkDate + Interval '-1' DAY;&lt;br /&gt;SET EndDate   = WorkDate;&lt;br /&gt;&lt;br /&gt;SET X = 1;&lt;br /&gt;END&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;h3&gt;How to set the StartDate and EndDate for the Previous Month&lt;/h3&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;SCRIPT&lt;br /&gt;BEGIN&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- This snippet of code sets the StartDate and EndDate to the &lt;br /&gt;-- first day  and last day of the previous month&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;DECLARE Today     DATE;&lt;br /&gt;DECLARE YYYY      INTEGER;&lt;br /&gt;DECLARE MM        INTEGER;&lt;br /&gt;DECLARE DateStr   VARCHAR(10);&lt;br /&gt;DECLARE WorkDate  DATE;&lt;br /&gt;DECLARE StartDate DATE;&lt;br /&gt;DECLARE EndDate   DATE;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- X is used set a breakpoint within ED Manager&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;DECLARE X INTEGER;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- Get the current Year and Month&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET Today = Current_Date;&lt;br /&gt;SET YYYY  = EXTRACT(YEAR FROM Today);&lt;br /&gt;SET MM    = EXTRACT(Month FROM Today);&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- Set the WorkDate equal to the first day of the current month&lt;br /&gt;-- by building a date string from the extracted date parts&lt;br /&gt;-- Example: YYYY-MM-01&lt;br /&gt;-- WHERE YYYY is the extracted Year&lt;br /&gt;-- AND   MM   is the extracted Month&lt;br /&gt;-- Make sure to pad any month less than 10 with a leading zero&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET DateStr = '';&lt;br /&gt;SET DateStr = DateStr + CAST(YYYY as VARCHAR);&lt;br /&gt;SET DateStr = DateStr + '-';&lt;br /&gt;IF MM &amp;lt; 10 THEN&lt;br /&gt;  SET DateStr = DateStr + '0';&lt;br /&gt;END IF;&lt;br /&gt;SET DateStr = DateStr + CAST(MM as VARCHAR);&lt;br /&gt;SET DateStr = DateStr + '-01';&lt;br /&gt;SET WorkDate  = CAST(DateStr as DATE);&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- For Previous month subtract one month from WorkDate&lt;br /&gt;-- Set StartDate equal to the first day of the month and create&lt;br /&gt;-- the EndDate by performing two simple date math operations&lt;br /&gt;-- 1. Add one Month to the WorkDate&lt;br /&gt;-- 2. Subtract one Day from the WorkDate&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;&lt;span style="color: #cc0000;"&gt;SET WorkDate  = WorkDate + Interval '-1' Month;&lt;/span&gt;&lt;br /&gt;SET StartDate = WorkDate;&lt;br /&gt;SET WorkDate  = WorkDate + Interval  '1' MONTH;&lt;br /&gt;SET WorkDate  = WorkDate + Interval '-1' DAY;&lt;br /&gt;SET EndDate   = WorkDate;&lt;br /&gt;&lt;br /&gt;SET X = 1;&lt;br /&gt;END&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;h3&gt;How to set the StartDate and EndDate for the Following Month&lt;/h3&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;SCRIPT&lt;br /&gt;BEGIN&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- This snippet of code sets the StartDate and EndDate to the &lt;br /&gt;-- first day  and last day of the following month&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;DECLARE Today     DATE;&lt;br /&gt;DECLARE YYYY      INTEGER;&lt;br /&gt;DECLARE MM        INTEGER;&lt;br /&gt;DECLARE DateStr   VARCHAR(10);&lt;br /&gt;DECLARE WorkDate  DATE;&lt;br /&gt;DECLARE StartDate DATE;&lt;br /&gt;DECLARE EndDate   DATE;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- X is used set a breakpoint within ED Manager&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;DECLARE X INTEGER;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- Get the current Year and Month&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET Today = Current_Date;&lt;br /&gt;SET YYYY  = EXTRACT(YEAR FROM Today);&lt;br /&gt;SET MM    = EXTRACT(Month FROM Today);&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- Set the WorkDate equal to the first day of the current month&lt;br /&gt;-- by building a date string from the extracted date parts&lt;br /&gt;-- Example: YYYY-MM-01&lt;br /&gt;-- WHERE YYYY is the extracted Year&lt;br /&gt;-- AND   MM   is the extracted Month&lt;br /&gt;-- Make sure to pad any month less than 10 with a leading zero&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET DateStr = '';&lt;br /&gt;SET DateStr = DateStr + CAST(YYYY as VARCHAR);&lt;br /&gt;SET DateStr = DateStr + '-';&lt;br /&gt;IF MM &amp;lt; 10 THEN&lt;br /&gt;  SET DateStr = DateStr + '0';&lt;br /&gt;END IF;&lt;br /&gt;SET DateStr = DateStr + CAST(MM as VARCHAR);&lt;br /&gt;SET DateStr = DateStr + '-01';&lt;br /&gt;SET WorkDate  = CAST(DateStr as DATE);&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- For Following month add one month to WorkDate&lt;br /&gt;-- Set StartDate equal to the first day of the month and create&lt;br /&gt;-- the EndDate by performing two simple date math operations&lt;br /&gt;-- 1. Add one Month to the WorkDate&lt;br /&gt;-- 2. Subtract one Day from the WorkDate&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;&lt;span style="color: #cc0000;"&gt;SET WorkDate  = WorkDate + Interval '1' Month;&lt;/span&gt;&lt;br /&gt;SET StartDate = WorkDate;&lt;br /&gt;SET WorkDate  = WorkDate + Interval  '1' MONTH;&lt;br /&gt;SET WorkDate  = WorkDate + Interval '-1' DAY;&lt;br /&gt;SET EndDate   = WorkDate;&lt;br /&gt;&lt;br /&gt;SET X = 1;&lt;br /&gt;END&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Enjoy,&lt;br /&gt;Gunny Mike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-1391539265125617360?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/1391539265125617360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatddb-date-math-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/1391539265125617360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/1391539265125617360'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatddb-date-math-2.html' title='ElevatdDB: Date Math 2'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-kkneT6vecWQ/TnpMmbDvEsI/AAAAAAAAACM/F8ZrGmA6DAs/s72-c/EDBManagerNewScript.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-8534259305840892069</id><published>2011-09-13T18:12:00.000-07:00</published><updated>2012-05-05T06:17:46.179-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='stored-procedure'/><category scheme='http://www.blogger.com/atom/ns#' term='elevate-db'/><title type='text'>ElevateDB: Stored Procedures Part 5</title><content type='html'>In the last post of this series &lt;a href="http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-4.html"&gt;ElevateDB: Stored Procedures Part&amp;nbsp;4&lt;/a&gt;&amp;nbsp;I told you I would share with you the optimized version of the stored procedure written by Tim Young from &lt;a href="http://www.elevatesoft.com/"&gt;ElevateSoft&lt;/a&gt; and I will. However, I need to point out that the monthly payment was calculated differently between the Microsoft SQL code and the ElevateDB code.&lt;br /&gt;&lt;br /&gt;I made sure I declared the APR input parameter as decimal(19,4) in both Microsft SQL and ElevateDB. Here are those declarations along with the appropriate code snippets:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;-----------------------------------------------------------------&lt;br /&gt;-- Microsoft SQL&lt;br /&gt;-----------------------------------------------------------------&lt;br /&gt;@APR decimal(19,4) = 3.25&lt;br /&gt;DECLARE @Payment decimal(19,2)&lt;br /&gt;SET @Payment = ROUND(@Principal * ((&lt;font color="#c90000"&gt;@APR/1200&lt;/font&gt;)/(1- EXP((@Months*-1) * LOG(1 + (&lt;font color="#c90000"&gt;@APR/1200&lt;/font&gt;))))),2)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Payment = 1370.20 (this is correct)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;-----------------------------------------------------------------&lt;br /&gt;-- ElevateDB (APR = 3.25 although it's not shown)&lt;br /&gt;-----------------------------------------------------------------&lt;br /&gt;IN "APR" DECIMAL(19,4), &lt;br /&gt;DECLARE Payment decimal(19,2);&lt;br /&gt;SET Payment = ROUND(Principal * ((&lt;font color="#c90000"&gt;APR/1200&lt;/font&gt;)/(1- EXP((Months*-1) * LN(1 + (&lt;font color="#c90000"&gt;APR/1200&lt;/font&gt;))))) to 2);&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Payment = 1369.26 &lt;font color="#c90000"&gt;(this is incorrect)&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;So, I decided to investigate why the two payments were different. Upon close examination I found the following:&lt;br /&gt;&lt;br /&gt;Even though both database have APR defined as decimal(19,4)...&lt;br /&gt;&lt;br /&gt;Microsoft SQL calculates @APR/1200 as 0.002708333&lt;br /&gt;ElevateDB calculates  APR/1200 as 0.0027&lt;br /&gt;&lt;br /&gt;I won't speculate why Microsoft's calculations seem to ignore the decimal place rules. I do know that ElevateDB does enforce the decimal place rules. So, armed with this bit of information, I changed ElevateDB to use the &lt;font color="#c90000"&gt;Float datatype&lt;/font&gt; for APR,&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;-----------------------------------------------------------------&lt;br /&gt;-- ElevateDB Revisited (APR = 3.25 although it's not shown)&lt;br /&gt;-----------------------------------------------------------------&lt;br /&gt;IN "APR" float,&lt;br /&gt;DECLARE Payment decimal(19,2);&lt;br /&gt;SET Payment = ROUND(Principal * ((&lt;font color="#c90000"&gt;APR/1200&lt;/font&gt;)/(1- EXP((Months*-1) * LN(1 + (&lt;font color="#c90000"&gt;APR/1200&lt;/font&gt;))))) to 2);&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Payment = 1370.20 (this is now correct)&lt;/b&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;So, if you intend to do calculations where the decimal places need to go beyond 4 places when using ElevateDB make sure to use the &lt;b&gt;float datatype&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;As promised, here is the optimized amortization schedule that Tim Young produced from the example Microsoft SQL Code i posted to his forum. There's a lot you can learn about how ElevateDB works from this code snippet, Enjoy!&lt;br /&gt;&lt;code&gt;&lt;pre&gt;----------------------------------------------------------------&lt;br /&gt;-- SQL Amortization Schedule&lt;br /&gt;-- Copyright 2011 © By Michael J. Riley&lt;br /&gt;-- www.zilchworks.com&lt;br /&gt;-- Created by Tim Young - ElevateSoft&lt;br /&gt;-- www.elevatesoft.com&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;CREATE PROCEDURE "spAmortizationSchedule02" (&lt;br /&gt;INOUT "StartDate" DATE, &lt;br /&gt;INOUT "Principal" DECIMAL(19,4), &lt;br /&gt;INOUT "APR" FLOAT, &lt;br /&gt;INOUT "Months" INTEGER)&lt;br /&gt;BEGIN&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- VARIABLE DECLARATIONS USED FOR PROCESSING&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;DECLARE InsertStmt STATEMENT;&lt;br /&gt;DECLARE InfoCursor SENSITIVE CURSOR FOR InfoStmt;&lt;br /&gt;DECLARE ResultCursor SENSITIVE CURSOR WITH RETURN FOR ResultStmt;&lt;br /&gt;&lt;br /&gt;DECLARE Payment      DECIMAL(19,4);&lt;br /&gt;DECLARE PaymentLast  DECIMAL(19,4);&lt;br /&gt;DECLARE PmtNumber    INTEGER;&lt;br /&gt;DECLARE PmtDate      DATE;&lt;br /&gt;DECLARE BalanceStart DECIMAL(19,4);&lt;br /&gt;DECLARE PmtInterest  DECIMAL(19,4);&lt;br /&gt;DECLARE PmtPrincipal DECIMAL(19,4);&lt;br /&gt;DECLARE BalanceEnd   DECIMAL(19,4);&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- INPUT PARAMETERS WITH DEFAULT VALUES&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;SET StartDate = COALESCE(StartDate, CURRENT_DATE());&lt;br /&gt;SET Principal = COALESCE(Principal, 195000);&lt;br /&gt;SET APR = COALESCE(APR, 3.25);&lt;br /&gt;SET Months = COALESCE(Months, 180);&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- TEMP TABLE TO HOLD AMORTIZATION OUTPUT&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;PREPARE InfoStmt FROM 'SELECT * FROM Information.TemporaryTables WHERE Name=?';&lt;br /&gt;OPEN InfoCursor USING 'TempAmortization02';&lt;br /&gt;IF ROWCOUNT(InfoCursor) &gt; 0 THEN&lt;br /&gt;  EXECUTE IMMEDIATE 'EMPTY TABLE TempAmortization02';&lt;br /&gt;ELSE&lt;br /&gt;  EXECUTE IMMEDIATE 'CREATE TEMPORARY TABLE TempAmortization02&lt;br /&gt;                    (&lt;br /&gt;                    PmtNumber    INTEGER       ,&lt;br /&gt;                    PmtDate      DATE          ,&lt;br /&gt;                    PmtAmount    DECIMAL(19,4) ,&lt;br /&gt;                    BalanceStart DECIMAL(19,4) ,&lt;br /&gt;                    PmtPrincipal DECIMAL(19,4) ,&lt;br /&gt;                    PmtInterest  DECIMAL(19,4) ,&lt;br /&gt;                    BalanceEnd   DECIMAL(19,4)&lt;br /&gt;                    )';&lt;br /&gt;END IF;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- CALCULATE MONTHLY PAYMENT BASED ON INPUT PARAMETERS&lt;br /&gt;-- This line may wrap and be hard to read&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET Payment = ROUND(Principal * ((APR/1200)/(1- EXP((Months*-1) *&lt;br /&gt;             LOG(1 + (APR/1200))))) to 2);&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- INITALIZE VARIABLES BEFORE THE LOOP STARTS&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET PmtNumber  = 0;&lt;br /&gt;SET BalanceEnd = Principal;&lt;br /&gt;&lt;br /&gt;PREPARE InsertStmt FROM 'INSERT INTO TempAmortization02&lt;br /&gt;                       (&lt;br /&gt;                       PmtNumber     ,&lt;br /&gt;                       PmtDate       ,&lt;br /&gt;                       PmtAmount     ,&lt;br /&gt;                       BalanceStart  ,&lt;br /&gt;                       PmtPrincipal  ,&lt;br /&gt;                       PmtInterest   ,&lt;br /&gt;                       BalanceEnd&lt;br /&gt;                       )&lt;br /&gt;                       VALUES (?,?,?,?,?,?,?)';&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- PERFORM CALCULATIONS FOR ALL BUT LAST MONTH AND&lt;br /&gt;-- STORE RESULTS IN TEMPORARY TABLE&lt;br /&gt;-- &lt;br /&gt;-- MICROSOFT SQL DATEADD(&lt;INTERVAL&gt;,&lt;VALUE&gt;,&lt;DATE&gt;&lt;br /&gt;-- ELEVATEDB SQL &lt;DATE&gt; + INTERVAL '&lt;VALUE&gt;' &lt;INTERVAL&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;WHILE PmtNumber &lt; Months -1 DO&lt;br /&gt;&lt;br /&gt;SET PmtNumber    = PmtNumber + 1;&lt;br /&gt;SET BalanceStart = BalanceEnd;&lt;br /&gt;SET PmtDate      = (StartDate + CAST(PmtNumber-1 AS INTERVAL MONTH));&lt;br /&gt;SET PmtInterest  = ROUND(BalanceStart *(APR/1200) to 2);&lt;br /&gt;SET PmtPrincipal = Payment - PmtInterest;&lt;br /&gt;SET BalanceEnd   = BalanceStart - PmtPrincipal;&lt;br /&gt;&lt;br /&gt;EXECUTE InsertStmt USING PmtNumber     ,&lt;br /&gt;                         PmtDate       ,&lt;br /&gt;                         Payment       ,&lt;br /&gt;                         BalanceStart  ,&lt;br /&gt;                         PmtPrincipal  ,&lt;br /&gt;                         PmtInterest   ,&lt;br /&gt;                         BalanceEnd;&lt;br /&gt;&lt;br /&gt;END WHILE;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- PERFORM CALCULATIONS FOR THE LAST MONTH AND&lt;br /&gt;-- STORE RESULTS IN TEMPORARY TABLE&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET PmtNumber    = PmtNumber +1;&lt;br /&gt;SET BalanceStart = BalanceEnd;&lt;br /&gt;SET PmtDate      = (StartDate + CAST(PmtNumber-1 AS INTERVAL MONTH));&lt;br /&gt;SET PmtInterest  = ROUND(BalanceStart *(APR/1200) ,2);&lt;br /&gt;SET PaymentLast  = BalanceStart + PmtInterest;&lt;br /&gt;SET PmtPrincipal = BalanceStart;&lt;br /&gt;SET BalanceEnd   = BalanceStart + PmtInterest - PaymentLast;&lt;br /&gt;&lt;br /&gt;EXECUTE InsertStmt USING PmtNumber     ,&lt;br /&gt;                        PmtDate       ,&lt;br /&gt;                        PaymentLast   ,&lt;br /&gt;                        BalanceStart  ,&lt;br /&gt;                        PmtPrincipal  ,&lt;br /&gt;                        PmtInterest   ,&lt;br /&gt;                        BalanceEnd;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- RETURN RESULTS FROM TEMPORARY TABLE&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;PREPARE ResultStmt FROM 'SELECT&lt;br /&gt;                       PmtNumber     ,&lt;br /&gt;                       PmtDate       ,&lt;br /&gt;                       PmtAmount     ,&lt;br /&gt;                       BalanceStart  ,&lt;br /&gt;                       PmtPrincipal  ,&lt;br /&gt;                       PmtInterest   ,&lt;br /&gt;                       BalanceEnd&lt;br /&gt;                       FROM TempAmortization02';&lt;br /&gt;OPEN ResultCursor;&lt;br /&gt;&lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;VERSION 1.00!&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;Semper Fi, &lt;br /&gt;Gunny Mike &lt;br /&gt;&lt;table border="0" style="width: 100px;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td width="50%"&gt;&lt;br /&gt;&lt;a href="http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-4.html"&gt;&amp;lt; Prev&lt;/a&gt;&lt;/td&gt;&lt;td width="50%"&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-8534259305840892069?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/8534259305840892069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-5.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/8534259305840892069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/8534259305840892069'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-5.html' title='ElevateDB: Stored Procedures Part 5'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-3777161271523557725</id><published>2011-09-08T17:03:00.000-07:00</published><updated>2012-05-05T06:18:17.220-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='stored-procedure'/><category scheme='http://www.blogger.com/atom/ns#' term='elevate-db'/><title type='text'>ElevateDB: Stored Procedures Part 4</title><content type='html'>Last time in &lt;a href="http://capecodgunny.blogspot.com/2011/09/elevateddb-stored-procedures-part-3.html"&gt;ElevateDB: Stored Procedures Part 3&lt;/a&gt; I showed you how I went about creating an Amortization schedule that works with Microsoft SQL Server. This took me all of about 35 minutes.&lt;br /&gt;&lt;br /&gt;You may be wondering why I'm writing about SQL code in a Delphi blog and also why I'm writing about Microsoft SQL if this blog series is entitle "ElevateDB: Stored Procedures Part XX". &lt;br /&gt;&lt;br /&gt;Well, the answer is simple... I upgraded from Delphi 5 Enterprise to Delphi 2010 Professional. That in itself is a big jump. Furthermore, I want to create a Delphi database applications that uses an embedded database, and in this case I have chosen to use ElevateDB.&lt;br /&gt;&lt;br /&gt;So, my goal is to create a very simple Delphi program that prints out an Amortization Schedule using Rave Reports that pulls the data from a database.&lt;br /&gt;&lt;br /&gt;Because I'm blogging about how I am going about doing this, sort of creating a Programming Documentary or "Progumentary", wow I just made up a new word. See how this works.&lt;br /&gt;&lt;br /&gt;Do I know how to use Rave Reports that comes with Delphi 2010? No, not yet. But I know if the data is in a database table I can more easily create that Rave Report. &lt;br /&gt;&lt;br /&gt;Have I created the Delphi 2010 VCL form for gathering the data inputs needed? No, but I know I can do this and that part is coming later.&lt;br /&gt;&lt;br /&gt;Do I know how to get the data into an ElevateDB database using a stored procedure? No. But I do know how to get the data into a MS SQL Database using a stored procedure and that is where this &lt;b&gt;Pro-gu-mentary&lt;/b&gt; is right now.&lt;br /&gt;&lt;br /&gt;ElevateDB comes with an ElevateDB Manager, which is a tool similar to Microsoft SQL Server Management Studio. It allows you to create databases, database objects and gives you a very robust query analyzer for performing all the necessary databse tasks.&lt;br /&gt;&lt;br /&gt;I have decided to put all the code logic for creating this amortization schedule inside a stored procedure. This allows me to develop a stand alone module that I can test and measure outside of Delphi. I asked a question on SO about using a proc verus keeping the code in Delphi and received a few interesting responses. (&lt;a href="http://stackoverflow.com/questions/7302324/in-delphi-should-i-use-multiple-database-inserts-from-within-a-loop-or-use-a-stor"&gt;Link to SO Question&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;Because I know I can wire up a few simple controls on a Delphi VCL form and make "One" call to an ElevateDB stored procedure this is time well spent and code that will be used when the time comes.&lt;br /&gt;&lt;br /&gt;So, after 6 plus hours of trying to get a similar stored procedure working in ElevateDB here is what I came up with:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;----------------------------------------------------------------&lt;br /&gt;-- SQL Amortization Schedule&lt;br /&gt;-- Copyright 2011 © By Michael J. Riley&lt;br /&gt;-- www.zilchworks.com&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;CREATE PROCEDURE "spAmortizationSchedule" &lt;br /&gt;(&lt;br /&gt;IN "StartDate" DATE, &lt;br /&gt;IN "Principal" DECIMAL(19,2), &lt;br /&gt;IN "APR" DECIMAL(19,4), &lt;br /&gt;IN "Months" INTEGER&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;BEGIN&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- VARIABLE DECLARATIONS USED FOR PROCESSING&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;DECLARE Payment      decimal(19,2);&lt;br /&gt;DECLARE PaymentLast  decimal(19,2);&lt;br /&gt;DECLARE PmtNumber    int          ;&lt;br /&gt;DECLARE PmtDate      date         ;&lt;br /&gt;DECLARE BalanceStart decimal(19,2);&lt;br /&gt;DECLARE PmtInterest  decimal(19,2);&lt;br /&gt;DECLARE PmtPrincipal decimal(19,2);&lt;br /&gt;DECLARE BalanceEnd   decimal(19,2);&lt;br /&gt;&lt;br /&gt;DECLARE SQLStatement Statement;&lt;br /&gt;DECLARE Result CURSOR WITH RETURN FOR Stmt;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- TEST FOR NULL INPUTS ADD AT SOME POINT&lt;br /&gt;-- PSEUDO-CODE UNTIL I FIGURE OUT HOW TO DO THIS IN ELEVATDB&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;IF StartDate IS NULL THEN SET STARTDATE = Current_Date;&lt;br /&gt;IF Principal IS NULL THEN SET Principal = 190000;&lt;br /&gt;IF APR       IS NULL THEN SET APR       = 3.25;&lt;br /&gt;IF Months    IS NULL THEN SET Months    = 180;&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- EMPTY TABLE FOR NEW USE&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;EXECUTE IMMEDIATE 'EMPTY TABLE "TempAmortization"';&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- CALCULATE MONTHLY PAYMENT BASED ON INPUT PARAMETERS&lt;br /&gt;-- THIS LINE IS LONG AND MAY WRAP MAKING IT HARD TO READ&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET Payment = ROUND(Principal * ((APR/1200)/(1- EXP((Months*-1) * LN(1 + (APR/1200))))) to 2);&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- INITALIZE VARIABLES BEFORE THE LOOP STARTS&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET PmtNumber  = 0         ;&lt;br /&gt;SET BalanceEnd = Principal ;&lt;br /&gt;SET PmtDate = StartDate + INTERVAL '-1' MONTH;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- PERFORM CALCULATIONS FOR ALL BUT LAST MONTH&lt;br /&gt;-- PmtDate column commented out. Need to get the proper syntax.&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;WHILE PmtNumber &amp;lt; Months -1&lt;br /&gt;DO&lt;br /&gt;  &lt;br /&gt;  SET PmtNumber    = PmtNumber +1;&lt;br /&gt;  SET BalanceStart = BalanceEnd;&lt;br /&gt;  SET PmtDate      = PmtDate + INTERVAL '1' MONTH;&lt;br /&gt;  SET PmtInterest  = ROUND(BalanceStart * (APR/1200) to 2);&lt;br /&gt;  SET PmtPrincipal = Payment -  PmtInterest;&lt;br /&gt;  SET BalanceEnd   = BalanceStart -  PmtPrincipal;&lt;br /&gt;&lt;br /&gt;  EXECUTE IMMEDIATE '&lt;br /&gt;  INSERT INTO TempAmortization&lt;br /&gt;  (&lt;br /&gt;  PmtNumber     ,&lt;br /&gt;--  PmtDate       ,&lt;br /&gt;  PmtAmount     ,&lt;br /&gt;  BalanceStart  ,&lt;br /&gt;  PmtPrincipal  ,&lt;br /&gt;  PmtInterest   ,&lt;br /&gt;  BalanceEnd    &lt;br /&gt;  )&lt;br /&gt;  VALUES&lt;br /&gt;  (&lt;br /&gt;  '   + CAST(PmtNumber    as varchar(25)) + '   ,&lt;br /&gt;--  ''' + CAST(PmtDate      as varchar(25)) + ''' ,&lt;br /&gt;  '   + CAST(Payment      as varchar(25)) + '   ,&lt;br /&gt;  '   + CAST(BalanceStart as varchar(25)) + '   ,&lt;br /&gt;  '   + CAST(PmtPrincipal as varchar(25)) + '   ,&lt;br /&gt;  '   + CAST(PmtInterest  as varchar(25)) + '   ,&lt;br /&gt;  '   + CAST(BalanceEnd   as varchar(25)) + '&lt;br /&gt;  )&lt;br /&gt;  ';&lt;br /&gt;&lt;br /&gt;END WHILE;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- PERFORM CALCULATIONS FOR THE LAST MONTH AND&lt;br /&gt;-- PmtDate column commented out. Need to get the proper syntax.&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET PmtNumber    = PmtNumber +1;&lt;br /&gt;SET BalanceStart = BalanceEnd;&lt;br /&gt;SET PmtDate      = PmtDate + INTERVAL '1' MONTH;&lt;br /&gt;SET PmtInterest  = ROUND(BalanceStart * (APR/1200) to 2);&lt;br /&gt;SET PaymentLast  = BalanceStart + PmtInterest;&lt;br /&gt;SET PmtPrincipal = BalanceStart;&lt;br /&gt;SET BalanceEnd   = BalanceStart + PmtInterest - PaymentLast;&lt;br /&gt;&lt;br /&gt;EXECUTE IMMEDIATE '&lt;br /&gt;INSERT INTO TempAmortization&lt;br /&gt;(&lt;br /&gt;PmtNumber     ,&lt;br /&gt;--PmtDate       ,&lt;br /&gt;PmtAmount     ,&lt;br /&gt;BalanceStart  ,&lt;br /&gt;PmtPrincipal  ,&lt;br /&gt;PmtInterest   ,&lt;br /&gt;BalanceEnd&lt;br /&gt;)&lt;br /&gt;VALUES&lt;br /&gt;(&lt;br /&gt;' + CAST(PmtNumber    as varchar(25)) + ' ,&lt;br /&gt;--''' + CAST(PmtDate      as varchar(25)) + ''' ,&lt;br /&gt;' + CAST(PaymentLast  as varchar(25)) + ' ,&lt;br /&gt;' + CAST(BalanceStart as varchar(25)) + ' ,&lt;br /&gt;' + CAST(PmtPrincipal as varchar(25)) + ' ,&lt;br /&gt;' + CAST(PmtInterest  as varchar(25)) + ' ,&lt;br /&gt;' + CAST(BalanceEnd   as varchar(25)) + '&lt;br /&gt;)&lt;br /&gt;';&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- RETURN RESULTS FROM TEMPORARY TABLE&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;PREPARE Stmt FROM &lt;br /&gt;'&lt;br /&gt;SELECT  &lt;br /&gt;PmtNumber     , &lt;br /&gt;PmtDate       , &lt;br /&gt;PmtAmount     , &lt;br /&gt;BalanceStart  ,&lt;br /&gt;PmtPrincipal  ,&lt;br /&gt;PmtInterest   ,&lt;br /&gt;BalanceEnd    &lt;br /&gt;FROM TempAmortization&lt;br /&gt;';&lt;br /&gt;&lt;br /&gt;OPEN Result;&lt;br /&gt;&lt;br /&gt;END&lt;br /&gt;VERSION 1.00!&lt;br /&gt;----------------------------------------------------------------&lt;/pre&gt;It's crude, it works, except for the &lt;span style="color: #cc0000;"&gt;PmtDate column&lt;/span&gt; but at least I knew enough to comment out just that one portion. There are some things I had to do differently from the original MS SSQL Stored Proc: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Had to &lt;b&gt;skip error trapping&lt;/b&gt; the input parameters becaue I don't know how to set default values&lt;/li&gt;&lt;li&gt;Had to used to use a &lt;b&gt;real table&lt;/b&gt; instead of a &lt;b&gt;temp table&lt;/b&gt; because I kept getting errors saying the temp table already exists for this session, bla bla bla&lt;/li&gt;&lt;li&gt;Had to comment out the &lt;b&gt;Payment Date&lt;/b&gt; column because I could not figure out the proper syntax even thought I thought I had worked that out with the &lt;a href="http://capecodgunny.blogspot.com/2011/09/elevatedb-date-math.html"&gt;ElevateDB Date Math&lt;/a&gt; stuff. I'll have to revisit ElevateDB Date Math at a later time&lt;/li&gt;&lt;/ul&gt;A day or two later Tim Young, the guy who created ElevateDB posted this on the support forum... &lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;i&gt;Michael, &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="color: #cc0000;"&gt;&amp;lt;&amp;lt; I'm new to ElevateDB coming from a Microsoft SQL background. Roy suggested I whip up an example of a Microsoft Stored procedure that I'd like to get converted over to ElevateDB and post it to the forum. &amp;gt;&amp;gt; &lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;I know that you've already got this done, but here's an optimal version for EDB: &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;CODE GOES HERE &lt;/i&gt;&lt;br /&gt;&lt;i&gt;(I'll share his code in a future post) &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;How cool is that. I got the guy who created ElevateDB to whip up an &lt;b&gt;&lt;i&gt;optimized version&lt;/i&gt;&lt;/b&gt; of the stored proc I needed. The proc I wrote in MS SQL is filled with little nuggets that can be used over and over again in other stored procs. There's alot going on in there. For example: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Use of defaults for input paramters&lt;/li&gt;&lt;li&gt;Use of temp table for storing temporary data&lt;/li&gt;&lt;li&gt;A date math routine that increments a date by one month&lt;/li&gt;&lt;li&gt;Use of a While loop&lt;/li&gt;&lt;li&gt;Selection of the final result set&lt;/li&gt;&lt;/ul&gt;That's it for now. Gunny Out! &lt;br /&gt;&lt;br /&gt;Semper Fi, &lt;br /&gt;Gunny Mike &lt;br /&gt;&lt;table border="0" style="width: 100px;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td width="50%"&gt;&lt;br /&gt;&lt;a href="http://capecodgunny.blogspot.com/2011/09/elevateddb-stored-procedures-part-3.html"&gt;&amp;lt; Prev&lt;/a&gt;&lt;/td&gt;&lt;td width="50%"&gt;&lt;br /&gt;&lt;a href="http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-5.html"&gt;Next &amp;gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-3777161271523557725?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/3777161271523557725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-4.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/3777161271523557725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/3777161271523557725'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-4.html' title='ElevateDB: Stored Procedures Part 4'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-1526779336250625373</id><published>2011-09-06T18:26:00.000-07:00</published><updated>2012-05-05T06:19:46.960-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='stored-procedure'/><category scheme='http://www.blogger.com/atom/ns#' term='elevate-db'/><title type='text'>ElevateDB: Stored Procedures Part 3</title><content type='html'>In my last &lt;a href="http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-2.html"&gt;ElevateDB Stored Procedure post&lt;/a&gt; I went on a rant about how frustrating my stored procedure journey became. Well, today is a new day and I feel better. A few more posts were added to the &lt;a href="http://www.elevatesoft.com/forums?action=view&amp;amp;category=edb&amp;amp;id=edb_sql&amp;amp;msg=4832&amp;amp;page=1"&gt;support thread&lt;/a&gt; I started with one really good one by the Tim Young the creator of ElevateDB. &lt;br /&gt;&lt;br /&gt;The stored proc I was attempting to create is a fairly simple "&lt;b&gt;Amortization Schedule&lt;/b&gt;". So here is how you go about building an Amortization Schedule from scratch. &lt;br /&gt;&lt;br /&gt;Because I'm an old school programmer here's my very simple method of deciding how to do just about every programming task:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Gunny's Rules&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;1. Identify the output&lt;/li&gt;&lt;li&gt;2. Identify the inputs&lt;/li&gt;&lt;li&gt;3. Ask ====&amp;gt; Are there enough inputs to create that output?&lt;/li&gt;&lt;/ul&gt;If the answer is &lt;b&gt;NO&lt;/b&gt; there are not enough inputs to create that output, then go get the necessary inputs. It's a waste of time to begin writing code until you have all the inputs. If you spend a little time now ironing out these details you will save tons of time later.&lt;br /&gt;&lt;br /&gt;This is really bone simple but it works. Or as I used to say to my Major... "&lt;b&gt;It's Gump Proof&lt;i&gt;&lt;/i&gt;&lt;/b&gt;" (Yeah I know I'm a Marine but it's still a cool saying. Calling something Gomer Proof doesn't have the same meaning.)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Identify The Output:&lt;/b&gt;&lt;br /&gt;A database table that contains payment information for each monthly payment in an Amortization Schedule. To be more specific:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Payment Number&lt;/li&gt;&lt;li&gt;Payment Date&lt;/li&gt;&lt;li&gt;Balance Before Payment&lt;/li&gt;&lt;li&gt;Payment Amount&lt;/li&gt;&lt;li&gt;Principal Portion of Payment&lt;/li&gt;&lt;li&gt;Interest Portion or Payment&lt;/li&gt;&lt;li&gt;Balance After Payment&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Identify The Inputs:&lt;/b&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Payment Start Date&lt;/li&gt;&lt;li&gt;Loan Amount&lt;/li&gt;&lt;li&gt;Annual Percentage Rate (APR)&lt;/li&gt;&lt;li&gt;Length of Loan in Months&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Ask ====&amp;gt; Are there enough inputs to create that output?&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Answer: No.&lt;/b&gt; I need the payment amount. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Decision Time:&lt;/b&gt; Okay, there are two choices at this point. &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Ask for this value to be supplied just like the other values&lt;/li&gt;&lt;li&gt;Calculate the payment based on the existing input values&lt;/li&gt;&lt;/ul&gt;I decide to calculate the payment. So now I need a loan payment formula. Let's assume I know where to get one of these. The major point is I identified an additional input was needed - &lt;b&gt;A Formula&lt;/b&gt;. My list of inputs now looks like this: &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Identify The Inputs:&lt;/b&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Payment Start Date&lt;/li&gt;&lt;li&gt;Loan Amount&lt;/li&gt;&lt;li&gt;Annual Percentage Rate (APR)&lt;/li&gt;&lt;li&gt;Length of Loan in Months&lt;/li&gt;&lt;li&gt;&lt;span style="color: #c90000;"&gt;Loan Payment Formula&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Ask ====&amp;gt; Are there enough inputs to create that output?&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Answer: No.&lt;/b&gt; I need two more bits of information. &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Another formula for calculating the Interest Portion of the payment&lt;/li&gt;&lt;li&gt;A method for advancing the Payment Date by one month&lt;/li&gt;&lt;/ul&gt;No problem. That formula is pretty straigh forward and most SQL languages support Date Math. I'm good at this point. Let's have another look at the list of inputs. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Identify The Inputs:&lt;/b&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Payment Start Date&lt;/li&gt;&lt;li&gt;Loan Amount&lt;/li&gt;&lt;li&gt;Annual Percentage Rate (APR)&lt;/li&gt;&lt;li&gt;Length of Loan in Months&lt;/li&gt;&lt;li&gt;Loan Payment Formula&lt;/li&gt;&lt;li&gt;Interest Payment Formula&lt;/li&gt;&lt;li&gt;Date Math Routine&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Ask ====&amp;gt; Are there enough inputs to create that output?&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Answer: Yes&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;That is Gunny's simple Gump Proof way of gathering requirements. Here is a Microsoft SQL Server version of the stored procedure. Next time I will show you my working but lame attempt at creating the same amortization stored procedure using ElevateDB. Enjoy!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;----------------------------------------------------------------&lt;br /&gt;-- SQL Amortization Schedule&lt;br /&gt;-- Copyright 2011 © By Michael J. Riley&lt;br /&gt;-- www.zilchworks.com&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;CREATE PROCEDURE [dbo].[spAmortizationSchedule] &lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- INPUT PARAMETERS WITH DEFAULT VALUES&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;@StartDate  datetime      = '2011-09-15' ,&lt;br /&gt;@Principal  decimal(19,2) = 195000       ,&lt;br /&gt;@APR        decimal(19,4) = 3.25         ,&lt;br /&gt;@Months     integer       = 180&lt;br /&gt;&lt;br /&gt;AS&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- VARIABLE DECLARATIONS USED FOR PROCESSING&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;DECLARE @Payment      decimal(19,2)&lt;br /&gt;DECLARE @PaymentLast  decimal(19,2)&lt;br /&gt;DECLARE @PmtNumber    int&lt;br /&gt;DECLARE @PmtDate      date&lt;br /&gt;DECLARE @BalanceStart decimal(19,2)&lt;br /&gt;DECLARE @PmtInterest  decimal(19,2)&lt;br /&gt;DECLARE @PmtPrincipal decimal(19,2)&lt;br /&gt;DECLARE @BalanceEnd   decimal(19,2)&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- TEMP TABLE TO HOLD AMORTIZATION OUTPUT&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;CREATE TABLE #TempAmortization&lt;br /&gt;(&lt;br /&gt;PmtNumber    int           , &lt;br /&gt;PmtDate      date          , &lt;br /&gt;PmtAmount    decimal(19,2) , &lt;br /&gt;BalanceStart decimal(19,2) ,&lt;br /&gt;PmtPrincipal decimal(19,2) ,&lt;br /&gt;PmtInterest  decimal(19,2) ,&lt;br /&gt;BalanceEnd   decimal(19,2) &lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- CALCULATE MONTHLY PAYMENT BASED ON INPUT PARAMETERS&lt;br /&gt;-- This line may wrap and be hard to read&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET @Payment = ROUND(@Principal * ((@APR/1200)/(1- EXP((@Months*-1) *&lt;br /&gt;LOG(1 + (@APR/1200))))),2)&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- INITALIZE VARIABLES BEFORE THE LOOP STARTS&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET @PmtNumber  = 0&lt;br /&gt;SET @BalanceEnd = @Principal&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- PERFORM CALCULATIONS FOR ALL BUT LAST MONTH AND&lt;br /&gt;-- STORE RESULTS IN TEMPORARY TABLE&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;WHILE @PmtNumber &lt; @Months -1&lt;br /&gt;BEGIN&lt;br /&gt; &lt;br /&gt; SET @PmtNumber    = @PmtNumber +1&lt;br /&gt; SET @BalanceStart = @BalanceEnd&lt;br /&gt; SET @PmtDate      = DATEADD(m, @PmtNumber-1, @StartDate)&lt;br /&gt; SET @PmtInterest  = ROUND(@BalanceStart *(@APR/1200) ,2)&lt;br /&gt; SET @PmtPrincipal = @Payment - @PmtInterest&lt;br /&gt; SET @BalanceEnd   = @BalanceStart - @PmtPrincipal&lt;br /&gt;&lt;br /&gt; INSERT INTO #TempAmortization&lt;br /&gt; (&lt;br /&gt; PmtNumber     , &lt;br /&gt; PmtDate       , &lt;br /&gt; PmtAmount     , &lt;br /&gt; BalanceStart  ,&lt;br /&gt; PmtPrincipal  ,&lt;br /&gt; PmtInterest   ,&lt;br /&gt; BalanceEnd    &lt;br /&gt; )&lt;br /&gt; VALUES&lt;br /&gt; (&lt;br /&gt; @PmtNumber     , &lt;br /&gt; @PmtDate       ,  &lt;br /&gt; @Payment       ,&lt;br /&gt; @BalanceStart  ,&lt;br /&gt; @PmtPrincipal  ,&lt;br /&gt; @PmtInterest   ,&lt;br /&gt; @BalanceEnd    &lt;br /&gt; )&lt;br /&gt; &lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- PERFORM CALCULATIONS FOR THE LAST MONTH AND&lt;br /&gt;-- STORE RESULTS IN TEMPORARY TABLE&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SET @PmtNumber    = @PmtNumber +1&lt;br /&gt;SET @BalanceStart = @BalanceEnd&lt;br /&gt;SET @PmtDate      = DATEADD(m, @PmtNumber-1, @StartDate )&lt;br /&gt;SET @PmtInterest  = ROUND(@BalanceStart *(@APR/1200) ,2)&lt;br /&gt;SET @PaymentLast  = @BalanceStart + @PmtInterest&lt;br /&gt;SET @PmtPrincipal = @BalanceStart&lt;br /&gt;SET @BalanceEnd   = @BalanceStart + @PmtInterest - @PaymentLast&lt;br /&gt;&lt;br /&gt;INSERT INTO #TempAmortization&lt;br /&gt;(&lt;br /&gt;PmtNumber     , &lt;br /&gt;PmtDate       , &lt;br /&gt;PmtAmount     , &lt;br /&gt;BalanceStart  ,&lt;br /&gt;PmtPrincipal  ,&lt;br /&gt;PmtInterest   ,&lt;br /&gt;BalanceEnd    &lt;br /&gt;)&lt;br /&gt;VALUES&lt;br /&gt;(&lt;br /&gt;@PmtNumber     , &lt;br /&gt;@PmtDate       ,  &lt;br /&gt;@PaymentLast   ,&lt;br /&gt;@BalanceStart  ,&lt;br /&gt;@PmtPrincipal  ,&lt;br /&gt;@PmtInterest   ,&lt;br /&gt;@BalanceEnd    &lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- RETURN RESULTS FROM TEMPORARY TABLE&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;SELECT  &lt;br /&gt;PmtNumber     , &lt;br /&gt;PmtDate       , &lt;br /&gt;PmtAmount     , &lt;br /&gt;BalanceStart  ,&lt;br /&gt;PmtPrincipal  ,&lt;br /&gt;PmtInterest   ,&lt;br /&gt;BalanceEnd    &lt;br /&gt;FROM #TempAmortization&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;-- HOUSEKEEPING&lt;br /&gt;----------------------------------------------------------------&lt;br /&gt;DROP TABLE #TempAmortization&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;  Semper Fi, Gunny Mike &lt;table border="0" style="width: 100px;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td width="50%"&gt;&lt;br /&gt;&lt;a href="http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-2.html"&gt;&amp;lt; Prev&lt;/a&gt;&lt;/td&gt;&lt;td width="50%"&gt;&lt;br /&gt;&lt;a href="http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-4.html"&gt;Next &amp;gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-1526779336250625373?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/1526779336250625373/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevateddb-stored-procedures-part-3.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/1526779336250625373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/1526779336250625373'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevateddb-stored-procedures-part-3.html' title='ElevateDB: Stored Procedures Part 3'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-2733920408680352273</id><published>2011-09-05T21:06:00.000-07:00</published><updated>2012-05-05T06:20:00.185-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='stored-procedure'/><category scheme='http://www.blogger.com/atom/ns#' term='elevate-db'/><title type='text'>ElevateDB: Stored Procedures Part 2</title><content type='html'>In &lt;a href="http://capecodgunny.blogspot.com/2011/09/elevatedb-part-1.html"&gt;ElevateDB: Stored Procedures Part 1&lt;/a&gt; I talked about my first attempt at making a stored procedure in ElevateDB. Well today was an interesting day. I wanted to make it my goal to successfully create a non-trivial Stored Procedure using ElevateDB. I finally did but what a adventure. WTF! I mean WTFO! (I'm military the 'O' stands for Over)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Goal: Develope A Stored Procedure That Creates An Amortization Schedule&lt;/b&gt;I'll share my ElevateDB Amortization Proc with you on an upcoming post.&lt;br /&gt;&lt;br /&gt;BTW, I purchased ElevateDB last week and technically it comes with a 30 day money back guarantee. At one point today I was so pissed off I kept thinking in my head "Yeah, if I can't get this to work I'm asking for a refund."&lt;br /&gt;&lt;br /&gt;Anyway, one of the "Team Elevate" support forum members responded to one of my posts about how simple it would be to whip this up in MS SQL Server and how difficult it is to do using ElevateDB. He suggested I create a proc using MS SQL and post it to the forum asking others members to help me convert it to ElevateDB parlance. Wow, that sounded like a great idea. &lt;br /&gt;&lt;br /&gt;I'm sure there are several other Delphi programmers out there with a Microsoft SQL background looking for an embedded database solution that does not rely on Microsoft and their "Database Driver DLL Hell". &lt;br /&gt;&lt;br /&gt;So I spent about 35 minutes whipping up a proc that does this. Here is the link to a the &lt;a href="http://www.elevatesoft.com/forums?action=view&amp;amp;category=edb&amp;amp;id=edb_sql&amp;amp;page=1&amp;amp;msg=4832#4832"&gt;MS SQL Server spAmortizationSchedule&lt;/a&gt; I wrote.&lt;br /&gt;&lt;br /&gt;After I posted this thing I immediately felt like a high school kid asking a support forum to help him with his homework. I had one forum user respond to my post. He basically asked me "What happens when you try to convert this yourself." Besides him, nothing. He didn't know I felt like I was asking the Internet to do my homework for me.&lt;br /&gt;&lt;br /&gt;Anyway, I rolled up my sleeves and started to convert this over to ElevateDB on my own. For the life of me, I could not get passed the mental block I developed over the use of cursors, dynamic SQL and prepared statements. If another person tells me to RTFM I don't know what I'd do.&lt;br /&gt;&lt;br /&gt;I have been pouring over the manuals and digging through the code scattered throughout the support forums. Do you think I could find an example similar to what I was trying to accomplish? No!&lt;br /&gt;&lt;br /&gt;Take in a few parameters&lt;br /&gt;Create a temp table to store the results&lt;br /&gt;While not done ...&lt;br /&gt;Calculate the values &lt;br /&gt;Insert them into the temp table&lt;br /&gt;Return the record set&lt;br /&gt;Drop the temp table&lt;br /&gt;&lt;br /&gt;There is nothing like this. Not in the manuals. Not in the support posts. No where. All I needed was some small little nudge "Hey Gunny, don't do that do this instead. And don't use that use this instead." Did I get that... No. Not Just No But F-No.&lt;br /&gt;&lt;br /&gt;Wow, I'm starting to feel better already. That is why I'm blogging about it here. &lt;br /&gt;&lt;ul&gt;&lt;li&gt;First, so I have a reference I can look back on when I forget how I did something. &lt;/li&gt;&lt;li&gt;Secondly, for any other poor soul who happens to stumble across this stuff looking for answers to questions like...I do this in MS SQL how do I do this in ElevateDB. &lt;/li&gt;&lt;/ul&gt;I love ElevateDB I really do, but until you fully wrap your head around the differences between MS SQL it's frustrating. Who know's maybe I'll have enough shit on this blog I could put it in a book.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;This Gunny is worn out. Goodnight y'all.&lt;br /&gt;&lt;br /&gt;Semper Fi,&lt;br /&gt;Gunny Mike&lt;br /&gt;&lt;table width="100" border="0"&gt;&lt;tr&gt; &lt;td width="50%"&gt;&lt;br /&gt;&lt;a href="http://capecodgunny.blogspot.com/2011/09/elevatedb-part-1.html"&gt;&amp;lt; Prev&lt;/a&gt;&lt;br /&gt;&lt;/td&gt; &lt;td width="50%"&gt;&lt;br /&gt;&lt;a href="http://capecodgunny.blogspot.com/2011/09/elevateddb-stored-procedures-part-3.html"&gt;Next &amp;gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-2733920408680352273?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/2733920408680352273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/2733920408680352273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/2733920408680352273'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-2.html' title='ElevateDB: Stored Procedures Part 2'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-6524820985930557049</id><published>2011-09-05T05:36:00.000-07:00</published><updated>2012-05-05T06:19:25.113-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='elevate-db'/><category scheme='http://www.blogger.com/atom/ns#' term='sql-nugget'/><title type='text'>ElevateDB: Select TOP Equivelent</title><content type='html'>In my previous post &lt;a href="http://capecodgunny.blogspot.com/2011/09/elevatedb-date-math.html"&gt;ElevateDB: Date Math&lt;/a&gt;&amp;nbsp;I discussed how to select internal constants and literals from within the ElevateDB Manager using a dummy table.&lt;br /&gt;&lt;br /&gt;Well the ElevateDB boys have spoken and you do not need to create a dummy table to perfom this type of query. You can simply go against the &lt;strong&gt;information.tables.&lt;/strong&gt; (I'll have to read up on these guys).&lt;br /&gt;&lt;br /&gt;Anyway here is the suggested way to run the same query without using my dummy table approach:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;select &lt;br /&gt;current_date as today &lt;br /&gt;from information.tables&lt;/code&gt;&lt;/pre&gt;This works great except it returns four rows in my environment. So, naturally the next question is how do you limit the results to produce only one row.&lt;br /&gt;&lt;br /&gt;From MS SQL Query Analyzer you just use the keyword TOP 1. In EDB it's slightly different:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;select &lt;br /&gt;current_date as today &lt;br /&gt;from information.tables &lt;br /&gt;range 1 to 1&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Semper Fi&lt;br /&gt;Gunny Mike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-6524820985930557049?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/6524820985930557049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatedb-select-top-1-equivelent.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/6524820985930557049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/6524820985930557049'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatedb-select-top-1-equivelent.html' title='ElevateDB: Select TOP Equivelent'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-6470085969413278830</id><published>2011-09-04T20:12:00.000-07:00</published><updated>2012-05-05T05:46:36.372-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='date-stuff'/><category scheme='http://www.blogger.com/atom/ns#' term='elevate-db'/><title type='text'>ElevateDB: Date Math 1</title><content type='html'>ElevateDB has just impressed me again the way it handles date math. I don't know if you have ever tried doing SQL Date Math but it can be tricky unless there is built in support.&lt;br /&gt;&lt;br /&gt;Often times you need to add a Day or a Month or a Year to a given date. ElevateDB lets you do this and it works well.&lt;br /&gt;&lt;br /&gt;I opened up a new SQL Window inside EDB Manager and tried executing the following:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;SELECT&lt;br /&gt;Current_Date as Today&lt;/code&gt;&lt;/pre&gt;I received an Error:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: #990000;"&gt;ElevateDB Error #700 An error was found in the statement at line 3 and column 1 (Missing FROM)&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;So I created a dummy table with one field and one record. Then I modified my original SQL as follows...&lt;br /&gt;&lt;pre&gt;&lt;code&gt;SELECT&lt;br /&gt;Current_Date as Today,&lt;br /&gt;FROM dummy&lt;/code&gt;&lt;/pre&gt;and it works great. Even though I'm not returning any real data from the "dummy" table.&lt;br /&gt;&lt;br /&gt;Being inquisitive and wanting to see how well ElevateDB does "Date Math" I tried the following...&lt;br /&gt;&lt;pre&gt;&lt;code&gt;SELECT&lt;br /&gt;Current_Date + INTERVAL '-4' DAY AS FourDaysAgo,&lt;br /&gt;Current_Date + INTERVAL '-3' DAY AS ThreeDaysAgo,&lt;br /&gt;Current_Date + INTERVAL '-2' DAY AS TwoDaysAgo,&lt;br /&gt;Current_Date + INTERVAL '-1' DAY AS OneDayAgo,&lt;br /&gt;Current_Date as Today,&lt;br /&gt;Current_Date + INTERVAL '1' DAY AS OneDayFromNow,&lt;br /&gt;Current_Date + INTERVAL '2' DAY AS TwoDaysFromNow,&lt;br /&gt;Current_Date + INTERVAL '3' DAY AS ThreeDaysFromNow,&lt;br /&gt;Current_Date + INTERVAL '4' DAY AS FourDaysFromNow&lt;br /&gt;FROM dummy&lt;/code&gt;&lt;/pre&gt;and it works &lt;b&gt;AWESOME&lt;/b&gt;. I tested going backwards until one day before March 1, 2011 testing leap year. I tested going forward until one day after Feb 28, 2012. I tested December 31st plus 1 Day and Jan 1st minus 1 Day. It's all good. &lt;br /&gt;&lt;br /&gt;Now I know that using a dummy table this way probably isn't considered EDB best practices but it did allow me to get the information I was looking for. This method also works for selecting literal values. &lt;br /&gt;&lt;br /&gt;I'm waiting to hear back from the ElevateDB boys on the proper way to return this kind of data but until then, I have a working model.&lt;br /&gt;&lt;br /&gt;Semper Fi&lt;br /&gt;Gunny Mike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-6470085969413278830?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/6470085969413278830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatedb-date-math.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/6470085969413278830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/6470085969413278830'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatedb-date-math.html' title='ElevateDB: Date Math 1'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-8541796286814746065</id><published>2011-09-04T16:10:00.000-07:00</published><updated>2012-05-05T06:20:15.333-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='stored-procedure'/><category scheme='http://www.blogger.com/atom/ns#' term='elevate-db'/><title type='text'>ElevateDB: Stored Procedures Part 1</title><content type='html'>Okay, so I finally decided to shit or get off the pot and I purchased ElevateDB last week. The GUI tool is great very user friendly. I created a couple tables and populated them. I used the reverse engineer tool to see what that does. It would be nice if the reverse engineer tool would let you pick just one table. (&lt;a href="http://www.elevatesoft.com/forums?action=view&amp;amp;category=edb&amp;amp;id=edb_suggestions&amp;amp;page=1&amp;amp;msg=245#245"&gt;Submited a wish list comment on the support forum&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;I'm commited to making ElevateDB work inside my Delphi applications. So, one of the first things I tried doing was creating a simple stored procedure to select all of the data from one of the tables. Easy enough right... wrong.&lt;br /&gt;&lt;br /&gt;I've been using stored procedures inside of Microsoft SQL for the past 12 years. So I created what I thought was a pretty straight forward stored procedure:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;CREATE PROCEDURE "spSelectStrategies" ()&lt;br /&gt;BEGIN&lt;br /&gt;SELECT&lt;br /&gt;StrategyId,&lt;br /&gt;Strategy,&lt;br /&gt;Hint&lt;br /&gt;FROM tblStrategies&lt;br /&gt;ORDER BY Sort&lt;br /&gt;END&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Nope. This gave me the following error:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: #990000;"&gt;ElevateDB Error #700 An error was found in the statement at line 4 and column 1 (Expected : but instead found StrategyId)&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I sped off to make my first post on ElevateDB's support forum. This is place where users help users. Besides being told my use of a stored procedure was a trivial use of a stored procedure I was given the correct syntax for &lt;a href="http://www.elevatesoft.com/forums?action=view&amp;amp;category=edb&amp;amp;id=edb_sql&amp;amp;page=1&amp;amp;msg=4800#4800"&gt;how an ElevateDB stored procedure should look&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;CREATE PROCEDURE "spSelectStrategies" ()&lt;br /&gt;BEGIN&lt;br /&gt;DECLARE procCur CURSOR WITH RETURN FOR procStmt;&lt;br /&gt;&lt;br /&gt;PREPARE procStmt FROM &lt;br /&gt;'&lt;br /&gt;SELECT &lt;br /&gt;StrategyId,&lt;br /&gt;Strategy,&lt;br /&gt;Hint &lt;br /&gt;FROM tblStrategies &lt;br /&gt;ORDER BY Sort&lt;br /&gt;';&lt;br /&gt;&lt;br /&gt;OPEN procCur;&lt;br /&gt;END&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The whitespace is not necessary, that's all me. I tend to use a lot of white space in my code. I know I'm anal when it comes to certain things. Anyway, it turns out that ALL stored procedures within &lt;b&gt;ElevateDB &lt;/b&gt;act on &lt;b&gt;Dynamic SQL&lt;/b&gt;. In order to get a dataset returned you need to &lt;br /&gt;&lt;pre&gt;&lt;code&gt;DECLARE a CURSOR;&lt;br /&gt;PREPARE a statement;&lt;br /&gt;OPEN the CURSOR&lt;/code&gt;&lt;/pre&gt;It's going to take me a little while to wrap my SQL Head around to the ElevateDB way of thinking. Stay tuned as I learn more about ElevateDB.&lt;br /&gt;&lt;br /&gt;Semper Fi,&lt;br /&gt;Gunny Mike&lt;br /&gt;&lt;table width="100" border="0"&gt;&lt;tr&gt; &lt;td width="50%"&gt;&amp;nbsp;&lt;/td&gt; &lt;td width="50%"&gt;&lt;br /&gt;&lt;a href="http://capecodgunny.blogspot.com/2011/09/elevatedb-stored-procedures-part-2.html"&gt;Next &amp;gt;&lt;/a&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-8541796286814746065?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/8541796286814746065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatedb-part-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/8541796286814746065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/8541796286814746065'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2011/09/elevatedb-part-1.html' title='ElevateDB: Stored Procedures Part 1'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-750365529065397723</id><published>2011-08-27T14:10:00.000-07:00</published><updated>2011-09-08T18:46:27.576-07:00</updated><title type='text'>Making a ClientDataSet Talk to an MS Access Database 1</title><content type='html'>I purchased Cary Jensen's book called &lt;a href="http://www.jensendatasystems.com/cdsbook/"&gt;Delphi in Depth: ClientDataSets&lt;/a&gt; a couple weeks ago. It's a great book filled with lots of nuggets. You can only read so much before you need to practice by doing. All of Cary's examples use the DBDEMOS database that comes with Delphi.&lt;br /&gt;&lt;br /&gt;So, I have decided to port these examples over so they talk to a MS Access database. I figure this is a great way to learn. For me this is a pain-stakingly slow process, because I want to learn (I mean really learn) how to do this well. &lt;br /&gt;&lt;br /&gt;I have&amp;nbsp;just gotten to page 53&amp;nbsp;of&amp;nbsp;Chapter 3 and decided to blog about what I've done so far. &lt;br /&gt;&lt;br /&gt;I substituted the &lt;strong&gt;BDE.TTable&lt;/strong&gt; for a &lt;strong&gt;dbGo.TADOTable&lt;/strong&gt;. I also had to use a &lt;strong&gt;dbGo.TADOConnection&lt;/strong&gt;. The &lt;strong&gt;TADOConnection&lt;/strong&gt; comes with a built in &lt;strong&gt;Connection String Builder&lt;/strong&gt; which works very well.&lt;br /&gt;&lt;br /&gt;Anyway, here's where the chicken and the egg thing come into play. In order for this to work you need an MS Access database. So, I created a very simple database using different table names from the DBDEMOS so I can learn how to wire everything up properly.&lt;br /&gt;&lt;br /&gt;I set set the &lt;strong&gt;TADOConnection.Connected&lt;/strong&gt; property to true so I can see stuff happening in the IDE. I decided to add a couple more tables to my MS Access database. With my project loaded in the IDE I attempted to open my MS Access database by doubl-clicking on the mdb file... Well, my computer hung. I had to do a hard reboot. Keep this in mind if you go back and forth between Delphi and MS Access.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Another thing that was weird. I tried applying the updates &lt;strong&gt;ClientDataSet1.ApplyUpdates(-1);&lt;/strong&gt; and I got the following error:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-nwdT5Nu-EWE/TllaVPclGgI/AAAAAAAAAB0/NuEBPMp1O3E/s1600/ResolverOffError.jpg" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="101px" qaa="true" src="http://2.bp.blogspot.com/-nwdT5Nu-EWE/TllaVPclGgI/AAAAAAAAAB0/NuEBPMp1O3E/s400/ResolverOffError.jpg" width="400px" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So, again Jensen to the rescue. On page 52 he talks about using the &lt;strong&gt;&lt;em&gt;ResolveToDataSet&lt;/em&gt;&lt;/strong&gt; property of the DataSetProvider component. I set this property to &lt;strong&gt;&lt;em&gt;True&lt;/em&gt;&lt;/strong&gt; and now my updates from with my Delphi application are showing up in the MS Access database.&lt;br /&gt;&lt;br /&gt;I'm off to learn some more. I'll share anything that's good to know along the way.&lt;br /&gt;&lt;br /&gt;Semper Fi&lt;br /&gt;Gunny Mike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-750365529065397723?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/750365529065397723/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2011/08/making-clientdataset-talk-to-ms-access.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/750365529065397723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/750365529065397723'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2011/08/making-clientdataset-talk-to-ms-access.html' title='Making a ClientDataSet Talk to an MS Access Database 1'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-nwdT5Nu-EWE/TllaVPclGgI/AAAAAAAAAB0/NuEBPMp1O3E/s72-c/ResolverOffError.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-6056187782172205948</id><published>2011-08-24T04:28:00.000-07:00</published><updated>2012-05-05T05:55:54.212-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='musings'/><title type='text'>I Took A Little Walk-About - But I'm Back</title><content type='html'>A lot has been going on inside my head since the last post. Delphi has just released XE2. I have finally decided to use ElevateDB for all my Delphi applications. &lt;b&gt;&lt;i&gt;I needed to shit or get off the pot&lt;/i&gt;&lt;/b&gt; on&amp;nbsp;making a decision about&amp;nbsp;which database to use.&lt;br /&gt;&lt;br /&gt;My apps are not that complicated. They are for single user interaction. I originally thought of using MS Access and then ruled that out. Then I toiled with the idea of using some version of MS SQL Server and after careful reading found out that too much stuff has to be configured on the users machine.&lt;br /&gt;&lt;br /&gt;I want a simple install, no complicated hunt and grab driver xxx from location yyy followed by asking some weird little question like "did you want to leave the current setting in place". When you sell a $40 app one sales call chews up the rest of the profit.&lt;br /&gt;&lt;br /&gt;Anyway, I pursued the idea of using Firebird 2.5 and spent quite a bit of time learning about all the third party vendors who sell Firebird drivers because my Delphi 2010 Professional doesn't come with a DBExpress driver for Firebird. Along the way I learned about the great Delphi community on Stack Overflow (&lt;a href="http://stackoverflow.com/"&gt;http://stackoverflow.com/&lt;/a&gt;). I also learned how even though Firebird is free, if you want really good help from the people in the know, it will cost you.&lt;br /&gt;&lt;br /&gt;So, I said all that to say this... I'm going to use ElevateDB from &lt;a href="http://www.elevatesoft.com/"&gt;http://www.elevatesoft.com/&lt;/a&gt;. It's 100% written in Delphi. I'm a small ISV and so is Elevate. The documentation is fantastic. I don't have to pay per incident for answers from people in the know. There is an annual maintenance fee but that's to be expected.&lt;br /&gt;&lt;br /&gt;If I could point to one thing that pushed me over the edge in my decision... the demo project used a&amp;nbsp;&lt;i&gt;&lt;b&gt;Delphi "Data Module"&lt;/b&gt;&lt;/i&gt; to consolidate all the db stuff in one location. I never heard of a TDataModule until yesterday and it came from Tim Young at ElevateSoft. Thank you Tim.&lt;br /&gt;&lt;br /&gt;How come Wharton, Biorre and all the others pushing Firebird didn't mention this? Answer they are too busy staring in the mirror they didn't see the big picture.&lt;br /&gt;&lt;br /&gt;Semper Fi - Gunny Mike&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-6056187782172205948?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/6056187782172205948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2011/08/i-took-little-walk-about-but-im-back.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/6056187782172205948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/6056187782172205948'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2011/08/i-took-little-walk-about-but-im-back.html' title='I Took A Little Walk-About - But I&apos;m Back'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-5617932113805299178</id><published>2010-02-03T17:29:00.000-08:00</published><updated>2012-05-05T06:22:15.815-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='musings'/><title type='text'>On Again Off Again On Again</title><content type='html'>There's an awful lot to do when you are a one-person, part-time Micro ISV. I purchased Delphi 2010 in November 2009 because I didn't want to miss out on the opportunity to upgrade from Delphi 5 Enterprise. I got excited about Delphi and writing code. I purchased several books so I would have a good source to rely on as I move from D5E to D2010. Then the excitement went away.&lt;br /&gt;&lt;br /&gt;I have decided that I will alternate on a monthly basis between writing code and marketing. I have also decided that during the marketing phase I will reflect on what I did right in the past and what I did wrong in the past and share those insights here so other OPPTMISV's can learn from them.&lt;br /&gt;&lt;br /&gt;So, this is the marketing month and so far I have done quite a few things already. &lt;br /&gt;&lt;ol&gt;&lt;li&gt;I added socializing links to all the pages on my web site. I decided to use the Add This social scheme. Here is a link to their web site. &lt;a href="http://www.addthis.com/"&gt;http://www.addthis.com/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;I also created a business page on facebook and added a "Find Us On Facebook" link to all the pages on my web site. Check it out for your self. &lt;a href="http://www.zilchworks.com/"&gt;http://www.zilchworks.com/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;I created a new section on my web site called "In The News". This will be dedicated to any and all news related articles about my software. &lt;a href="http://www.zilchworks.com/inthenews/"&gt;http://www.zilchworks.com/inthenews/&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;I need to focus on "Righting a Wrong".For two plus years, a company has been using illegal copies of my software to fraud people. My name has been dragged through the mud by this guy. I'm trying to figure out how to take this wrong and make something good out of it.&lt;br /&gt;&lt;br /&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;I also am forging strong affiliate relationships. I will not inundate my customers with overloaded links to other peoples products which I am affiliated. I want high quality products with special discounts that only I can give. This is my service after the sale.&lt;br /&gt;&lt;br /&gt;Semper Fi - Gunny Mike&lt;/div&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-5617932113805299178?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/5617932113805299178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2010/02/on-again-off-again-on-again.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/5617932113805299178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/5617932113805299178'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2010/02/on-again-off-again-on-again.html' title='On Again Off Again On Again'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-7554508225210733871</id><published>2009-12-19T07:33:00.000-08:00</published><updated>2012-05-05T06:16:27.216-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='musings'/><title type='text'>Experience Delphi Again For The First Time</title><content type='html'>Granted it's been quite a while since I compiled my last verion of real Delphi code. I just looked at the release date for my last retail product, 02/28/2004. Has it really been that long. Unbelievable.&lt;br /&gt;&lt;br /&gt;I purchased Delphi 2010 in November 2009 for a few reasons:&lt;br /&gt;&lt;br /&gt;Embarcadero allows the upgrade price for any version until 12/31/2009.&lt;br /&gt;I need to bring my products up to date (no more 640 X 480 windows) etc.&lt;br /&gt;I'm no longer burnt out from writing other people's code.&lt;br /&gt;&lt;br /&gt;So, I've concluded that I've learned quite a bit in the almost six years that I haven't written any Delphi code. Translation, I've made several hundred mistakes and have become more seasoned at my craft. Anyway, I didn't stop coding, I jumped into heavy duty web development using classic ASP and Microsoft SQL.&lt;br /&gt;&lt;br /&gt;I've decided to "&lt;strong&gt;&lt;em&gt;Experience Delphi Again For The First Time&lt;/em&gt;&lt;/strong&gt;". Oh yeah a lot has changed and if I was to do it all over again (wait a minute that's what I'm doing) I'd still pick Delphi but I'd learn... I mean really learn what I should have learned the first time. I started by compiling a list of bookmarks that include:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Stackoverflow&lt;/strong&gt; (&lt;a href="http://stackoverflow.com/"&gt;http://stackoverflow.com/&lt;/a&gt;)&lt;br /&gt;&lt;strong&gt;Delphi About&lt;/strong&gt; (&lt;a href="http://delphi.about.com/"&gt;http://delphi.about.com/&lt;/a&gt;)&lt;br /&gt;&lt;strong&gt;Code Central&lt;/strong&gt; (&lt;a href="http://cc.embarcadero.com/"&gt;http://cc.embarcadero.com/&lt;/a&gt;)&lt;br /&gt;&lt;strong&gt;Delphi Feeds&lt;/strong&gt; (&lt;a href="http://www.delphifeeds.com/"&gt;http://www.delphifeeds.com/&lt;/a&gt;)&lt;br /&gt;&lt;strong&gt;Marco Cantù&lt;/strong&gt; (&lt;a href="http://www.marcocantu.com/"&gt;http://www.marcocantu.com/&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I've also started accumulating a new set of books to compliment the other 24 Delphi/Pascal books I already have laying around. Of my old books "&lt;em&gt;&lt;strong&gt;Complete Turbo Pascal Third Edition&lt;/strong&gt;&lt;/em&gt;" by &lt;strong&gt;Jeff Duntemann&lt;/strong&gt; is my absolute favorite. Here's a list of new (to me anway) books I've recently acquired:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;em&gt;Mastering Delphi 2005&lt;/em&gt;&lt;/strong&gt; - Marco Cantù&lt;br /&gt;&lt;strong&gt;&lt;em&gt;Delphi 2007 Handbook&lt;/em&gt;&lt;/strong&gt; - Marco Cantù&lt;br /&gt;&lt;strong&gt;&lt;em&gt;Delphi 2009 Handbook&lt;/em&gt;&lt;/strong&gt; - Marco Cantù&lt;br /&gt;&lt;strong&gt;&lt;em&gt;Delphi 2009 Development Essentials&lt;/em&gt;&lt;/strong&gt; - Bob Swart&lt;br /&gt;&lt;strong&gt;&lt;em&gt;The Tomes of Delphi Algorithms and Data Structures&lt;/em&gt;&lt;/strong&gt; - Julian Bucknall&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;However, there's one other resource that I need to tell you about. It's called "&lt;strong&gt;&lt;em&gt;The Delphi Magazine&lt;/em&gt;&lt;/strong&gt;". It is no longer in print but you can order the "&lt;strong&gt;&lt;em&gt;Delphi Magazine Total Collection&lt;/em&gt;&lt;/strong&gt;" for $57.00. This collection is amazing. I spent last night looking at all the article titles written by each author. This includes all 139 magazine issues from April 1995 through March 2007.&lt;br /&gt;&lt;br /&gt;I like the fact that you can browse articles by author. The same author will have several related articles and if you are interested in those articles they are all in one place. It's like recording your favorite TV shows without the commercials.&lt;br /&gt;&lt;br /&gt;Get the &lt;strong&gt;&lt;em&gt;Delphi Magazine Total Collection&lt;/em&gt;&lt;/strong&gt;.&lt;br /&gt;&lt;a href="http://www.thedelphimagazine.com/"&gt;http://www.thedelphimagazine.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I told you I was "&lt;strong&gt;&lt;em&gt;Experience Delphi Again For The First Time&lt;/em&gt;&lt;/strong&gt;" and this total collection is awesome. I have never fully converted from a Top-Down Procedural programmer to an Object Oriented programmer but I will be after I read and put to use the 6 articles by David Baer.&lt;br /&gt;&lt;br /&gt;1: Crossing The Chasm &lt;br /&gt;2: Welcome To The Machine &lt;br /&gt;3: Skyrocketing Property &lt;br /&gt;4: The TObject Of My &lt;br /&gt;5: You Are TEgg Man... &lt;br /&gt;6: To Talk Of Many Thing &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Semper Fi - Gunny Mike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-7554508225210733871?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/7554508225210733871/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2009/12/experience-delphi-again-for-first-time.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/7554508225210733871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/7554508225210733871'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2009/12/experience-delphi-again-for-first-time.html' title='Experience Delphi Again For The First Time'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8832291873344926372.post-1018215159743146734</id><published>2009-12-14T04:19:00.000-08:00</published><updated>2012-05-05T06:16:46.843-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='delphi-nugget'/><title type='text'>Keeping Your Code Folded in Delphi 2010</title><content type='html'>I really enjoy the "&lt;strong&gt;&lt;em&gt;Code Folding&lt;/em&gt;&lt;/strong&gt;" feature inside Delphi 2010. I noticed that each time I reopened the project I was working on the folded code was no longer folded.&lt;br /&gt;&lt;br /&gt;To keep your code folded you need to turn on the "Project desktop" setting:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Tools&lt;/strong&gt; &gt; &lt;strong&gt;Options&lt;/strong&gt; &gt; &lt;strong&gt;Environment&lt;/strong&gt; &gt; &lt;strong&gt;Project desktop&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Semper Fi - Gunny Mike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8832291873344926372-1018215159743146734?l=capecodgunny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://capecodgunny.blogspot.com/feeds/1018215159743146734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://capecodgunny.blogspot.com/2009/12/keeping-your-code-folded-in-delphi-2010.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/1018215159743146734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8832291873344926372/posts/default/1018215159743146734'/><link rel='alternate' type='text/html' href='http://capecodgunny.blogspot.com/2009/12/keeping-your-code-folded-in-delphi-2010.html' title='Keeping Your Code Folded in Delphi 2010'/><author><name>Michael Riley</name><uri>http://www.blogger.com/profile/15959746627356186242</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_CwHZ9RQn_wQ/S2oVwDsLOrI/AAAAAAAAAA8/CcRvXqknS4Y/S220/Mike008.jpg'/></author><thr:total>0</thr:total></entry></feed>
