1

データベースからレコードを取得するプログラムを作成しています。3 つの変数 (studentID、firstName、および/または lastname) に基づいて動的クエリを作成したいと考えています。レコードを返す私のJavaコードは次のとおりです。

result = statement.executeQuery("SELECT * FROM student "
        + "WHERE (studentID = "
        + getStudentId() + " AND " + getStudentId() + " <> 0)"
        + " OR (firstName = '"
        + getFirstName() + "' AND '" + getFirstName() + "' IS NOT NULL)"
        + " OR (lastName = '"
        + getLastName() + "' AND '" + getLastName() + "' IS NOT NULL)");

私が望むのは、検索で、存在する変数に基づいて特定のあいまいな結果が返されることです。現在、提供されているフィールドが StudentID のみの場合、その単一のレコードを返すか、studentID が存在しないが firstName が存在する場合、firstName ごとにすべてのレコードを返します (変数のみが存在する場合、lastName についても同じです)。うまくいかないのは、firstName と lastName を指定すると、レコードの姓に関係なく firstName を持つすべてのレコードと、名に関係なく lastName を持つすべてのレコードが返されることです。例 firstName = "Bill" および lastName = "Jackson":

1  Bill Hader
2  Steve Jackson
3  Bill Jackson
4  Bill Stewart
5  Denise Jackson
6  Wendy Jackson
7  Bill Matthews

私が把握しようとしているのは、firstName や lastName などの特定の条件を指定して、指定された名と姓の両方を含む特定のレコードを取得する方法です。

4

3 に答える 3

1

A)これでうまくいくはずです:

String query = "SELECT * FROM student WHERE (studentID=? OR ?=0) 
                                        AND (firstName=? OR ? IS NULL)
                                        AND (lastName =? OR ? IS NULL)";
ps.setInt(1,getStudentID());
ps.setString(2,getFirstName());
ps.setString(3,getFirstName());
result ps.executeQuery();

ロジックは投稿したものとは逆であることに注意してください。コードでstudentIdis0firstNameis null の場合、次のようになります。

(studentID=0 AND 0<>0) OR (firstName='null' OR null IS NOT NULL)

ですfalse。代わりに指定する必要があります

(studentID=0 OR 0=0) AND (firstName='null' OR null IS NULL)

B) Java で条件付きロジックが必要な場合:

String query = "SELECT * FROM student WHERE (";
if (getStudentId()!=0) query+="studentID=? AND";
if (getFirstName()!=null) query+="firstName=? AND";
if (getLastName ()!=null) query+="lastName=?  AND";
query+=" 1=1)";
PreparedStatement ps = connection.prepare(query);
if (getStudentId()!=0)    ps.setInt(1,getStudentID());
if (getFirstName()!=null) ps.setString(2,getFirstName());
if (getLastName ()!=null) ps.setString(3,getFirstName());
result ps.executeQuery();
于 2013-03-13T12:10:06.860 に答える
0

したがって、基準が 0、「Bill」、および「Jackson」であると仮定すると、これは実行するクエリです。

select *
from student
where 
   (studentID = 0 and 0 <> 0)
or (firstName = 'Bill' and 'Bill' is not null)
or (lastName = 'Jackson' and 'Jackson' is not null)

あなたのwhere句には3つの条件があります。最初のもの (ここでも、0 を入力したと仮定します) は、何にも一致しません。firstName2 番目は、 'Bill'であるすべてのレコードに一致します。lastName3 番目は、 'Jackson'であるすべてのレコードに一致します。条件がor演算子によって結合されているため、結果のセット (クエリ結果) は一致したすべてのセットの和集合になるため、firstName「Bill」またはlastName「Jackson」のレコード、つまりすべてのサンプル レコードになります。これを 1 つの名と姓だけに制限したい場合は、 を に変更orandてクエリを簡素化します。

select *
from student
where 
    firstName = 'Bill' 
and lastName = 'Jackson'

単一の where 句にあまりにも多くのロジックを構築しようとしているようです。さて、これはどのように行うことができますか?フィールドを 1 分間そのままにしておくstudentIDと、正確な名前 (提供されている場合) と正確な姓 (提供されている場合) のみを一致させる必要があります。これを使用してそれを行うことができます:

select *
from student
where
    (firstName = ? or ? is null)
and (lastName =  ? or ? is null)

最後に、あなたが望むと思われるもう 1 つの条件は、学生 ID が提供された場合、結果をその ID のみに制限することです。これを使用してそれを行うことができます:

select *
from student
where
    (studentID = ? and ? <> 0)
or (
      (firstName = ? or ? is null)
  and (lastName =  ? or ? is null)
)

簡単にするために、これは、姓または名が一致しない場合でも、特定の学生 ID に一致する行を常に返すことを前提としています。(したがって、パラメーター 1、'Bill'、'Jackson' で実行すると、2 つのレコードが生成されます)。代わりに を使用して、studentID3 つの条件すべてに一致しないレコードを削除する場合は、クエリを次のように変更します。

select *
from student
where
    (studentID = ? or ? = 0)
and  (
      (firstName = ? or ? is null)
  and (lastName = ? or ? is null)
)

これがどのように機能するかを示すSQLFiddleです。

他の人が言及したように、Java でパラメーター化されたクエリを使用する方法を学んでください。それは難しいことではありません。

于 2013-03-13T12:22:58.977 に答える
0

この質問に示されているようにクエリ ビルダー APIを使用することは、複雑な動的 SQLを実現するための最良の方法である可能性があります。動的 SQL を構築するための一般的な API は次のとおりです。

動的 JPQL を構築するための一般的な API は次のとおりです。

質問に jOOQ を使用する例は次のとおりです。

Condition condition = DSL.trueCondition();
if (getStudentId() != 0)
    condition = condition.and(STUDENT.STUDENTID.eq(getStudentId()));
if (getFirstName() != null)
    condition = condition.and(STUDENT.FIRSTNAME.eq(getFirstName()));
if (getLastName() != null)
    condition = condition.and(STUDENT.LASTNAME.eq(getLastName()));

Result<StudentRecord> result =
DSL.using(configuration)
   .selectFrom(STUDENT)
   .where(condition);

(免責事項:私はjOOQの背後にある会社で働いています)

于 2018-05-11T09:48:59.067 に答える