2017-02-14 3 views
0

Ich habe ein JAVAFX-Projekt mit HSQLDB. Wenn ich versuche, die QUELLE einer Tabelle zu setzen, bekomme ich eine Ausnahme, von der ich denke, dass ich sie verstehe, aber da ich sie nicht beheben kann, denke ich, dass ich sie nicht verstehe. My SQL ist:HSQLDB unerwartetes Token :?

DROP TABLE temp IF EXISTS; 
CREATE TEXT TABLE temp(text_data LONGVARCHAR(10000)); 
SET TABLE temp SOURCE ?; 
INSERT INTO log(typ, json) SELECT SUBSTRING(text_data, 3, LOCATE('"', text_data, 3)-3),text_data FROM temp WHERE text_data <> ''; 
DROP TABLE temp IF EXISTS; 

Mutliple Statements für mich irgendwie nicht hier arbeiten, und dies sollte kein Problem für jetzt sein. Ich spalte die obige SQL in eine ArrayList von Strings, wobei jede Zeile ein Element ist. Also habe ich diesen Java-Code:

s = c.createStatement(); 
for (String sql : sqls) { 
    System.out.println("sql: " + sql); 
    if (sql.contains("?")) { 
    System.out.println("in ? part"); 
    PreparedStatement ps = c.prepareStatement(sql); 

    ps.setString(1, path.toUri().toString() + ";encoding=UTF-8;ignore_first=false;fs=\\n\\r"); 
    System.out.println("ps prepared" + ps.toString()); 
    ps.execute(); 
    } else { 
    s.execute(sql); 
    } 
} 

Und meine Anwendung ist in Zeile PreparedStatement ps = c.prepareStatement(sql); mit folgenden Ausnahme Fehler:

java.sql.SQLSyntaxErrorException: unexpected token: ? in statement [SET TABLE temp SOURCE ?;] 
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) 
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) 
    at org.hsqldb.jdbc.JDBCPreparedStatement.<init>(Unknown Source) 
    at org.hsqldb.jdbc.JDBCConnection.prepareStatement(Unknown Source) 
    at myfile in the line I pointed out above 
    at anotherofmyfiles 
    at javafx.concurrent.Task$TaskCallable.call(Task.java:1423) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: org.hsqldb.HsqlException: unexpected token: ? 
    at org.hsqldb.error.Error.parseError(Unknown Source) 
    at org.hsqldb.ParserBase.unexpectedToken(Unknown Source) 
    at org.hsqldb.ParserBase.checkIsValue(Unknown Source) 
    at org.hsqldb.ParserBase.readQuotedString(Unknown Source) 
    at org.hsqldb.ParserCommand.compileTableSource(Unknown Source) 
    at org.hsqldb.ParserCommand.compileSetTable(Unknown Source) 
    at org.hsqldb.ParserCommand.compileSet(Unknown Source) 
    at org.hsqldb.ParserCommand.compilePart(Unknown Source) 
    at org.hsqldb.ParserCommand.compileStatement(Unknown Source) 
    at org.hsqldb.Session.compileStatement(Unknown Source) 
    at org.hsqldb.StatementManager.compile(Unknown Source) 
    at org.hsqldb.Session.execute(Unknown Source) 
    ... 7 more 

mit dieser Ausgabe vor:

sql: DROP TABLE temp IF EXISTS; 
sql: CREATE TEXT TABLE temp(text_data LONGVARCHAR(10000)); 
sql: SET TABLE temp SOURCE ?; 
in ? part 

Ich bin mir bewusst, dass ps.setString(1, path.toUri().toString() + ";encoding=UTF-8;ignore_first=false;fs=\\n\\r"); möglicherweise nicht vollständig in der Semantik korrekt, aber syntaxweise sollte es funktionieren, und da der Fehler davor ist, sollte es keine Ursache für diesen Fehler sein. Wenn ich die Anwendung ohne diese Zeile ausführe, tritt derselbe Fehler auf.

Also meine Frage ist: Was ist los mit SET TABLE temp SOURCE ?;? Warum kann ich das nicht als PreparedStatement in Java verwenden? Wie ich aus der documentation verstehe, ist die Syntax SET TABLE <tablename> SOURCE <quoted_filename_and_options>, wobei <quoted_filename_and_options> eine Zeichenfolge ist. Kann ich das in Java vorbereiten?

Antwort

1

PreparedStatements werden zur Kompilierung an die zugrunde liegende SQL-Engine gesendet. Der Ort, an dem Sie Parameter verwenden dürfen, hängt vom Treiber und der Engine ab. In der Regel werden sie nur an ganz bestimmten Stellen unterstützt, da sonst eine Aussage nicht wirklich kompiliert werden kann.

Betrachten wir ein PreparedStatement, die nur enthält, und Sie liefern einen Parameter "?":

ps.setString(1, "SELECT * FROM myTable"); 

Dies kann nicht kompiliert werden, so wird sie abgelehnt.

Daher unterstützen die meisten SQL-Datenbanken nur Parameter in INSERT/UPDATE/SELECT in Positionen, wo normalerweise ein einfacher Wert erscheint. Sie können nicht für Feldnamen, Tabellennamen usw. verwendet werden.

+0

Das ist ein guter Punkt, danke. Ich denke, ich werde dies als Antwort markieren, da Sie meine Frage beantwortet haben. Haben Sie einen Vorschlag, wie Sie die QUELLE für die Tabelle als Parameter einstellen? – Sebu

+0

Nun, der offensichtliche Ansatz, das '' 'selbst zu ersetzen, würde funktionieren, aber Sie können SQL-Injection-Angriffe offenlassen, abhängig davon, woher dieser String kommt. Sie müssen die Eingabe zuerst bereinigen, um sicherzustellen, dass sie nicht für solche Zwecke verwendet werden kann. Die übliche Vorgehensweise besteht darin, das einzuschränken, was Sie beispielsweise mit einer Regex eingeben dürfen. – john16384

+0

Das funktioniert für mich. Vielen Dank, John – Sebu