I want to be able to use the LIKE command with a passed parameter within a SQLite database using the || concatenation tool using this SQL request:
SELECT id FROM Lockers WHERE id <> :id AND ObfuscatedPathParent LIKE %||:ObfuscatedPathParent
or with single quotes: SELECT id FROM Lockers WHERE id <> :id AND ObfuscatedPathParent LIKE '%'||:ObfuscatedPathParent
but I get the error (I have already added the SQLPreparedStatementMBS.BindType(…)):
Bind variable/parameter ‘ObfuscatedPathParent’ not found
It seems as though SQLite is absorbing the :ObfuscatedPathParent itself as text and not a parameter. My issue is with SQLDatabaseMBS, but I assume it is the same with SQLiteDatabase.
How can I add a parameter into a LIKE statement in SQLite?
I guess you would need to create the complete LIKE pattern (including wildcards) in code before binding it as a parameter.
Var strPlaceholder As String = "%" + ObfuscatedPathParent
("SELECT id FROM Lockers WHERE id <> ? AND ObfuscatedPathParent LIKE ?", theId, strPlaceholder)
Yes, ObfuscatedPathParent is a field name in the database. With SQLdatabaseMBS you pass a parameter by using a colon on the front. For clarity I pass the same parameter name as the field name but with a prepended colon.
If I used the normal SQLite form to find all the records ending with 'ABC", it would be:
LIKE ‘%ABC’
but if I want to use a parameter it becomes:
LIKE ‘%:ABC’
but this doesn’t work since it searches for the records ending in ‘:ABC’.
So I tried using concatenation to insert my parameter, but SQLite seems to absorb it and returns the error.
It handles your paramter like a literal string. Try as @Greg_O recommended a CONCAT(‘%’, ObfuscatedPathParent) or do what i recommended above How to concatenate LIKE with parameter - #2 by Sascha_S. The latter is how i do it most times and other times i do like @Greg_O recommended. Both ways work just fine.
Var db As new SQLiteDatabase
db.Connect
var sql As String = "CREATE TABLE tb ( "+_
"id INTEGER PRIMARY KEY AUTOINCREMENT, "+_
"txt TEXT"+_
" );"
db.ExecuteSQL( sql )
db.ExecuteSQL("INSERT INTO tb (txt) VALUES (""ashdfjahdfABC"");")
db.ExecuteSQL("INSERT INTO tb (txt) VALUES (""ashdfjahdfCDE"");")
Var rs As RowSet
Var ending As String = "BC"
rs = db.SelectSQL("SELECT * FROM tb WHERE txt LIKE '%'||:ending", ending)
break
The error is elsewhere if following the syntax as shown in my example.
var sSearch as String = "%" + sObfuscatedPathParent
rs = db.SelectSQL("SELECT id FROM Lockers WHERE id <> :id AND ObfuscatedPathParent LIKE ?", sSearch)
The reason why people avoid the simple “?” when using SQLITE is just due SQLITE recommendation. They consider it a subpar parametrization (people can error targets missing counts) only existing to follow compatibility with some other DBs.
Thanks to all who participated in finding the solution.
There were two caveats to this issue though, I am using MBS’s SQLDatabaseMBS (thus the colons) and not Xojo’s SQLiteDatabase (which uses ?'s), plus I am connecting to a SQLite database and not MySQL, so I don’t have access to the CONCAT() function. So I don’t know if the issue was created by MBS or SQLite.
Either way, @Greg_O 's solution worked by putting spaces around the SQLite || concatenation function ie this works: id <> :id AND ObfuscatedPathParent LIKE '%' || :ObfuscatedPathParent
My question was NOT about which placeholder you were using and still remains unanswered.
Unless there’s some really compelling reason I’m going to learn about today, I don’t see why you would want to complicate the SQL in this manner and not just concatenate in Xojo code.
“I don’t see why you [don’t] … just concatenate in Xojo code”
Because the LIKE command is a mongrel to have to escape certain characters (eg \, ;, % and _).
For future searchers, using Tim’s example, but with SQLDatabaseMBS I would normally do this (not tested):
Var sSearch as String = "%" + sObfuscatedPathParent
Var tempSQL As String = "SELECT id FROM Lockers WHERE id <> :id AND ObfuscatedPathParent LIKE :sSearch"
Var tempSQLPreparedStatementMBS As SQLPreparedStatementMBS = db.Prepare(tempSQL)
mySQLPreparedStatementMBS.BindType("sSearch", SQLPreparedStatementMBS.kTypeString)
mySQLPreparedStatementMBS.Bind("sSearch", sSearch)
rs = tempSQLPreparedStatementMBS.SelectSQLMT