Use .sql Files with SQLEXEC for Better Script Management
The SQLEXEC command in FoxPro allows you to sends SQL statements to a database where they can be executed, returning one or more result sets. You might make a call like this in your application:
SQLEXEC(lnConnHand,'SELECT * FROM Customer')
Of course, using SQLEXEC in this way isn’t a great architectural choice, although serviceable. It is difficult to manage code in this way and difficult to support varying back end databases. I would never code customer applications in this way. Instead, I would load an external SQL file and execute that instead.
SQLEXEC(lnConnHand,FILETOSTR("c:\sqlserver2005\script1.sql"))
This approach not only decouples the proprietary SQL code from my application, but it also allows me to test and review the scripts in the native application (and likely get syntax coloring and intellisense). For example, script1.sql might contain TSQL code that I can review (and test) in SSMS. Even better, if I have a lone client running SQL Server 2000, I can use a different script if a new command (like INTERSECT, for example) is not available. This approach will prove even more valuable as some clients upgrade to SQL Server 2008. I will be able to take advantage of some of the new, faster features of SQL Server 2008 while still supporting older versions.
Using Metadata
To take this a step further, I have built metadata to manage these scripts. Consider an application that supports 4 different back-end databases: Visual FoxPro, SQL Server 2000, SQL Server 2005, and MySQL. Create the following table and store all SQL for each back-end database in the appropriate memo field:
CREATE TABLE sql_meta FREE (; query_id character(15),; sql_vfp m,; sql_ss2005 m,; sql_ss2000 m,; sql_mysql m)
Include this table in your project. In your beforebuild event in your project hook, import or update the sql scripts from your development folders into this table when you build your application.
Now, when you want to execute a script, your code would look a little like this:
*-- create the query/sql management object and execute the code oMQ = CREATEOBJECT( "manage_query" ) SQLEXEC(lnConnHand, oMQ.get_sql('SQL_ss2005','CUSTOMER')) *-- ok, so not very bullet-proof but you get the idea: DEFINE CLASS manage_query AS Custom PROCEDURE get_sql LPARAMETERS tcBackEnd, tcQueryId SELECT sql_meta LOCATE FOR query_id = tcQueryId RETURN sql_meta.&tcBackEnd ENDPROC ENDDEFINE
I’m a big fan of writing readable code. In fact, it is a priority in my development tasks. I’m also a big fan of making testing easier. This approach allows me to view and test each SQL script outside of my business and data access objects. It also makes for more readable and manageable code.
I’ve left out some examples on how you could use parameters or SQLPREPARE using this approach. I’ll be sure to make this a topic in a future entry.
I'm a Quant Technical Specialist (Data Warehousing and Business Intelligence), with expertise in business analysis, data modeling, and data integration. I have extensive experience developing vertical and integrated desktop, Internet, and BI applications spanning municipal, clinical, and financial industries.

October 19th, 2007 at 11:25 am
Great concept, Todd. I take the exact same approach–using metadata–in my n-tier designs. I demonstrated this at FoxForward this year and of course the downloads from that–including the source code with the sqldefs.dbf metadata table–are available from Ed Leafe’s ProFox downloads site: http://leafe.com/dls/vfp (see “Designing in N-Tier fashion”).
It’s always best to decouple when you can (without introducing much complexity). Even since the conference I’ve seen other areas in that project where I could decouple even more—specifically for adding temporary indexes.
If I’m not mistaken, Andy Kramek does something extraordinary with decoupling, where virtually most of the code is meta-data! I’m guessing he’s relying heavily on EXECSCRIPT? Neat.
Cool stuff!
–Michael
October 19th, 2007 at 1:32 pm
Thanks Michael, there are some great decoupling techniques around and I think that, by far, it is one of the smartest design decisions a developer can make. Especially if there is (or might be) a need to use a different database or UI.
I loved your business object demonstrations and the concept of “passing the buck”. It helped me put some theory around the practices I have been getting used to over the years.
October 21st, 2007 at 6:15 pm
[…] McKenna has posted a good article on Using .sql Files with SQLEXEC in […]
November 15th, 2007 at 8:16 am
business intelligence data mining…
Good comment. It brought light to an old idea I had….
November 16th, 2007 at 10:52 pm
bernard hills…
Thanks for the nice read, keep up the interesting posts…..