javasqlsqlitesqlitejdbc

Java: SQLite parameter filling in a PreparedStatement results in an error


I am trying to read data from a SQL database from Java using SQLite-JDBC, but upon filling parameters to a PreparedStatement I am getting an error. Important parts of the code and the error are below.

        Scanner scanner = new Scanner(System.in);
        Connection db = DriverManager.getConnection("jdbc:sqlite:kurssit.db");
        Statement s = db.createStatement();
        PreparedStatement p;
                        p = db.prepareStatement("SELECT SUM(K.laajuus) "
                                + "FROM Suoritukset S, Kurssit K "
                                + "WHERE S.kurssi_id = K.id AND S.paivays LIKE '" + "?" + "%';");
                        p.setString(1, scanner.nextLine());
                        try {
                            ResultSet r = p.executeQuery();
                            System.out.println("Amount: " + r.getString(1));
                        } catch (SQLException e) {
                            System.out.println("Data not found.");
                        }
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
    at org.sqlite.core.CorePreparedStatement.batch(CorePreparedStatement.java:121)
    at org.sqlite.jdbc3.JDBC3PreparedStatement.setString(JDBC3PreparedStatement.java:421)
    at Main.main(Main.java:28)
C:\Users\user\AppData\Local\NetBeans\Cache\12.0\executor-snippets\run.xml:111: The following error occurred while executing this line:
C:\Users\user\AppData\Local\NetBeans\Cache\12.0\executor-snippets\run.xml:68: Java returned: 1

The line 28, the line of the error, is in this shortened version of the code the one saying p.setString(1, scanner.nextLine());.

//Imports
import java.sql.*;
import java.util.*;

Many thanks in advance.


Solution

  • The sql statement is not constructed correctly.
    The ? placeholder must not be inside single quotes, because if it is then it is not considered as a placeholder but just a string.
    It will be replaced properly by a string after setString().
    Change to this:

    p = db.prepareStatement(
      "SELECT SUM(K.laajuus) FROM Suoritukset S, Kurssit K WHERE S.kurssi_id = K.id AND S.paivays LIKE ? || '%';"
    );
    

    As a side note, you should use proper join syntax:

    p = db.prepareStatement(
      "SELECT SUM(K.laajuus) FROM Suoritukset S INNER JOIN Kurssit K ON S.kurssi_id = K.id WHERE S.paivays LIKE ? || '%';"
    );