Hi,
Im am building a dictionary database using SQLite under B4J, and having problems getting an SQL statement usingt an ON CONFLICT clause to work.
Still getting used to B4J, and SQLite too, but it looks like a good pair of tools.
Note that in the code below I am just using SQL, then running it under B4J with the SQL command SQL.ExecNonQuery(query)
I know how to create the SQL strings using StringBuilder and the utilities in the DBUtils module
That works fine to create the table, note the UNIQUE command to limit insertions to unique words
Then if I do:
That works fine.
But of course if I do the same INSERT again, it fails because of the UNIQUE constraint - that is what I want
However if I use
Then I get a huge pile of Java errors:
Table size 4
*** p_word: B4XPage_Appear [mainpage]
*** p_word: B4XPage_Resize [mainpage, p_word]
INSERT INTO tblWords (word,Length) VALUES ("test5",5) ON CONFLICT DO NOTHING
Error occurred on line: 884 (m_word)
java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (near "ON": syntax error)
at org.sqlite.DB.newSQLException(DB.java:383)
at org.sqlite.DB.newSQLException(DB.java:387)
at org.sqlite.DB.throwex(DB.java:374)
at org.sqlite.NativeDB.prepare(Native Method)
at org.sqlite.DB.prepare(DB.java:123)
at org.sqlite.Stmt.execute(Stmt.java:113)
at anywheresoftware.b4j.objects.SQL.ExecNonQuery(SQL.java:161)
at wordle.database.m_word._btntest_click(m_word.java:753)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:629)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:234)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
at anywheresoftware.b4a.BA$1.run(BA.java:236)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(Native Method)
I tried the same SQL on a little SQLIte DBBrowser program, and it works perfectly. But I know there are many flavours of SQLIte. Does the version used by the B4J system allow this ?
I know I can use a variation like this:
and it works. But it has the drawback that it actually removes the old record, then creates a new one, with a new recordID. When doing this repeatedly on a large collection of long word lists, it takes extra processing time, which seems to me a waste when the ON CONFLICT clause should just skip the INSERT.
SQLite library jSQL version 1.61
B4J version 9.80
Any comments would be appreciated.
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:834)
Im am building a dictionary database using SQLite under B4J, and having problems getting an SQL statement usingt an ON CONFLICT clause to work.
Still getting used to B4J, and SQLite too, but it looks like a good pair of tools.
Note that in the code below I am just using SQL, then running it under B4J with the SQL command SQL.ExecNonQuery(query)
I know how to create the SQL strings using StringBuilder and the utilities in the DBUtils module
Table creation:
CREATE TABLE "tblWords" (
"wordID" INTEGER,
"word" TEXT,
"Length" INTEGER,
"Plural" INTEGER,
"Proper" INTEGER,
UNIQUE("word"),
PRIMARY KEY("wordID")
);
Then if I do:
Insert to table:
INSERT INTO tblWords (word,Length) VALUES ("test5",5)
But of course if I do the same INSERT again, it fails because of the UNIQUE constraint - that is what I want
However if I use
B4X:
INSERT INTO tblWords (word,Length) VALUES ("test5",5) ON CONFLICT DO NOTHING
Table size 4
*** p_word: B4XPage_Appear [mainpage]
*** p_word: B4XPage_Resize [mainpage, p_word]
INSERT INTO tblWords (word,Length) VALUES ("test5",5) ON CONFLICT DO NOTHING
Error occurred on line: 884 (m_word)
java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (near "ON": syntax error)
at org.sqlite.DB.newSQLException(DB.java:383)
at org.sqlite.DB.newSQLException(DB.java:387)
at org.sqlite.DB.throwex(DB.java:374)
at org.sqlite.NativeDB.prepare(Native Method)
at org.sqlite.DB.prepare(DB.java:123)
at org.sqlite.Stmt.execute(Stmt.java:113)
at anywheresoftware.b4j.objects.SQL.ExecNonQuery(SQL.java:161)
at wordle.database.m_word._btntest_click(m_word.java:753)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:629)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:234)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
at anywheresoftware.b4a.BA$1.run(BA.java:236)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(Native Method)
I tried the same SQL on a little SQLIte DBBrowser program, and it works perfectly. But I know there are many flavours of SQLIte. Does the version used by the B4J system allow this ?
I know I can use a variation like this:
Insert or Replace:
INSERT OR REPLACE INTO tblWords (word,Length) VALUES ("test5",5)
SQLite library jSQL version 1.61
B4J version 9.80
Any comments would be appreciated.
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:834)
Last edited: