Postgresql:ERROR:专栏" mayvar"不存在,而myvar是一个变量

时间:2015-02-03 06:15:56

标签: postgresql postgresql-9.4

我正在尝试在plsql中创建一个函数,以便在作为参数传递给函数的用户的1英里范围内找到5个用户。

这是我的代码:

    CREATE OR REPLACE FUNCTION testfunction (integer) RETURNS integer as $$
    DECLARE
    myvar integer := $1;
    mylon double precision; 
    mylat double precision; 
    lon1 float; 
    lon2 float; 
    lat1 float; 
    lat2 float;
    BEGIN
    raise notice 'help = %', $1; --just for testing
    raise notice 'myvar = %', myvar; --again for testing
    select cr.last_known_longitude, cr.last_known_latitude into mylon, mylat from current_reg as cr where userid = myvar;
    lon1 = mylon - 1 / abs(cos(radians(mylat))*69);
    lon2 = mylon + 1/abs(cos(radians(mylat))*69);
    lat1 = mylat - (1/69);
    lat2 = mylat + (1/69);
    create view myview as
            select destination.userid, 3956*2*asin(sqrt(power(sin((origin.last_known_latitude-destination.last_known_latitude)*pi()/180 / 2), 2) + cos(origin.last_known_latitude* pi()/180) * cos(destination.last_known_latitude* pi()/180) * power(sin((origin.last_known_longitude-destination.last_known_longitude) * pi()/180 /2), 2))) as distance
            from current_reg destination, current_reg origin
            where origin.userid = myvar
            and destination.last_known_longitude between lon1 and lon2
            and destination.last_known_latitude between lat1 and lat2
            having distance < 1 order by distance limit 5;
    return 0;
    END; 
    $$ LANGUAGE 'plpgsql';
    Select testfunction(7);

其中current_reg是一个以userid,last_known_latitude,last_known_longitude为列的表。作为整数传递给函数的参数是用户的用户ID,我希望在其位置(纬度和经度)中找到一英里范围内的用户。

我收到以下错误:

NOTICE:  help = 7
NOTICE:  myvar = 7

ERROR:  column "myvar" does not exist
LINE 1: ...ination, current_reg origin where origin.userid = myvar and de...
                                                             ^
QUERY:  create view myview as select destination.userid, 3956*2*asin(sqrt(power(sin((origin.last_known_latitude-destination.last_known_latitude)*pi()/180 / 2), 2) + cos(origin.last_known_latitude* pi()/180) * cos(destination.last_known_latitude* pi()/180) * power(sin((origin.last_known_longitude-destination.last_known_longitude) * pi()/180 /2), 2))) as distance from current_reg destination, current_reg origin where origin.userid = myvar and destination.last_known_longitude between lon1 and lon2 and destination.last_known_latitude between lat1 and lat2 having distance < 1 order by distance limit 5
CONTEXT:  PL/pgSQL function testfunction(integer) line 19 at SQL statement
********** Error **********

ERROR: column "myvar" does not exist
SQL state: 42703
Context: PL/pgSQL function testfunction(integer) line 19 at SQL statement

自&#34; myvar&#34;是一个变量,它为什么期望它成为一个列?

在@a_horse_with_no_name的帮助下,这是修改后的代码

    CREATE OR REPLACE FUNCTION testfunction (p_userid integer) 
    RETURNS table (userid integer, distance float) 
    AS 
    $$
    DECLARE
    mylon double precision; 
    mylat double precision; 
    lon1 float; 
    lon2 float; 
    lat1 float; 
    lat2 float;
    BEGIN
    raise notice 'help = %', p_userid; --just for testing

    select cr.last_known_longitude, cr.last_known_latitude 
    into mylon, mylat 
    from current_reg as cr 
    where cr.userid = p_userid;

    lon1 = mylon - 1 / abs(cos(radians(mylat))*69);
    lon2 = mylon + 1/abs(cos(radians(mylat))*69);
    lat1 = mylat - (1/69);
    lat2 = mylat + (1/69);

    return query 
       select destination.userid, 
       3956*2*asin(sqrt(power(sin((origin.last_known_latitude-destination.last_known_latitude)*pi()/180 / 2), 2) + cos(origin.last_known_latitude* pi()/180) * cos(destination.last_known_latitude* pi()/180) * power(sin((origin.last_known_longitude-destination.last_known_longitude) * pi()/180 /2), 2)))
       as distance 
       from current_reg as destination JOIN current_reg as origin 
       where origin.userid = p_userid
       and destination.last_known_longitude between lon1 and lon2 
       and destination.last_known_latitude between lat1 and lat2 
       having distance < 1 
       order by distance limit 5;

    END; 
    $$ LANGUAGE plpgsql;
    Select userid from testfunction(4);

我现在收到以下错误: 错误:语法错误在或附近&#34;其中&#34; 第29行:其中origin.userid = p_userid              ^

1 个答案:

答案 0 :(得分:3)

如果要返回查询结果,则需要在PL / pgSQL中使用return query。您不能在这样的DDL语句中使用变量。为每次调用函数创建一个视图是一个非常糟糕的主意。而且还有更多:第二次调用时,你的函数会失败,因为视图已经存在。

根据你所写的内容,我认为你想要这样的东西:

CREATE OR REPLACE FUNCTION testfunction (p_userid integer) 
  RETURNS table (userid integer, distance float) 
AS 
$$
DECLARE
  mylon double precision; 
  mylat double precision; 
  lon1 float; 
  lon2 float; 
  lat1 float; 
  lat2 float;
BEGIN
  raise notice 'help = %', p_userid; --just for testing

  select cr.last_known_longitude, cr.last_known_latitude 
      into mylon, mylat 
  from current_reg as cr 
  where userid = p_userid;

  lon1 = mylon - 1 / abs(cos(radians(mylat))*69);
  lon2 = mylon + 1/abs(cos(radians(mylat))*69);
  lat1 = mylat - (1/69);
  lat2 = mylat + (1/69);

  return query 
    select destination.userid, 
           3956*2*asin(sqrt(power(sin((origin.last_known_latitude-destination.last_known_latitude)*pi()/180 / 2), 2) + cos(origin.last_known_latitude* pi()/180) * cos(destination.last_known_latitude* pi()/180) * power(sin((origin.last_known_longitude-destination.last_known_longitude) * pi()/180 /2), 2))) as distance 
    from current_reg destination, 
         current_reg origin 
    where origin.userid = p_userid
      and destination.last_known_longitude between lon1 and lon2 
      and destination.last_known_latitude between lat1 and lat2 
    having distance < 1 
    order by distance limit 5;

END; 
$$ LANGUAGE plpgsql;
  1. 您想要返回查询结果,因此您的函数应声明为returns table
  2. 您可以为参数指定名称,无需通过复制代码来混淆代码。
  3. 要在PL / pgSQL中返回查询结果,您需要return query
  4. 要获得该函数的结果,请使用:

    select *
    from testfunction(1); 
    

    请注意,该函数位于FROM子句中,而不在SELECT列表中!

    仍然看起来可疑的事情:

    1. 您没有加入两个表from current_reg destination, current_reg origin在两者之间创建交叉加入。使用显式JOIN的另一个好例子比where子句
    2. 中的旧隐式连接更好
    3. 您正在使用having但未使用任何聚合