` Comment on an Icetips Article
Icetips - Templates, Tools & Utilities for Clarion Developers

Templates, Tools and Utilities
for Clarion Developers

Add a comment to an Icetips Article

Please add your comments to this article. Please note that you must provide both a name and a valid email address in order for us to publish your comment. Comments are moderated and are not visible until they have been approved. Spam is never approved!

Your Name:  
Email:  
Header text/Subject:  

Please enter your comment in the box below:

Back to article list   Search Articles     Add Comment     Printer friendly     Direct link  

SQL Related Articles: Better SQL Part 4
2002-07-23 -- Dan Pressnell
 
Somebody made a really stupid decision when designing SQL when he invented the Date-Time type. Two values in one field? Hey, let's have a firstname-lastname type, and a city-state-country-postalcode type! Why stop with one stupid idea?
 
But it's done, and we have to live with it.
 
In the demo app at http://www.icetips.com/downloadfile.php?FileID=59 you can see one simple way of handling a date-time column for a browse queue. In the UpdatePlayers procedure, there is a browse for "At bats". The first column in the browse is a date filed. Because the queue will be filled by the QueryFromQueue procedure, some special thought has to be given to the queue structure.
 
To handle a date, declare your queue like this:
atbatqueue    queue
Date            string(10), name('atbats.date')
OppTeam         like(tea:teamname), name('teams.teamname')
Result          string(10), name('atbats.result')
AtBatID         like(atb:atbatid), name('atbats.atbatid')
              end
The date field in the queue is declared as string(10) simply because that's what you are going to get for the value, in the format "yyyy-mm-dd". There can also be a time portion to that, but I'll get to that below.
 
After you fill the queue from the query, do something like this:
loop i=1 to records(atbatqueue)
  get(atbatqueue, i)
  atbatqueue.Date = deformat(atbatqueue, @d010-)
  atbatqueue.Result = AtBatResultToString(atbatqueue.Result)
  put(atbatqueue)
end
That converts the SQL date format to a standard date format that Clarion handles, and you can use any picture in the browse for that column that you want.
 
Don't worry too much about handling date-time fields for updates. The standard Clarion update procedure works pretty well for doing all the conversions.
 
If you need the time portion as well, it's another one line of code. Suppose this queue:
MyQueue    queue
MyDate       string(20), name('mytable.date')
MyTime       long, name('''''')
           end
Note the name attribute for the MyTime field. Your query, when generated by the QueryFromQueue procedure, will include '' in the SELECT portion. How much bandwidth does a blank string take? I don't know, but I suspect it's not much. When you have a field in the queue which you will set later yourself, you can set the name atrribute like that. Or you could set it to a default value. I don't think there is much difference one way or the other, since you'll be processing it later anyway.
 
Also notice that the MyDate field is now string(20). That's so it can hold the full date-time combination from the result set.
 
Now to get the date and time fields converted in the queue. Be sure to convert the time field first, because when you convert the date, you'll wipe out the time portion. Do it like this:
loop i=1 to records(MyQueue)
  get(MyQueue, i)
  MyQueue.MyTime = deformat(MyQueue.MyDate[12 : 19], @t4)
  MyQueue.MyDate = deformat(MyQueue.MyDate[1 : 10], @d010-)
  put(MyQueue)
end
Now look back at the atbatsqueue declaration. It has this field:
Result        string(10), name('atbats.result')
In the atbats table, the result column is a numeric. In practice, it should contain only the values 0,1,2,3, or 4. So why not declare the Result field as a byte in the queue? Because we want to hold something descriptive, something like "Out", "Single", "Double", "Triple", or "Home Run."
 
Immediately after the query, the Result field holds the number that is in the table row. While converting the date column for the queue, the code in the SendAtBatsQuery routine also converts that number to the string representation so it can display in the browse.
 
Now back to date-time fields. Don't rely on something like this:
  SELECT CUSTOMER WHERE LASTBILLED >= '2000-01-01' and
  LASTBILLED <= '2000-01-31'
The first part of the condition is okay. But what if there is a time portion to the LASTBILLED column? You will miss the records that have a value of '2000-01-31 14:00:00'.
 
The correct way to do that is to look for values that are less than the target date plus one date. For example, if you want the dates up through 2000-01-31, then it would be
   LASTBILLED < '2000-02-01'

Comments...

 
That depends on the SQL backend. MS-SQL has it's roots in Sybase ASE 4.2 and they only have a single timestamp type of column. We use Sybase's ASA 8.0.1 and it has column types of timestamp, date and time. We use all three formats depending on what the need for that is. Works well within Clarion also. If your using just the date or time, there is nothing special that needs to be done, except for formatting the date when doing a prop:sql but other than that, it's a breeze.
Comments...

 
Another way to handle a compound date/time field when querying only the date is as follows:
ORD.ORDERDATE BETWEEN {ts '1994-09-30 00:00:00'} AND {|
 ts '1994-09-30 23:59:59'} )

 
The new SQL extensions to The Clarion Handy Tools handle date stamps in this way.
 
The classes detect when the back end is using a date stamp data type. If you're doing a query involving only the date part of this, it intercepts your query statement (date = 9/30/1994) and expands it to include the highest and lowest possible times in a range. You don't really have to think about this since the work is done for you in the background.
 
We've added some easy to use functions to our browse class extensions that let you keep your querying statements in pure Clarion if you want to:
OBJ.AppendSQLFilter('ORD:ORDERDATE = ' &  YourDateValue)
OBJ.ReplaceSQLFilter('ORD:ORDERSATE = ' & YourDateValue)
The back end receives
ORD.ORDERDATE BETWEEN {ts '1994-09-30 00:00:00'} AND |
 {ts '1994-09-30 23:59:59'} )

 
The classes are aware that it is possible to change the date formats used by various back end data bases and allow you to indicate by template configuration or at run time how the back end is formatting dates. So the SQL output string is adjusted accordingly.


Today is November 21, 2024, 6:54 am
This article has been viewed 35321 times.
Google search has resulted in 366 hits on this article since January 25, 2004.



Back to article list   Search Articles   Add Comment   Printer friendly

Login

User Name:

Password: