You have a nice link for finding mySQL distances.
Forget about Oracle Spatial. Too much code, too much complexity, adding value is not enough.
Here is a query that will do the trick. It uses charter miles. EDIT . This fixes the error mentioned by mdarwin at the cost of checking for separation if you try to use it for a location at the north or south pole.
SELECT id, city, LATITUDE, LONGITUDE, distance FROM ( SELECT id, city, LATITUDE, LONGITUDE, (3959 * ACOS(COS(RADIANS(LATITUDE)) * COS(RADIANS(mylat)) * COS(RADIANS(LONGITUDE) - RADIANS(mylng)) + SIN(RADIANS(LATITUDE)) * SIN(RADIANS(mylat)) )) AS distance, b.mydst FROM Cities JOIN ( SELECT :LAT AS mylat, :LONG AS mylng, :RADIUS_LIMIT AS mydst FROM DUAL )b ON (1 = 1) WHERE LATITUDE >= mylat -(mydst/69) AND LATITUDE <= mylat +(mydst/69) AND LONGITUDE >= mylng -(mydst/(69 * COS(RADIANS(mylat)))) AND LONGITUDE <= mylng +(mydst/(69 * COS(RADIANS(mylat)))) )a WHERE distance <= mydst ORDER BY distance
If you work in kilometers, change mydst / 69 to mydst / 111.045 and change 3959 to 6371.4. (1/69 converts miles to degrees, 3959 - the radius of the planet).
Now you are likely to be tempted to use this large query as a "magic black box." Do not do this! It is not very difficult to understand, and if you understand this, you can do a better job. This is what happens.
This section is the foundation of what makes the request fast. He is looking for a table of cities for nearby cities to the point you specify.
WHERE LATITUDE >= mylat -(mydst/69) AND LATITUDE <= mylat +(mydst/69) AND LONGITUDE >= mylng -(mydst/(69 * COS(RADIANS(mylat)))) AND LONGITUDE <= mylng +(mydst/(69 * COS(RADIANS(mylat))))
For it to work, you definitely need an index in the LATITUDE column. The index of your LONGITUDE column will also help a bit. It performs an approximate search, looking for lines that are inside a quasi-rectangular patch on the surface of the earth near your point. He chooses too many cities, but not too many.
This section allows you to exclude additional cities from your result set:
WHERE distance <= mydst
This item is a haversine formula that calculates the distance between big cities and the point.
(3959 * ACOS(COS(RADIANS(LATITUDE)) * COS(RADIANS(mylat)) * COS(RADIANS(LONGITUDE) - RADIANS(mylng)) + SIN(RADIANS(LATITUDE)) * SIN(RADIANS(mylat))
In this section, you can enter your point and your radius limiter only once as related variables in your query. This is useful because various formulas use these variables several times.
SELECT :LAT AS mylat, :LONG AS mylng, :RADIUS_LIMIT AS mydst FROM DUAL
The rest of the query simply arranges things, so you select and order by distance.
Here is a more complete explanation: http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/