# Suche In SQL Datenbank mit array



## Sidet (19. Dez 2020)

Hallo,

ich habe in meinem Programm eine SQL Datenbank angelegt, die die Spalten "name", "phase" und einen primary key hat.

Ich will nun herausfinden, wie viele Einträge in dieser Datenbank zum einen:
- eine bestimmtePhase haben und gleichzeitig
- einen key haben, der in einem int[] Array enthalten ist.

Mein bisheriger Ansatz:

```
int [] array = new int[] {1,2,3,4,5};
String ids = array.toString();
ids.replace("[","(").replace("]",")");
int i = 2;
int count;
      
Cursor c = database.rawQuery("SELECT * FROM cards WHERE phase='"+i+"' AND type in "+ids+"",null);
if (c.moveToFirst()){
    count=c.getCount();
}else{
    count=0;
}
```

Der Fehler sieht dann so aus:
     Caused by: android.database.sqlite.SQLiteException: no such table: 1, 2, 3, 4, 5 (code 1): , while compiling: SELECT * FROM cards WHERE phase='1' AND type in [1, 2, 3, 4, 5]

Jetzt wären meine Fragen: 
 1. Wie kann ich prüfen, ob der Eintrag "phase" der Datenbank im array enthalten ist?
 2. Gibt es eine elegantere Methode die Anzahl der passenden Einträge festzustellen? So wie es hier steht funktioniert es zwar (ohne den AND Zusatz in der Query), aber es kommt mir etwas klobig vor...

Schonmal vielen Dank für Eure Zeit und Hilfe


----------



## krgewb (19. Dez 2020)

SELECT COUNT(*) FROM Tabellenname...


----------



## Sidet (19. Dez 2020)

krgewb hat gesagt.:


> SELECT COUNT(*) FROM Tabellenname...


Danke für die Antwort.
Bin leider sehr unerfahren mit SQL, würde man dann auch mit einem Cursor arbeiten? Oder wie würde der vollständige Code aussehen?


----------



## kneitzel (19. Dez 2020)

Nein, Cursor wird bitte immer vermieden, wenn es irgendwie geht. Das Killt die Performance massiv.

Wenn DU SQL Abfragen machen willst, dann solltest Du Dir da zumindest die Grundlagen aneignen.
@krgewb hat Dir gezeigt, wie Du die Anzahl von Datensätzen ermitteln kannst.

In Deinem SQL müssten die Werte in Klammern kommen also "type in (1, 2, 3, 4)" oder so. 

*ABER:*
Die SQL Abfrage selbst solltest Du generell nicht so zusammen bauen aus Strings. Dazu gibt es PreparedStatement und Du willst die beiden Parameter in einem PreparedStatement mitgeben. Da könnte dann ggf. auch die Methode createArrayOf von Connection interessant sein.


			Connection (Java SE 11 & JDK 11 )
		



			PreparedStatement (Java SE 11 & JDK 11 )
		


Und als Einführung evtl.:








						JDBC PreparedStatement
					

The JDBC PreparedStatement class can parameterize your SQL statements, so they can be reused again with different parameter values. This JDBC PreparedStatement tutorial explains how to use and reuse a PreparedStatement.



					tutorials.jenkov.com


----------



## Dukel (19. Dez 2020)

Als weiteren Tipp (sonst gewöhnt man sich das an): Kein "SELECT *" nutzen sondern die Spalten angeben.


----------



## mihe7 (19. Dez 2020)

Eine standardkonforme Lösung *wäre* etwas wie:


```
private static String QUERY = "SELECT count(*) FROM cards WHERE phase=? AND type = ANY(?)";
private Connection conn;

public long count() throws SQLException {
    try(PreparedStatement stmt = conn.prepareStatement(QUERY)) {
        stmt.setInt(1, phase);
        stmt.setArray(2, conn.createArrayOf("INTEGER", array);
        try(ResultSet rs = stmt.executeQuery()) {
            return rs.getLong(1);
        }
    }
}
```

Allerdings unterstützen das nicht alle DBMS bzw. JDBC-Treiber. Alternativ kann man statt "= ANY(?)" auch "IN (?)" versuchen und dann im Code mit setObject statt mit setArray arbeiten: `stmt.setObject(2, array);`. Das dürfte zumindest in MySQL funktionieren. Daneben gibt es dann noch DBMS-spezifische Varianten.

So lange die Zahl der Parameter überschaubar bleibt, kann man auch eine geeignete Query zusammenbauen, also "IN (?, ?, ? ...)" schreiben, wobei das Auslassungszeichen natürlich du eine entsprechende Zahl an ", ?" zu ersetzen wäre. Dann muss auch jeder Parameter gesetzt werden, also etwas wie


```
int param = 2;
for (int value : array) {
    stmt.setInt(param, value);
    param++;
}
```

verwendet werden. Das wärs erstmal.


----------



## Sidet (20. Dez 2020)

Vielen Dank für die Antworten, werde mich wohl etwas intensiver mit SQL auseinandersetzen.


----------

