1

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");
        }

以下は、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;

Java でコードを実行すると、print ステートメントは Car found の null 値を出力します。ここで助けていただければ幸いです。

4

1 に答える 1

6

問題

  • 最も重要なことは、 のクエリLOOPがナンセンスであることです。から行を選択しcarinstanceましたが、すべての条件がオンになっていrecます。これにより、すべての行が複数回選択されます。

  • 1 つEND多すぎます。FORはありません。ENDあるだけLOOPです。

  • plpgsql で明示カーソルを使用したいという誘惑に駆られたら、すぐにやめてください。間違っている可能性があります。FORとにかく、ループには暗黙のカーソルがあります。

  • 二重引用符なしで大文字と小文字が混在する識別子をいじらないでください。すべての識別子を小文字に変換しました。

  • 単純なクエリを 1 つ使用し、カーソルと別のクエリに広げます。これはすべてはるかに簡単です。

解決

代わりに、次の単純な 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;

電話:

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

または、すべてを関数に組み込みます。

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;

電話:

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

注意:OUTパラメータlicense_plateは、関数本体のどこにでも表示されます。したがって、名前の競合を防ぐために、常に同じ名前の列をテーブル修飾する必要があります。

DISTINCT冗長な場合とそうでない場合があります。

于 2013-03-18T18:43:35.417 に答える