
January 14th, 2004, 11:25 AM
|
|
Registered User
|
|
Join Date: Jan 2004
Posts: 6
Time spent in forums: 2 m 15 sec
Reputation Power: 0
|
|
|
Function behaves differently when put in the where clause appose to as column heading
I have a pl/sql function which resides on the database server which is called from within a select statement in an application on the client machine.
select latitude, longitude from scatter where latlong(latitude, longitude)=1;
For each row in the scatter table the fields for the latitude and longitude values are input to the function latlong which compares them to reference latitude longitude points. If the current row is the first row in the table the reference points are assigned to the current values and 1 is returned. For the second ++ rows in the table, if either of the compared latitude / longitude points are >0.005 from the ref points then a 1 is returned and the row is included in the output from the select statement. Another if statement is used to check if the user has begun a new select statement so that the reference points are reset.
The function is within a package so that global variables can be used to remember the reference points since the function is executed for each row in the table.
The current code is…
create or replace package globalLL is
refLat number(32,10);
refLong number(32,10);
refID number(32,10);
function latLong(latitude in number, longitude in number, ID in number) return number;
end;
/
create or replace package body globalLL as
function latLong(latitude in number, longitude in number, ID in number) return number is
compLat number(32,10);
compLong number(32,10);
begin
if refLat is null and refLong is null and refID is null then
-- set default value of refLat and refLong and refID
refLat := latitude;
refLong := longitude;
refID := ID;
return 1;
end if;
if ID < refID then
-- checks if user has chosen a new table or reselected the same table and resets global variables
refLat := latitude;
refLong := longitude;
refID := ID;
return 1;
end if;
refID := ID;
compLat := abs(refLat – latitude);
compLong := abs(refLong – longitude);
if compLat > 0.005 or compLong > 0.005 then
refLat := latitude;
refLong := longitude;
return 1;
else
return 0;
end if;
end;
Now for the problem, if I do this select statement from SQL plus or the application
1)
select seq, latitude, longitude, globalLL.latLong (latitude, longitude, seq)
from scatter;
I get a result containing all of the rows in the scatter table and an indication of which would be not included (0) and which would be included (1) if I ran the following select statement.
2)
select latitude, longitude, seq
from scatter where globalLL.latLong (latitude, longitude, seq)=1
I counted the number of rows with 1s in the globalLL.latLong column for the result from sql statement 1 manually and there were 45.
When I run the 2nd sql statement it does not agree with my manual count. It returns a result containing 86 rows. This is incorrect because it should be 45!
From analysis of the two data sets in my application, when the function runs in the 2nd select statement it is appears as though the number of rows (that the function returns 0 to) between a row that returns 1 and another row that returns 1 is important. It seems when this is large the function resets itself and outputs a 1 when it really should output a 0.
Eg if works ok if row 200 returns 1 and then there are 100 rows that return 0 before the 301st row returns 1. This seems to work ok. But if row 500 returns 1 and then there are 500 rows that return 0 before the 1001st row returns 1, then extra 1s are returned in the middle when they should be 0 and hence increasing my count from 45 to 86. The lat / long distance between row 200 and 301 is the same as row 500 to 1000. There is just more points data points in the second distance.
I do not think it is a problem with the function itself but some options on oracle. Does it limit how many times a function can be run within a package. It is strange that this problem only occurs when the function is put within the ‘where’ clause of the select statement (sql 2) appose to as a column (sql 1).
Any ideas would be much appreciated.
Howard
|