August 2004 Archive
The joys of Perl!
So, Perl managed to die on our server somehow! Therefore it managed to kill movabletype off as well. However, after reinstalling Perl and all the PPMs it is back up and running.
I can’t believe I’m going to say this, but Perl is actually pretty cool. Well, specifically, the ease of being able to install new extensions over the wire. It was SO easy! A real pleasure to work with!
Anyways, now the blog is back! I look forward to seeing it grow over the coming months!
Posted by Niklas Richardson on 16 Aug 2004
New UKCFUG design released
After a week of work we released the new design of the UK ColdFusion User Group website.
We also managed to slip in a couple of bug fixes to the code base (including the jobs page and the forgotten password tool).
As time was tight we couldn’t move away from the old layout too much, but we hope the new design will improve the overall feel of the site.
Thanks to Filip our designer for putting together a truely awesome design!
Posted by Niklas Richardson on 17 Aug 2004
I'm back
I’m back from my summer holiday in the twin cities.
Congrats to Filip and Nik for putting together the new theme of the UKCFUG website. The new style looks great.
I’m thrust straight back into Flex coding again. This will be good, because I need to get ready for our free seminar on Large Datasets in Flex. More on that to come…
Posted by Neil Middleton on 17 Aug 2004
Flash Video Kit Announced
The Macromedia Flash Video Kit has been announced. You can find more information at the below links.
Flash Video Product Page:
http://www.macromedia.com/software/studio/flashvideokit/
Flash Video Developer Center:
http://www.macromedia.com/devnet/mx/flash/video.html
FAQ:
http://www.macromedia.com/software/studio/flashvideokit/faq.html#item-7
Posted by Niklas Richardson on 17 Aug 2004
Associations Between VOs in Flex
We are just moving into some interesting discussions regarding how to develop complex relationships between multiple VO (Value Objects) in Flex.
If we are to follow the rule that VOs can only contain scalar properties or arrays of other VOs how can we define the following relationship:
“A contact can be in one company, but a company can have many contacts.”
It seems like it would be pretty straight forward, but it becomes a bit more confusing when you enumerate the contact data to include all company data, and the company data to include all related contact data. This leads to something like this:
[code lang=“as3”]
myContactVO.company.contacts1.company.contacts1.company.contacts1.company…
[/code]
If it isn’t enumerated, then do we use IDs?! Wouldn’t that be a hack, no?
We have talked about Association Classes, is that our solution?
Posted by Neil Middleton on 17 Aug 2004
Associations Between VOs in Flex (Part 2)
After chatting with Nik about Steven’s thoughts on the age old problems of VOs composition we have tripled the number of Value Objects (Transfer Objects).
Some VOs are “deeply embedded” object graphs for example :
[code lang=“as3”]
ContactsVO.homeAddress.addressID
[/code]
( Where homeAddress is a AddressVO.)
And others are simple lists which don’t contain any deeply embedded object graphs. This has assisted us in getting away from the problems of circular references.
We are now thinking hard about ways to more rapidly build, test and refactor these VOs. This will, no doubt, be the subject of my next blog.
It seems that this is the promise of MDA, no? We have these VISIO class UML diagrams of VOs which we are refactoring all of the time. There is no reason why we shouldn’t be able to dynamically generate this very predictable code from such diagrams.
I heard from a friend that the new version of .net will have such Visio or Model integration. Apparently in the new version of Visual Studio.net is a refactor button which will map out your classes into Visio itself…
Posted by Neil Middleton on 18 Aug 2004
New DevNet content online!
Just to let you know there is new DevNet content online.
http://www.macromedia.com/devnet/
Posted by Niklas Richardson on 19 Aug 2004
MMUG Cancelled
I was sad to see that the MMUG meeting ‘Battle of the Web Editors’ was cancelled due to low numbers. I hope that we can see the battle later on.
I love this Reality TV meets User Group idea…
Posted by Neil Middleton on 19 Aug 2004
CFC Deep Copies (Part 1)
I am surprised to see that ColdFusion currently doesnt support cloning object instances. By Cloning I mean a Deep Copy, such that
[code lang=“cf”]
myWidget = new Widget();
myWidgetClone = myWidget.clone();
[/code]
Where myWidget and myWidgetClone arent two aliases for the same memory reference, but the objects are structurally the same.
The duplicate function is good first take, but, alas, it only returns structures. This is good if you want to pass structures around as object parameters, but we at Prismix have found that using structures rather than objects for structured parameters is difficult to validate and maintain in ColdFusion’s typeless environment.
Here is my quick take at a universal duplicate function. Let me know how I can improve it. Thanks!
Updated Snippet (19/08/04 18:06): Please cut and paste into a text editor.
[code lang=“cf”]
<!—-
Build a new instance of this object and then
use introspection to dynamicaly copy the properties.
Certain requirements are implied:
1. Arrays can only contain scalar values or other VOs.
2. VOs must implement clone themselves.
3. ColdFusion structures will only be duplicated, if there are VOs in sub keys
the will NOT be cloned.
This would be a great STATIC method.
—→
var thisMetaData = getMetaData(this);
myClone = CreateObject(“component”, thisMetaData.name).new();
for (i = 1; i lte arrayLen(thisMetaData.properties); i = i + 1){
currentPropertyName = thisMetaData.properties[i].name;
/*
Figure out cloning in three main cases :
1. Scalar Types
2. Other VOs
3. Arrays
*/
if (structKeyExists(this,currentPropertyName))
{
if (isSimpleValue(this[currentPropertyName]))
{
myClone[currentPropertyName] = this[currentPropertyName];
}
else if (isObject(this[currentPropertyName]))
{
myClone[currentPropertyName] = this[currentPropertyName].clone();
}
else if (isStruct(this[currentPropertyName]))
{
myClone[currentPropertyName] = duplicate(this[currentPropertyName]);
}
/*
If this is an array, then itterate over the scalar or VOs it contains and clone them.
*/
else if (isArray(this[currentPropertyName]))
{
myClone[currentPropertyName] = arrayNew(1);
for (j = 1; j lte arrayLen(this[currentPropertyName]); j = j + 1)
{
myCurrentSubProperty = this[currentPropertyName][j];
if (isSimpleValue(myCurrentSubProperty))
{
myClone[currentPropertyName][j] = myCurrentSubProperty;
}
else if(isObject(myCurrentSubProperty))
{
myClone[currentPropertyName][j] = myCurrentSubProperty.clone();
}
}
}
}
}
return(myClone);
[/code]
Posted by Neil Middleton on 19 Aug 2004
CFC Deep Copies (Part 2)
We are following the Transfer Object or (Value Object) Pattern to by ‘contract’ agree upon the structure of the data objects we pass between tiers in our Enterprise application.
We find that we need to use these VOs often before the data layer has been written. This data layer serialises, or writes them to the database. I have been playing around with code that ‘auto stubs’ these VOs, so that it is easy to knock one together and get it working between interfaces. The code is below, I will flesh this description out in more detail on Monday.
Special thanks to Lucas Sherwood at Macromedia for his isValidCFC() code which uses the Factory Methods. How can I get his cool code formatting?!
[code lang=“cf”]
<!—-
Iterate over all values, as in clone, but rather than assign values create new ones
using a stub utility.
It takes an existing VO and fills up all of the properties which are undefined with
valid filler data.
—→
var thisMetaData = getMetaData(this);
var stubbedVO = CreateObject(“component”, thisMetaData.name).new();
var VOMetaData = getMetaData(stubbedVO);
var currentProperty = structNew();
//Loop over all properties and use introspection to populate their scalar values
for (i = 1; i lte arrayLen(voMetaData.properties); i = i + 1){
currentProperty = voMetaData.properties[i];
//check to see if the property is an array
if (currentProperty.type eq ‘array’)
{
arraySize = Randrange(0,8);
stubbedVO[currentProperty.name] = arrayNew(1);
for (j = 1; j lte arraySize; j = j + 1){
myCurrentProperty = duplicate(currentProperty);
myCurrentProperty.type = myCurrentProperty.itemType;
stubbedVO[currentProperty.name][j] = stubProperty(myCurrentProperty);
}
}
else
stubbedVO[currentProperty.name] = stubProperty(currentProperty);
}
stubbedProperty = ’’;
switch(propertyData.type) {
case “uuid”:
return (createUUID());
break;
case “string”:
return (propertyData.name & ’ ’ & randString(20));
break;
case “numeric”:
return (randRange(0,5000));
break;
case “struct”:
myStruct = structNew();
myStruct.a = randString(10);
myStruct.b = randString(10);
myStruct.c = randString(10);
myStruct.d = randString(10);
return(myStruct);
break;
default:
/*
The type may contain a path to a CFC, if this is the case
then return it as a stub.
::ToDo: Proper validation of CFC paths
*/
try
{
if(isValidCFC(propertyData.type))
return(CreateObject(“component”,propertyData.type).buildStub());
else
return(randString(20));
}
catch(“Any” exceptionVariable)
{
return (‘property type not supported:’ & propertyData.type);
}
} //end switch
var tempAlphaList = “a|b|c|d|e|g|h|i|k|L|m|n|o|p|q|r|s|t|u|v|w|x|y|z”;
var tempNumList = “1|2|3|4|5|6|7|8|9|0”;
var tempCompositeList = tempAlphaList&“|”&tempNumList;
var tempCharsInList = listLen(tempCompositeList,“|”);
var tempCounter = 1;
var tempWorkingString = "";
//loop from 1 to stringLength to generate string
while (tempCounter LTE stringLength) {
tempWorkingString = tempWorkingString&listGetAt(tempCompositeList,randRange(1,tempCharsInList),“|”);
tempCounter = tempCounter + 1;
}
return tempWorkingString;
<!—-
Thanks to Lucas Sherwood at Macromedia lsherwood@macromedia.com
>
var filePath = cfcPath;
var factory = CreateObject(“java”, “coldfusion.server.ServiceFactory”);
var delim = “/”;
// determine file system delimeter
if (findNoCase(“windows”,server.os.name,1)){
delim = “\”;
}
//switch the dots to /‘s and then add the extension
filePath = replace(cfcpath,“.”,delim,’ALL’) & “.cfc”;
// check to see if CFC exists with a reletave mapping
if(FileExists(ExpandPath(filePath))) {
return true;
}
// check absolute mapping
filePath = delim & filepath;
if(FileExists(ExpandPath(filePath))) {
return true;
}
// attempt to resolve mappings and try again
filePath = StructFind(factory.RuntimeService.getMappings(),‘/’ & listFirst(cfcPath,‘.’)) & listDeleteAt(filePath,1,delim);
if(listLen(cfcpath,“.”) neq 1 and structKeyExists(factory.RuntimeService.getMappings(),‘/’ & listFirst(cfcPath,‘.’))) {
filePath = StructFind(factory.RuntimeService.getMappings(),‘/’ & listFirst(cfcPath,‘.’)) & listDeleteAt(filePath,1,delim);
if(FileExists(filePath)) {
return true;
}
}
// nope it’s all failed…
return false;
[/code]
Posted by Neil Middleton on 20 Aug 2004
MTCodeBeautifier and MovableType
I didn’t realise that setting up MTCodeBeautifier would be SO hard. Well, in fact it was! It was a flipping nightmare! In any case, I now have it working, and we can now output lovely ColdFusion code:
[code lang=“cf”]
myvar = “Hello World!”;
[/code]
These are the steps that I took:
I installed the following:
The installation of these is straight forward and if you follow the instructions on the MTCodeBeautifier website for using MTMacro instead of Textile 2 then I’ve found it works a treat. You also need to add the following CSS to your stylesheet for it to look nice.
[code lang=“css”]
.linecomment { color: #FF8000; }
.blockcomment { color: #FF8000; }
.prepro { color: #0000BB; }
.select {}
.quote { color: #DD0000; }
.category1 { color: #007700; }
.category2 { color: #0000BB; }
.category3 { color: #0000BB; }
/* To make Word-wrap work */
pre
{
border: 1px solid #888;
background: #FFF;
padding: 5px;
overflow: auto;
width: 95%;
max-height: 450px;
margin: 0px auto;
}
[/code]
I then just wrap the following around my code snippets to get code colouring:
[code lang=“html”]
<cfscript>
myvar = "Hello World!";
[/code]
It also supports other language colouring like ActionScript, PHP and Perl.
However, be sure to turn off “Text Formatting” when you create your posts otherwise it will look REALLY ugly, and make sure you format your own posts using HTML.
Posted by Niklas Richardson on 23 Aug 2004
Imitating Flash Remoting Object Calls
We are needing to do remapping between Flex Remote Object calls and our CFCs in our ColdFusion service layer. We are using the Business Delegate and Transfer Object patterns to translate the communication between Client and Server layers. Flash Remoting translates our Transfer Objects from the server into typeless structures on the client. We need to translate that onto the server into the typed VOs which our CFC calls require.
The below snippet is what we are using to imitate how Flash calls our Business Delegates on the server. It uses our new and clone VO functions along with the ColdFusion duplicate() function to transform a typed VO into a typeless struct. It works great for our test harnesses. Just thought that I would pass this little snippet on…
[code lang=“cf”]
//emulating the structure of the flash remoting calls
//Use auto-stubbing to create an item, then use duplicate on it to turn it into a CF structure – simliar to Flash Remoting
this.struct_companyVO = duplicate(CreateObject(“component”,‘net.ourclient.vo.CompanyVO’).new().buildStub());
this.struct_companyListVO = duplicate(CreateObject(“component”,‘net.ourclient.vo.CompanyListVO’).new().buildStub());
[/code]
Posted by Neil Middleton on 24 Aug 2004
CFDUMP for AS2 and Flex
As much as we love FlexBuilder, MXML and ActionScript 2.0 as a development platform we continue to run into the age old problem of trying to visulize exactly what data we are working on. So much of debugging seems to be centred around resolving a misconception of what structure of data you are working on. In the world of ActionScript, this is even more the case. Error reporting is less than verbose with most run-time errors failing silently.
Years ago when we ran into this problem with early versions of ColdFusion, I came up with a little utility called CF_DumpStruct(). This simple custom tag takes any ColdFusion struct and dumps a visualisation of the contents into the browser. This improved our need to have a visual understanding of the contents of the structure. Peter Muzila, then lead architect of Spectra, which later became Farcry (not officially of course) expanded on this and made cf_dump. This later became CFDUMP which everyone knows and loves(?) today.
Excuse my digression as I point the reader out to this little class that we are using to visualise our ActionScript objects. Instead of writing our own utility, we have decided to use the NetConnection Debugger and Flash Remoting to visualise it for us. Essentially, we make a fake call with our object out to some unknown remote method and then examine the contents of the call to see what it is we are working on.
It is very simple, but I use it every day. Much easier than examining a log file when dealing with large structures of data and object trees.
Enjoy!
[code language=“xml”]
[/code]
[code lang=“as3”]
/*
Then use mangled names on the label to get a visual map of your variable
*/
static function dump(lbl : String, obj) : Void{
}
[/code]
Posted by Neil Middleton on 24 Aug 2004
MySQL version of Matt Chotin's Large Data Sets SQL (Part 1 of 2)
Matt Chotin wrote three really great articles on managing large data sets in Flex. Part 2 of his series used MSSQL stored procedures. As we are using MySQL I decided to figure out the SQL for MySQL.
Below is the MSSQL and MySQL version of the SQL. MySQL doesn’t support stored procedures yet, however you can still use these MySQL SQL directly.
I would love to hear your feedback, as I’m not a DBA by trade!
MSSQL Stored Proc
[code lang=“sql”]
Create Procedure sp_GetSortedCensusDataPosition
(
@SearchId int,
@SortSQL varchar(100)
)
As
SET NOCOUNT ON
CREATE TABLE #TempTable
(
rownum int IDENTITY,
age smallint NULL,
classofworker varchar(100) NULL,
education varchar(100) NULL,
maritalstatus varchar(100) NULL,
race varchar(100) NULL,
sex varchar(10) NULL,
id int
)
DECLARE TempSQL varchar(5000)
SELECT @TempSQL = 'INSERT INTO #TempTable '+
'SELECT age, classofworker, education, maritalstatus, race, sex, id FROM censusincome ORDER BY ' + @SortSQL
EXECUTE(TempSQL)
SELECT rownum FROM #TempTable WHERE id = @SearchId
SET NOCOUNT OFF
[/code]
MySQL
[code lang=“sql”]
CREATE TEMPORARY TABLE temptable
(
age int(11) default NULL,
classofworker varchar(255) default NULL,
education varchar(255) default NULL,
maritalstatus varchar(255) default NULL,
race varchar(255) default NULL,
sex varchar(255) default NULL,
id int(11) unsigned NOT NULL,
rownumber int(11) unsigned NOT NULL auto_increment,
PRIMARY KEY (rownumber)
);
INSERT INTO temptable (age, classofworker, education, maritalstatus, race, sex, id)
SELECT age, classofworker, education, maritalstatus, race, sex, id
FROM censusincome
ORDER BY @SortSQL;
SELECT rownumber
FROM temptable
WHERE id = @SearchId;
DROP TABLE temptable;
[/code]
Posted by Niklas Richardson on 25 Aug 2004
Contact List (Part 1 - Exploring Large Data Sets)
Macromedia’s Matt Chotin in his three part series about Large Data Sets in Flex is a informative hands-on tutorial about handling enterprise – level quantities of data between the Flex presentation tier and a services tier. I find Matt’s contributions to both his Blog and the Flexcoders email list a tangible contribution to the community. We have started testing his sample code with a ColdFusion Application server and MySQL database on the server side. Later we aim to compare and constrast the results with J2EE and .Net at MX Europe 2005 in January.
ColdFusion lacks many of the fully OOP features that we would like to see, but it has been traditionally rapid in knocking out web applications. In particular CF lacks polymorphism and the clear seperation between interface and implementation. That being said, with the release of ColdFusion MX developing Web Services became extremely easy to rapdily prototype. We continue to use ColdFusion, but more and more question the usefulness of a 4GL rapid Java develelopment environment against just J2EE direct – or .NET I’m looking forward to seeing if the Blackstone seminar at the UKCFUG tomorrow addresses many of these concerns. But I feel that it may just be the classic trade-off between rapid protyping and robustness of architecture.
We have knocked out a first take at the CensusDataService object that we will be later using as a guide for integrating into our own application.
First steps are to get Matt’s examples running in our current environment. Then, we would like to integrate these patterns into our Contacts area, where the user will be managing possibly thousands of contacts and companies – CRM – style. Finally, we would like to explore new ways of improving the Contacts interface through many well known Outlook paradigms, in particular inline searching and filtering.
Below is a snippet which is our CFC (very slow and being improved with some nice SQL from Nik ) implementation of Matt’s ValueList and SortedValueList services. We will be exploring these concepts at a Free seminar on Flex and ColdFusion next month.
[code lang=“cf”]
<!—-
Used for testing paging
>
SELECT
id, age, classofworker, education, maritalstatus, race, sex
FROM
censusincome
WHERE
id > #arguments.begin#
AND
id <= #arguments.count# + #arguments.begin#
<!—-
Needs to be cleaned up…
>
<cfif len(arguments.sortField) AND len(arguments.sortAscending)>
Order By
#arguments.sortField# #iif(arguments.sortAscending,de(‘ASC’),de(‘DESC’))#
SELECT
id
FROM
censusincome
<!—-
/**
- Return a range of elements sorted in the order specified
- @param begin the position of the first element to return
- @param count how many elements to return
- @param sortField the field on which to sort
- @param sortAscending true if the sort should be in ascending order
- @return a sorted List of elements
*/
—→
<!—-
Build a temporary sorted table which has a new rownum primary key column,
then insert sorted data into temp table. Use the new rownum column to obtain
the specified ‘page’.
>
CREATE TEMPORARY TABLE temptable
(
age int(11) default NULL,
classofworker varchar(255) default NULL,
education varchar(255) default NULL,
maritalstatus varchar(255) default NULL,
race varchar(255) default NULL,
sex varchar(255) default NULL,
id int(11) unsigned NOT NULL,
rownum int(11) unsigned NOT NULL auto_increment,
PRIMARY KEY (rownum)
);
INSERT INTO temptable (age, classofworker, education, maritalstatus, race, sex, id)
SELECT age, classofworker, education, maritalstatus, race, sex, id
FROM censusincome
<cfif len(arguments.sortField) AND len(arguments.sortAscending)>
ORDER BY
#arguments.sortField# #iif(arguments.sortAscending,de(‘ASC’),de(‘DESC’))#
SELECT *
FROM temptable
WHERE rownum >= #arguments.begin#
AND rownum < #arguments.begin# + #arguments.count#
<cfif len(arguments.sortField) AND len(arguments.sortAscending)>
ORDER BY
#arguments.sortField# #iif(arguments.sortAscending,de(‘ASC’),de(‘DESC’))#
DROP TABLE temptable;
<!—-
/**
- Return the 0-based index of the passed in element if a List were sorted according to the parameters
- @param searchObject the element we’re searching for
- @param sortField the field on whcih to sort
- @param sortAscending true if the sort should be in ascending order
- @return the 0-based index of the searchObject
*/
—→
<!—-
Build a temporary sorted table which has a new rownum primary key column,
then insert sorted data into temp table. Use the new rownum column to obtain
the location of the selected object.
ToDo: can we reuse the other getSortedElements bit here?
—→
CREATE TEMPORARY TABLE temptable
(
age int(11) default NULL,
classofworker varchar(255) default NULL,
education varchar(255) default NULL,
maritalstatus varchar(255) default NULL,
race varchar(255) default NULL,
sex varchar(255) default NULL,
id int(11) unsigned NOT NULL,
rownum int(11) unsigned NOT NULL auto_increment,
PRIMARY KEY (rownum)
);
INSERT INTO temptable (age, classofworker, education, maritalstatus, race, sex, id)
SELECT age, classofworker, education, maritalstatus, race, sex, id
FROM censusincome
<cfif len(arguments.sortField) AND len(arguments.sortAscending)>
ORDER BY
#arguments.sortField# #iif(arguments.sortAscending,de(‘ASC’),de(‘DESC’))#
SELECT rownum
FROM temptable
WHERE id = #searchObject.id#;
DROP TABLE temptable;
[/code]
Posted by Neil Middleton on 25 Aug 2004
Free Seminar : September 30th
As Web developers we often need to worry about displaying and managing large amounts of data. Working in an enterprise environment this is often the case – companies frequently have tens of thousands of business objects like contacts, invoices, work orders etc.
Macromedia’s Matt Chotin has given us some insights into ways of working with large amounts of data in Flex. We will apply these concepts and the patterns he uses in a sample Flex and ColdFusion Application.
Outline
- Architectural Review
- Explicit Paging
- Implicit Paging
- Sorting
- CFC Implementation Changes and Limits
Ideas and concepts covered
- CFML
- ColdFusion Components
- Flash Remoting
- MXML
- ActionScript 2.0 in Flex
- SQL Optimisation
Background Material
Level
Intermediate / Advanced
About The Speaker
Allen Manning, Technical Director, Prismix Ltd.
Posted by Neil Middleton on 26 Aug 2004
MySQL version of Matt Chotin's Large Data Sets SQL (Part 2 of 2)
Yesterday I posted an entry on converting the SQL used in Matt Chotin’s second article on Large Data Sets in Flex to work with MySQL. Today I post the second lot of SQL. Enjoy!
Each block (from yesterday and today) takes about 2.5 seconds to run on MySQL. That is, creating the temporary table, inserting 16,383 sorted records, doing a select and then dropping the table. Now, this performance doesn’t sound great, however I haven’t tried it on SQL Server. I guess we’ll have to wait to MySQL 5.0 to get stored procedures to see if that speeds it up!
MSSQL Stored Proc
[code lang="sql"] Create Procedure sp_GetSortedCensusData ( @Begin int, @End int, @SortSQL varchar(100) ) As SET NOCOUNT ON CREATE TABLE #TempTable ( rownum int IDENTITY, age smallint NULL, classofworker varchar(100) NULL, education varchar(100) NULL, maritalstatus varchar(100) NULL, race varchar(100) NULL, sex varchar(10) NULL, id int ) DECLARE @TempSQL varchar(5000) SELECT @TempSQL = 'INSERT INTO #TempTable '+ 'SELECT age, classofworker, education, maritalstatus, race, sex, id FROM censusincome ORDER BY ' + @SortSQL EXECUTE(@TempSQL) SELECT age, classofworker, education, maritalstatus, race, sex, id FROM #TempTable WHERE rownum >= @Begin AND rownum < @End ORDER BY rownum ASC SET NOCOUNT OFF [/code]
MySQL
[code lang="sql"] CREATE TEMPORARY TABLE temptable ( age int(11) default NULL, classofworker varchar(255) default NULL, education varchar(255) default NULL, maritalstatus varchar(255) default NULL, race varchar(255) default NULL, sex varchar(255) default NULL, id int(11) unsigned NOT NULL, rownum int(11) unsigned NOT NULL auto_increment, PRIMARY KEY (rownum) ); INSERT INTO temptable (age, classofworker, education, maritalstatus, race, sex, id) SELECT age, classofworker, education, maritalstatus, race, sex, id FROM censusincome ORDER BY @SortSQL; SELECT rownum FROM temptable WHERE rownum >= @Begin AND rownum < @End ORDER BY @SortSQL; DROP TABLE temptable; [/code]
Posted by Niklas Richardson on 26 Aug 2004
| www.flickr.com |
Archives
Posted by Neil Middleton on 01 Jan 1910
From our portfolio
| www.flickr.com |
