LOCAL laMax[1] CREATE CURSOR c_Test (PK int autoinc, value char(40)) INSERT INTO c_test (value) VALUES ('1.1') INSERT INTO c_test (value) VALUES ('1.02') INSERT INTO c_test (value) VALUES ('10.1') INSERT INTO c_test (value) VALUES ('01.3') INSERT INTO c_test (value) VALUES ('1.02.N') INSERT INTO c_test (value) VALUES ('1.02.N.R') INSERT INTO c_test (value) VALUES ('1.10.R') INSERT INTO c_test (value) VALUES ('1.10.R.1') INSERT INTO c_test (value) VALUES ('20DP') INSERT INTO c_test (value) VALUES ('20') INSERT INTO c_test (value) VALUES ('1.02.R') SELECT MAX(GETWORDCOUNT(value, '.')) FROM c_Test INTO ARRAY laMax SELECT getorder(ALLTRIM(c_test.value), laMax[1]), c_test.* FROM c_test ORDER BY 1 FUNCTION getOrder(tcValue, tnMaxWords) LOCAL lnWord, lnWords, lcValue lnWords = GETWORDCOUNT(tcValue, '.') lcValue = '' FOR lnWord = 1 TO tnMaxWords IF lnWord <= lnWords lcValue = lcValue + PADL(GETWORDNUM(tcValue, lnWord, '.'), 40, '0') + '.' ELSE lcValue = lcValue + REPLICATE('0', 40) ENDIF NEXT lnWord RETURN lcValueNote that the code is using a word length of 40, which is the max length a single "word" can have, and in this simple sample you sent it will work, but if you have a combination of large words and small words, all the extra paddings will make the string huge and unsuitable for the order by clause.