从Java调用PostgreSQL中的存储过程

ueg*_*990 1 java sql postgresql stored-procedures plpgsql

我编写了一个存储过程,我想用Java调用它.但我不认为它能够对我通过的查询做任何事情.以下是我的java代码:

String QUERY_LOCATION = "select (license_plate) as test from carInst( (select     category_name from reservation where rid = ?) , (select lname from reservation where rid =  ?))";  
        //PreparedStatement check_location = null;
        PreparedStatement check_location = connection.prepareStatement(QUERY_LOCATION);
        check_location.setInt(1, rid);
        check_location.setInt(2, rid);
        rs = check_location.executeQuery();
        if (rs.next()) {
            System.out.print("Car found: "+rs.getString("test")+"\n");
            license_plate = rs.getString("test");
            update_reservation.setString(5, license_plate);

            bool = false;
        } else {
            System.out
                    .print("There is no car available\n");
        }
Run Code Online (Sandbox Code Playgroud)

以下是我用PL/pgSQL(PostgreSQL)编写的存储过程:

CREATE OR REPLACE FUNCTION carInst(cname varchar(20), loc varchar(20) ) 
RETURNS TABLE (license_plate varchar(6) ) AS $$
BEGIN 
    DECLARE cur CURSOR 
        FOR SELECT carinstance.license_plate, carmodel.category_name, carinstance.lname FROM carinstance,carmodel 
            WHERE carinstance.mid = carmodel.mid ;                  
BEGIN 
    FOR rec IN cur LOOP
        RETURN QUERY SELECT distinct carinstance.license_plate FROM Carinstance 
            WHERE rec.category_name  = cname
                AND rec.lname = loc
                AND rec.license_plate=carinstance.license_plate;
        END LOOP;
    END; 
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

当我在Java中运行代码时,print语句为Car found打印一个空值.我真的很感激这里的一些帮助.

Erw*_*ter 6

问题

  • 最重要的是,查询中的LOOP含义是无稽之谈.您可以从中选择行carinstance,但所有条件都已启用rec.这会多次选择所有行.

  • 一个END太多了.FOR没有END,只有LOOP.

  • 每当你感觉到在plpgsql中使用显式游标的诱惑时,请在那里停下来.机会是,你做错了.一个FOR循环有一个隐式游标反正.

  • 不要在没有双引号的情况下混淆大小写标识符.我将所有标识符转换为小写.

  • 您使用一个简单的查询,分散在游标和另一个查询上.这一切都可以简单得多.

请尝试使用这个简单的SQL函数:

CREATE OR REPLACE FUNCTION car_inst(_cname text, _loc text) 
  RETURNS TABLE (license_plate text) AS
$func$
   SELECT DISTINCT ci.license_plate
   FROM   carmodel    cm
   JOIN   carinstance ci USING (mid)
   WHERE  cm.category_name  = $1
   AND    ci.lname = $2
$func$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)

呼叫:

"SELECT license_plate AS test FROM car_inst(
         (SELECT category_name FROM reservation WHERE rid = ?)
        ,(SELECT lname FROM reservation WHERE rid = ?))";  
Run Code Online (Sandbox Code Playgroud)

或者将它全部构建到您的函数中:

CREATE OR REPLACE FUNCTION car_inst(_cname text, _loc text) 
  RETURNS TABLE (license_plate text) AS
$func$
   SELECT DISTINCT ci.license_plate
   FROM   carmodel    cm
   JOIN   carinstance ci USING (mid)
   JOIN   reservation r1 ON r1.category_name = cm.category_name
   JOIN   reservation r2 ON r2.lname = ci.lname
   WHERE  r1.rid = $1
   AND    r2.rid = $2;
$func$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)

呼叫:

"SELECT license_plate AS test FROM car_inst(? , ?)";  
Run Code Online (Sandbox Code Playgroud)

请记住:该OUT参数license_plate在函数体中的任何位置都可见.因此,您必须始终对同名列进行表限定,以防止命名冲突.

DISTINCT 可能是也可能不是多余的.