简体   繁体   English

从Java在PostgreSQL中调用存储过程

[英]Calling a stored procedure in PostgreSQL from Java

I have written a stored procedure that I would like to call in Java. 我已经编写了一个要在Java中调用的存储过程。 But I don't think it is able to do anything with the query that I passed. 但是我认为它不能对我传递的查询执行任何操作。 Following is my code from 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");
        }

And following is my stored procedure written in PL/pgSQL (PostgreSQL): 以下是我用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;

When I run the code in Java, the print statement prints a null value for Car found. 当我用Java运行代码时,print语句为找到的Car打印一个空值。 I would really appreciate some help here. 我非常感谢您的帮助。

Problems 问题

  • Most importantly, the query in the LOOP is nonsense. 最重要的是, LOOP的查询是胡说八道。 You select rows from carinstance , but all conditions are on rec . 您可以选择从行carinstance ,但各方面条件都在rec This select all rows multiple times. 多次选择所有行。

  • One END too many. 一个END太多。 FOR has no END , only LOOP has. FOR没有END ,只有LOOP有。

  • Whenever you feel the temptation to work with an explicit cursor in plpgsql, stop right there. 每当您想使用plpgsql中的显式游标的诱惑时,请就此停下来。 Chances are, you are doing it wrong. 可能是,您做错了。 A FOR loop has an implicit cursor anyway. 无论如何, FOR循环都有一个隐式游标。

  • Don't mess with mixed case identifiers without double quotes . 不要弄混没有双引号的大小写混合的标识符 I converted all identifiers to lower case. 我将所有标识符都转换为小写。

  • You use one simple query, spread out over a cursor and another query. 您使用一个简单的查询,分布在游标上,另一个查询。 This can all be much simpler. 这一切都可能更加简单。

Solution

Try this simple SQL function instead: 请尝试使用以下简单的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;

Call: 呼叫:

"SELECT license_plate AS test FROM car_inst(
         (SELECT category_name FROM reservation WHERE rid = ?)
        ,(SELECT lname FROM reservation WHERE rid = ?))";  

Or build it all into your function: 或将其全部构建到您的函数中:

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;

Call: 呼叫:

"SELECT license_plate AS test FROM car_inst(? , ?)";  

Remember: The OUT parameter license_plate is visible anywhere in the body of the function. 切记: OUT参数license_plate在函数主体中的任何位置都可见。 Therefore you must table-qualify the column of the same name at all times to prevent a naming collision. 因此,您必须始终对具有相同名称的列进行表限定,以防止命名冲突。

DISTINCT may or may not be redundant. DISTINCT可能是冗余,也可能不是冗余。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM