DBUtils is a set of helper methods. You can build the table directly with SQL.ExecuteNonQuery and set the foreign key or the multi-column primary key. It will be simpler than adding a general CreateTable method that tries to handle all cases.
Sub CreateDataBase
Dim Query As String
Query = "CREATE TABLE persons (ID INTEGER, PRIMARY KEY(FirstName TEXT, LastName TEXT), City TEXT)"
SQL1.ExecNonQuery(Query)
End Sub
CREATE TABLE persons (ID INTEGER, FirstName TEXT, LastName TEXT, City TEXT, PRIMARY KEY(FirstName, LastName))
CREATE TABLE persons (ID INTEGER, FirstName TEXT, LastName TEXT, City TEXT, PRIMARY KEY(ID, City))
It is probably better to use an external tool.
These are correct:
B4X:CREATE TABLE persons (ID INTEGER, FirstName TEXT, LastName TEXT, City TEXT, PRIMARY KEY(FirstName, LastName)) CREATE TABLE persons (ID INTEGER, FirstName TEXT, LastName TEXT, City TEXT, PRIMARY KEY(ID, City))
Has anyone got referential integrity to work?
I have set up a small database as described here http://www.sqlite.org/foreignkeys.html.
But I am still allowed to delete a record on the main file which has children on the second file.
I have set up the foreign key on the second file and done the SQL.ExecNonQuery("PRAGMA foreign_keys = ON") bit.
Does anyone know if it is possible that I don't have the right version of SQL?
Dim R As Reflector
R.Target = oSQL
R.Target = R.GetField("db")
R.Runmethod2("setForeignKeyConstraintsEnabled",True,"java.lang.boolean")
Sub Process_Globals
'These global variables will be declared once when the application starts.
'These variables can be accessed from all modules.
Dim oSQL As SQL
End Sub
Sub Globals
'These global variables will be redeclared each time the activity is created.
'These variables can only be accessed from this module.
End Sub
Sub Activity_Create(FirstTime As Boolean)
Dim oCursor As Cursor
Dim cntr As Int
Dim R As Reflector
File.Copy(File.DirAssets,"fkeytest.db",File.DirDefaultExternal,"fkeytest.db")
oSQL.Initialize(File.DirDefaultExternal,"fkeytest.db",True)
Dim R As Reflector
R.Target = oSQL
R.Target = R.GetField("db")
R.Runmethod2("setForeignKeyConstraintsEnabled",True,"java.lang.boolean")
oCursor = oSQL.ExecQuery("PRAGMA foreign_keys")
oCursor.Position = 0
Log("foreign_keys = " & oCursor.GetString2(0))
oCursor = oSQL.ExecQuery("Select * from orderdetails where ordernumber = 10103")
Log("No Rows For Orderdetails where ordernumber = 10103: " & oCursor.RowCount)
oCursor = oSQL.ExecQuery("Select * from orders where ordernumber = 10103")
Log("No. Rows For Orders where ordernumber = 10103: " & oCursor.RowCount)
Log("Deleteteing OrderNumber 10103")
oSQL.ExecNonQuery("DELETE FROM ORDERS WHERE ordernumber = 10103")
oCursor = oSQL.ExecQuery("Select * from orderdetails where ordernumber = 10103")
Log("No. Rows For Orderdetails where ordernumber = 10103: " & oCursor.RowCount)
oCursor = oSQL.ExecQuery("Select * from orders where ordernumber = 10103")
Log("No. Rows For Orders where ordernumber = 10103: " & oCursor.RowCount)
End Sub
foreign_keys = 1
No Rows For Orderdetails where ordernumber = 10103: 16
No. Rows For Orders where ordernumber = 10103: 1
Deleteteing OrderNumber 10103
No. Rows For Orderdetails where ordernumber = 10103: 0
No. Rows For Orders where ordernumber = 10103: 0
KeirS could I trouble you just one more time to cast your eye over this?
SQL.ExecNonQuery("CREATE TABLE Bosses (bossno INTEGER PRIMARY KEY , desc TEXT, sdate TEXT, ssos int, ddate TEXT, dsos int, actioned TEXT,notes TEXT,adate TEXT, atime TEXT, asos int ,cdate TEXT, ctime TEXT, csos int,device text,ccmail text,importance text)")
SQL.ExecNonQuery("CREATE TABLE Bosssubs (bosssubno INTEGER PRIMARY KEY , bossno int, desc TEXT, bdate TEXT, btime TEXT, foreign key(bossno) REFERENCES Bosses(bossno) on delete RESTRICT)")
This is how I Have created my database in a B4A program. I am able to for example to delete a record on Bosses where bossno = 123 even if there is a record on Bosssubs where bossno = 123.
After running this code that you gave me foreign key = 1 is logged.
Dim R As Reflector
R.Target = SQL
R.Target = R.GetField("db")
R.Runmethod2("setForeignKeyConstraintsEnabled",True,"java.lang.boolean")
oCursor = oSQL.ExecQuery("PRAGMA foreign_keys")
oCursor.Position = 0
Log("foreign_keys = " & oCursor.GetString2(0))
Can you perhaps think of someting else that should be set?
Many thanks.
CREATE TABLE Bosssubs (bosssubno INTEGER PRIMARY KEY , bossno int REFERENCES Bosses(bossno) on delete RESTRICT, desc TEXT, bdate TEXT, btime TEXT)
CREATE UNIQUE INDEX bosses_bossno ON bosses ( bossno COLLATE BINARY ASC )
CREATE INDEX bosssubs_bossno ON bosssubs ( bossno COLLATE BINARY ASC )
Sub Process_Globals
'These global variables will be declared once when the application starts.
'These variables can be accessed from all modules.
Dim oSQL As SQL
End Sub
Sub Globals
'These global variables will be redeclared each time the activity is created.
'These variables can only be accessed from this module.
End Sub
Sub Activity_Create(FirstTime As Boolean)
Dim oCursor As Cursor
Dim cntr As Int
Dim R As Reflector
File.Copy(File.DirAssets,"fkeytest.db",File.DirDefaultExternal,"fkeytest.db")
oSQL.Initialize(File.DirDefaultExternal,"fkeytest.db",True)
Dim R As Reflector
R.Target = oSQL
R.Target = R.GetField("db")
R.Runmethod2("setForeignKeyConstraintsEnabled",True,"java.lang.boolean")
oCursor = oSQL.ExecQuery("PRAGMA foreign_keys")
oCursor.Position = 0
Log("foreign_keys = " & oCursor.GetString2(0))
oCursor = oSQL.ExecQuery("Select * from orderdetails where ordernumber = 10103")
Log("No Rows For Orderdetails where ordernumber = 10103: " & oCursor.RowCount)
oCursor = oSQL.ExecQuery("Select * from orders where ordernumber = 10103")
Log("No. Rows For Orders where ordernumber = 10103: " & oCursor.RowCount)
Log("Deleteteing OrderNumber 10103")
Try
oSQL.ExecNonQuery("DELETE FROM ORDERS WHERE ordernumber = 10103")
oCursor = oSQL.ExecQuery("Select * from orderdetails where ordernumber = 10103")
Log("No. Rows For Orderdetails where ordernumber = 10103: " & oCursor.RowCount)
oCursor = oSQL.ExecQuery("Select * from orders where ordernumber = 10103")
Log("No. Rows For Orders where ordernumber = 10103: " & oCursor.RowCount)
Catch
If LastException.Message.Contains("foreign key constraint failed") Then
Log("Cannot delete order 10103 it has children!")
Else
Log(LastException.Message)
End If
End Try
End Sub
foreign_keys = 1
No Rows For Orderdetails where ordernumber = 10103: 16
No. Rows For Orders where ordernumber = 10103: 1
Deleteteing OrderNumber 10103
Cannot delete order 10103 it has children!
Can I afford a suggestion?
You should choose better names, both fields and tables names.
Moreover, given that DESC is a keyword, I substituted it with descr.
Try the attachment.
(it should be: LM THE BOSS)
'Creates a new table with the given name.
'FieldsAndTypes - A map with the fields names as keys and the types as values.
'You can use the DB_... constants for the types.
'PrimaryKey - The column(S) that will be the primary key, separated by commas. Pass empty string if not needed.
' ---- could this replace CreateTable as a more powerful version?
Sub CreateTable2(SQL As SQL, TableName As String, FieldsAndTypes As Map, PrimaryKey As String)
Dim sb As StringBuilder
sb.Initialize
sb.Append("(")
For i = 0 To FieldsAndTypes.Size - 1
Dim field, ftype As String
field = FieldsAndTypes.GetKeyAt(i)
ftype = FieldsAndTypes.GetValueAt(i)
If i > 0 Then sb.Append(", ")
sb.Append("[").Append(field).Append("] ").Append(ftype)
' If field = PrimaryKey Then sb.Append(" PRIMARY KEY")
Next
If PrimaryKey.Length>0 Then
sb.Append(", PRIMARY KEY(").Append(PrimaryKey).Append(")" )
End If
sb.Append(")")
Dim query As String
query = "CREATE TABLE IF NOT EXISTS [" & TableName & "] " & sb.ToString
Log("CreateTable: " & query)
SQL.ExecNonQuery(query)
End Sub
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?