HSQLDB HSQLDB lässt mich nicht auf erstellte Tabelle zugreifen

Felix

Bekanntes Mitglied
Hallo,

in meinem Programm erstelle ich zuerst mal eine Tabelle in einer HSQL-Datenbank:

Java:
statement.execute("CREATE TABLE Vocables (index CHARACTER VARYING(12) NOT NULL PRIMARY KEY, germanimport CHARACTER VARYING(500) NOT NULL, foreignimport CHARACTER VARYING(500) NOT NULL, box SMALLINT DEFAULT 0, knowngf NUMERIC NOT NULL, unknowngf NUMERIC NOT NULL, knownfg NUMERIC NOT NULL, unknownfg NUMERIC NOT NULL, apposition TIMESTAMP DEFAULT LOCALTIMESTAMP, lastinterrogation TIMESTAMP);");

Das funktioniert auch super. Dann möchte ich Daten einfügen:

Java:
statement.executeUpdate("INSERT INTO \"Vocables\" (index, germanimport, foreignimport) VALUES ('" + index + "', '" + german + "', '" + foreign + "');");

Da kommt dann aber die Fehlermeldung:
Java:
java.sql.SQLException: user lacks privilege or object not found: Vocables
Wenn ich die Datenbank aber mit dem DatabaseManagerSwing, der bei der HSQLDB mitkommt, durchschaue, finde ich die Datenbank.

Ich verbinde mich mit der DB mit dem folgenden Code:
Java:
connection = DriverManager.getConnection("jdbc:hsqldb:file:/home/felix/voktrainer/db/VocablesDB;shutdown=true","SA","");

Ich versteh einfach nicht, wo das Problem liegt. Wäre nett, wenn ihr mir weiterhelfen könntet.

Grüße
Felix
 
Hallo,

das einzige, was ich mir grob vorstellen kann ist, dass deine Datenbank das erstellen der Tabelle in eine Transaktion packt.

Dein nächster aufruf erzeugt eine neue Transaktion und kann (ohne dirty read) nicht auf die Tabelle zugreifen.

Eventuell hat die Tabelle auch keinen korrekten owner, oder SA ist nicht berechtigt auf der Datenbank zu lesen.

Gruß,

Martin
 
Hallo,
danke erstmal für die Antworten und sorry, dass ich so lange auf mich warten ließ.
Also das schließen der Verbindung und des Statements (muss man Statements schließen?) bewirkt nichts.
Was mir allerdings jetzt aufgefallen ist, ist dass auch das DatabaseManagerSwing-Tool die Datenbank direkt nach dem erstellen nicht öffnen kann. Die Files, die die Datenbank bilden sind allerdings erstellt (geschieht ja automatisch). Das DatabaseManagerSwing gibt beim Versuch des Öffnens direkt nach dem Erstellen der Datenbank und der Tabelle durch mein Programm (Programm ist noch geöffnet) folgenden Fehler zurück:

Java:
java.sql.SQLException: Database lock acquisition failure: lockFile: org.hsqldb.LockFile@bb1c56bd[file = /home/felix/voktrainer/db/VocablesDB.lck, exsists=true, locked=false,valid=false, ] method: checkHeartbeat read: 2010-07-14 09:35:57 heartbeat - read: -8782ms.

Wenn das Programm geschlossen ist, kann das Tool die Datenbank (und die darin erstelle Tabelle) öffnen.
 
Ich hab das mal bei mir nachgebaut. Und ohne die Verbindung zu schließen hatte ich den selben Fehler. Als ich dann mal versucht hab die Verbindung zu schliessen und danach wieder ne neue zu öffnen und ein neues Statement erzeugt habe, gings.
Edit: Zu deinem Fehler, man kann nur einmal gleichzeitig auf die Datenbank zugreifen, der Fehler ist also normal.
 
Könntest du deinen Code mal online stellen? Vllt fällt mir ja beim Lesen deines Codes mein Fehler auf...
Danke schonmal!

EDIT:
Es erscheint die selbe Fehlermeldung, auch wenn ich die Tabelle und Datenbank vorher nicht erst erstellt habe, sondern diese von einem der vorherigen Testläufe des Programms noch bestehen.

EDITEDIT:
Ich habe jetzt lediglich den Namen der Tabelle von "Vocables" auf "VOCABLES" geändert, und es erscheint eine andere Fehlermeldung:
Java:
java.sql.SQLException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10030 table: VOCABLES
        at org.hsqldb.jdbc.Util.sqlException(Util.java:200)
        at org.hsqldb.jdbc.JDBCStatement.fetchResult(JDBCStatement.java:1805)
        at org.hsqldb.jdbc.JDBCStatement.executeUpdate(JDBCStatement.java:206)
 
Zuletzt bearbeitet:
Java:
Connection con = DriverManager.getConnection("jdbc:hsqldb:file:Z:/Datenbank/neu;shutdown=true", "SA", "");
PreparedStatement st = con.prepareStatement("CREATE TABLE Vocables (index INTEGER PRIMARY KEY, germanimport VARCHAR(500) NOT NULL, foreignimport VARCHAR(500) NOT NULL, box SMALLINT DEFAULT 0, knowngf NUMERIC, unknowngf NUMERIC, knownfg NUMERIC, unknownfg NUMERIC, apposition TIMESTAMP DEFAULT LOCALTIMESTAMP, lastinterrogation TIMESTAMP)");
st.execute();
st.close();
st = con.prepareStatement("INSERT INTO Vocables (index, germanimport, foreignimport) VALUES (?, ?, ?)");
st.setInt(1, 1);
st.setString(2, german);
st.setString(3, foreign);');");
st.executeUpdate();
st.close();
st = con.prepareStatement("SHUTDOWN");
st.execute();

So geht es jetzt bei mir. Hab noch n paar Sachen anders gemacht wie du, die nix an der Funktionalität ändern sollten:
- Hab ein PreparedStatement benutzt
- Hab als index n Integer genommen
- Und hab VARCHAR genommen
Was wichtig ist, ich hab bei den meisten Spalten das NOT NULL rausgenommen da du bei der Erstellung der Datenbank sagst dass diese Spalten NOT NULL sein dürfen, aber beim INSERT die Spalten sozusagen leerlässt, dadurch tritt auch der
Code:
NOT NULL check constraint;
Fehler auf.

Hoffe jetzt geht bei dir dann alles🙂
 
Uff, ich hab den Fehler endlich gefunden. Ich hatte bei den SQL-Befehl INSERT INTO Vocables das Vocables in Anführungszeichen gesetzt. Als ich die gelöscht hatte, hat es funktioniert. Bei PostgreSQL hat es allerdings auch mit den Anführungszeichen geklappt. Warum ist denn sowas nicht genormt??
Vielen Dank, ohne deinen Code wäre ich da vermutlich nie drauf gekommen.

Eine Frage hätte ich jetzt trotzdem noch. Ich möchte die Tabelle ja nur erstellen, wenn sie nicht schon besteht. Deshalb habe ich den Befehl zum erstellen in eine if-Anweisung eingebaut. Der Code sieht so aus:
Java:
ResultSet rs = connection.getMetaData().getTables(null, null, table, null);
            if (!rs.next()) {
                statement.execute("CREATE TABLE " + table + " (index CHARACTER VARYING(12) NOT NULL PRIMARY KEY, germanimport CHARACTER VARYING(500) NOT NULL, foreignimport CHARACTER VARYING(500) NOT NULL, box SMALLINT DEFAULT 0, knowngf NUMERIC, unknowngf NUMERIC, knownfg NUMERIC, unknownfg NUMERIC, apposition TIMESTAMP DEFAULT LOCALTIMESTAMP, lastinterrogation TIMESTAMP);");
                statement.close();

                //DEBUG
                System.out.println("Tabelle " + table + " angelegt...");
            }

Der Code funktioniert allerdings nicht, weil immer versucht wird die Tabelle zu erstellen. Warum das denn?
 
Java:
pfad = "jdbc:hsqldb:file:"+ System.getenv("ProgramFiles") +"\\DatenbankJAVA\\Adressbuch";
Connection con = null;
try {	
	con = DriverManager.getConnection(pfad);
	PreparedStatement pstmt = con.prepareStatement("SELECT * FROM ADRESSE");
	pstmt.execute();
	
	return con;
} catch (Exception e) {
	try {
		PreparedStatement pstmt = con.prepareStatement("CREATE MEMORY TABLE PUBLIC.ADRESSE(PERSONID INTEGER PRIMARY KEY," +
				"VORNAME VARCHAR(50),NACHNAME VARCHAR(50),STRASSE VARCHAR(50), PLZ VARCHAR(7)," +
				"ORT VARCHAR(50),TELEFON VARCHAR(50),HANDY VARCHAR(50),EMAIL VARCHAR(50),GEB VARCHAR(50),SONSTIGES VARCHAR(50))");
		pstmt.execute();
	} catch (SQLException e1) {
		
	}
	
}

Ich hab das bei einer Übungsaufgabe mal so gelöst. Erst einen SELECT Befehl ausgeführt, der falls die Tabelle noch nicht da ist in s catch springt und dort dann die Tabelle erzeugt. Hoff das kann dir helfen.

So noch n schönes Wochenende!
 
Bin mir jetzt nicht zu 100% sicher, obs SQL Standard ist, aber wie wäre es mit:

Java:
statement.execute("CREATE TABLE IF NOT EXISTS" + table + " (index CHARACTER VARYING(12) NOT NULL PRIMARY KEY, germanimport CHARACTER VARYING(500) NOT NULL, foreignimport CHARACTER VARYING(500) NOT NULL, box SMALLINT DEFAULT 0, knowngf NUMERIC, unknowngf NUMERIC, knownfg NUMERIC, unknownfg NUMERIC, apposition TIMESTAMP DEFAULT LOCALTIMESTAMP, lastinterrogation TIMESTAMP);");
 
Das hab ich auch schon im Internet gelesen, aber es scheint iwie nicht zu funktionieren. Es entsteht immer eine Exception:
Java:
java.sql.SQLException: unexpected token: NOT required: (
        at org.hsqldb.jdbc.Util.sqlException(Util.java:200)
        at org.hsqldb.jdbc.JDBCStatement.fetchResult(JDBCStatement.java:1805)
        at org.hsqldb.jdbc.JDBCStatement.execute(JDBCStatement.java:635)
        at voktrainer03.database.DBConnector.connect(DBConnector.java:27)
        at voktrainer03.Main.<init>(Main.java:49)
        at voktrainer03.Main.main(Main.java:31)
Caused by: org.hsqldb.HsqlException: unexpected token: NOT required: (
        at org.hsqldb.error.Error.parseError(Error.java:151)
        at org.hsqldb.ParserBase.unexpectedTokenRequire(ParserBase.java:765)
        at org.hsqldb.ParserBase.readThis(ParserBase.java:434)
        at org.hsqldb.ParserDDL.compileCreateTableBody(ParserDDL.java:1084)
        at org.hsqldb.ParserDDL.compileCreateTable(ParserDDL.java:1071)
        at org.hsqldb.ParserDDL.compileCreate(ParserDDL.java:150)
        at org.hsqldb.ParserCommand.compilePart(ParserCommand.java:205)
        at org.hsqldb.ParserCommand.compileStatements(ParserCommand.java:88)
        at org.hsqldb.Session.executeDirectStatement(Session.java:1133)
        at org.hsqldb.Session.execute(Session.java:939)
        at org.hsqldb.jdbc.JDBCStatement.fetchResult(JDBCStatement.java:1797)
        ... 4 more
 

Zurück
Oben