MySQL PrepareStatement Problem

This is webapplication where user input member name or email etc and this code will
search in database and return the member list

If using PrepareStatement following code is not returning any data but without
preparestatement it is working fine.

using Xojo.Data
  using Xojo.Core
  
  dim SQL as Text
  dim qry() as Text
  dim i as integer = 0
  
  qry = atext.Split(" ") -> atext = "jiten shah"
  
  SQL = SQL + ""
  SQL = SQL + "select "
  SQL = SQL + "  a.member_id, a.member_name, a.email, a.phone "
  SQL = SQL + "from "
  SQL = SQL + " member_master a "
  SQL = SQL + " join member_card_detail b on a.member_id = b.member_id "
  SQL = SQL + "where "
  SQL = SQL + " a.cstat='x' and b.cstat='x' "
  SQL = SQL + " and b.card_collection_date is null "
  SQL = SQL + " and b.card_printing_date is not null "
  
  for i = 0 to qry.Ubound
    SQL = SQL + " and instr(lower(concat_ws('', a.member_id, a.member_name, a.email, a.phone)), ?) > 0 "
  next
  
  SQL = SQL + "order by "
  SQL = SQL + " a.member_name "
  
  
  dim pstmt as PreparedSQLStatement 
  pstmt = DB.Prepare(SQL)
  
  dim pmt As New Dictionary
  dim b_text as Text
  '
  i = 0
  for each b_text in qry
    pmt.Value(i) = b_text
    i = i + 1
  next

  for each entry as DictionaryEntry in pmt
    i = entry.Key
    b_text = entry.Value
    pstmt.BindType(i, MySQLPreparedStatement.MYSQL_TYPE_STRING)
    pstmt.Bind(i, b_Text)
  next

  dim rs as RecordSet = pstmt.SQLSelect()
  if DB.Error = True then
    msgbox(DB.ErrorMessage)
    return Nil
  end if
  
  return rs

@Sascha

both option not working

Why are you using a dictionary instead of your qry() array directly? The dictionary may be returning the values in a different order, making your sql - built with qry() - and your bind values - using the dictionary - out of sync.

@Time Hare
Order will not effect the query user can input member name in any order like
tim hare
or
hare tim
and data type also same string

but your suggestion is correct in case if i have different data type then dictionary will create a problem.

Is no one encounter this type of issue

Compare the sql statement without using prepare (the one that is working) vs. the sql string that you pass to prepare. Is the only difference the presence of the “?” Or are there other differences. You might want to copy and paste them here. Often, a second pair of eyes can see what you might miss.

using Xojo.Data
using Xojo.Core

dim SQL as Text
dim qry() as Text
dim i as integer = 0

qry = atext.Split(" ")

SQL = SQL + “”
SQL = SQL + “select”
SQL = SQL + " a.member_id, a.member_name, a.email, a.phone "
SQL = SQL + "from "
SQL = SQL + " member_master a "
SQL = SQL + " join member_card_detail b on a.member_id = b.member_id "
SQL = SQL + "where "
SQL = SQL + " a.cstat=‘x’ and b.cstat=‘x’ "
SQL = SQL + " and b.card_collection_date is null "
SQL = SQL + " and b.card_printing_date is not null "

for i = 0 to qry.Ubound
SQL = SQL + " and instr(lower(concat_ws(’’, a.member_id, a.member_name, a.email, a.phone)), ’ " + qry(i) + " ') > 0 "
'SQL = SQL + " and instr(lower(concat_ws(char(32), a.member_id, a.member_name, a.email, a.phone)), ?) > 0 "
next

SQL = SQL + "order by "
SQL = SQL + " a.member_name "

return DB.SQLSelect(SQL)

Just a friday tip!
To write code like this you can use the break line separator “(space)_” like this.

SQL = "SELECT " _
+ "a.member_id, a.member_name, a.email, a.phone " _
+ "FROM " _
+ "member_master a " _
+ "JOIN member_card_detail b ON a.member_id = b.member_id " _
+ "WHERE " _
+ "a.cstat='x' AND b.cstat='x'  " _
+ "AND b.card_collection_date IS NULL " _
+ "AND b.card_printing_date IS NOT NULL"

Even better use the constant editor and just type it in as plain text or paste the SQL statement with included line breaks. See http://blog.xojo.com/tip-formatted-text/strings-in-xojo.

@Albin Kiland and @Wayne Golding thank you for your suggestion

I rewrote your code a bit to produce SQL that was a little more readable:

  using Xojo.Data
  using Xojo.Core
  
  dim SQL as Text
  dim qry() as Text
  dim i as integer = 0
  
  qry = atext.Split(" ")
  
  SQL = _
  "select" + &uA + _
  " a.member_id, a.member_name, a.email, a.phone " + &uA + _
  "from " + &uA + _
  " member_master a " + &uA + _
  " join member_card_detail b on a.member_id = b.member_id " + &uA + _
  "where " + &uA + _
  " a.cstat='x' and b.cstat='x' "+ &uA + _
  " and b.card_collection_date is null "+ &uA + _
  " and b.card_printing_date is not null " + &uA
  
  for i = 0 to qry.Ubound
    SQL = SQL + " and instr(lower(concat_ws('', a.member_id, a.member_name, a.email, a.phone)), ' " + qry(i) + " ') > 0 " + &uA
  next
  
  SQL = SQL + "order by " + &uA + _
  " a.member_name "

That produces SQL like this:

select
 a.member_id, a.member_name, a.email, a.phone 
from 
 member_master a 
 join member_card_detail b on a.member_id = b.member_id 
where 
 a.cstat='x' and b.cstat='x' 
 and b.card_collection_date is null 
 and b.card_printing_date is not null 
 and instr(lower(concat_ws('', a.member_id, a.member_name, a.email, a.phone)), ' john ') > 0 
 and instr(lower(concat_ws('', a.member_id, a.member_name, a.email, a.phone)), ' doe ') > 0 
order by 
 a.member_name 

There are spaces around the data but no spaces in the concatenated columns so you’ll never get a match. Try rewriting that portion as:

    SQL = SQL + " and instr(lower(concat_ws(' ', '', a.member_id, a.member_name, a.email, a.phone, '')), '" + qry(i).Trim.Lowercase + "') > 0 " + &uA

(BTW, beware of double-spaces in the input. If the user entered “john doe”, you are going to get a false match. Trim and squeeze your input first.)

Finally, rewriting it with a PS like this should work:

  using Xojo.Data
  using Xojo.Core
  
  dim SQL as Text
  dim qry() as Text
  dim i as integer = 0
  
  qry = atext.Trim.Lowercase.Split(" ")
  for i = qry.Ubound downto 0
    qry( i ) = qry( i ).Trim
    if qry( i ) = "" then
      qry.Remove i
    end if
  next
  
  if qry.Ubound = -1 then
    //
    // Nothing to search
    //
    return
  end if
  
  SQL = _
  "select" + &uA + _
  " a.member_id, a.member_name, a.email, a.phone " + &uA + _
  "from " + &uA + _
  " member_master a " + &uA + _
  " join member_card_detail b on a.member_id = b.member_id " + &uA + _
  "where " + &uA + _
  " a.cstat='x' and b.cstat='x' "+ &uA + _
  " and b.card_collection_date is null "+ &uA + _
  " and b.card_printing_date is not null " + &uA
  
  for i = 0 to qry.Ubound
    SQL = SQL + " and instr(lower(concat_ws(' ', '', a.member_id, a.member_name, a.email, a.phone, '')), ?) > 0 " + &uA
  next
  
  SQL = SQL + "order by " + &uA + _
  " a.member_name "
  
  dim ps as PreparedSQLStatement = DB.Prepare( SQL )
  for i = 0 to qry.Ubound
    ps.BindType i, MySQLPreparedStatement.MYSQL_TYPE_STRING
    ps.Bind i, qry( i ).Trim.Lowercase
  next i
  
  dim rs as RecordSet = ps.SQLSelect

I can’t test this, unfortunately.

(BTW, if you are indexing on the concatenated string, you should update your index. Even so, it might be faster to search each individual field.)

I have remove the concate_ws condition and search only on one field still no record found

  SQL = SQL + ""
  SQL = SQL + "select"
  SQL = SQL + "  a.member_id, a.member_name, a.email, a.phone "
  SQL = SQL + "from "
  SQL = SQL + " member_master a "
  SQL = SQL + " join member_card_detail b on a.member_id = b.member_id "
  SQL = SQL + "where "
  SQL = SQL + " a.cstat='x' and b.cstat='x' "
  SQL = SQL + " and b.card_collection_date is null "
  SQL = SQL + " and b.card_printing_date is not null "
  
  for i as Integer = 0 to qry.Ubound
    SQL = SQL + " and instr(lower(a.member_name), ?) > 0 "
    'SQL = SQL + " and instr(lower(a.member_name), '" + qry(i) + "' ) > 0 "
   
  next
  
  SQL = SQL + "order by "
  SQL = SQL + " a.member_name "
  
  'return DB.SQLSelect(SQL)
  
  dim pstmt as PreparedSQLStatement 
  pstmt = DB.Prepare(SQL)
  for i as Integer = 0 to qry.Ubound
    pstmt.BindType(i, MySQLPreparedStatement.MYSQL_TYPE_STRING)
    pstmt.Bind(i, qry(i))
  next
  
  
  dim rs as RecordSet = pstmt.SQLSelect()
  if DB.Error = True then
    MsgBox(DB.ErrorMessage)
    return Nil
  end if
  
  return rs

This is working from mysql client

PREPARE msr FROM
'select 
  a.member_id, a.member_name, a.email, a.phone 
from  
  member_master a  join member_card_detail b on a.member_id = b.member_id 
where  
  a.cstat=char(120) and b.cstat=char(120)
  and b.card_collection_date is null  
  and b.card_printing_date is not null  
  and instr(lower(a.member_name), ?) > 0  
  and instr(lower(a.member_name), ?) > 0 
order by  
 a.member_name'

set @a='shah', @b='kumar' 

execute msr using @a, @b 

Any error? Are you sure qry contains what you think it contains?

Following is working

  SQL = SQL + " PREPARE msr FROM "
  SQL = SQL + """"
  SQL = SQL + "select"
  SQL = SQL + "  a.member_id, a.member_name, a.email, a.phone "
  SQL = SQL + "from "
  SQL = SQL + " member_master a "
  SQL = SQL + " join member_card_detail b on a.member_id = b.member_id "
  SQL = SQL + "where "
  SQL = SQL + " a.cstat='x' and b.cstat='x' "
  SQL = SQL + " and b.card_collection_date is null "
  SQL = SQL + " and b.card_printing_date is not null "
  
  dim aqry() as Text
  dim alist() as Text
  dim vname as Text
  for i as Integer = 0 to qry.Ubound
    SQL = SQL + " and instr(lower(concat_ws('', a.member_id, a.member_name, a.email, a.phone)), ?) > 0 "
    vname = "@a" + i.ToText
    aqry.Append(vname + " = '" + qry(i) + "'")
    alist.Append(vname)
  next
  
  SQL = SQL + "order by "
  SQL = SQL + " a.member_name "
  SQL = SQL + """"
  
  DB.SQLExecute(SQL)
  DB.SQLExecute(" set " + Text.Join(aqry, ","))
  return DB.SQLSelect("execute msr using " + Text.Join(alist, ","))
  

Any suggestion, Any solution Anyone please

What is your question now? Your last message said that it works, so we don’t know what you need help with now.

with PrepareQuery is not working yet

What you should do is compare the SQL string you’re giving to the Prepare statement and compare that to the one that works with the mysql client. What are the differences? There should be none. Maybe show us the string here so we can help spot the difference. Showing us the code is not helping as we’re not going to write a test app for you, probably.

Kem Tekinay has already shown you one error, where you had spaces around the ’ … ’ names. I assume you’ve fixed that already?

I on the mysql general-log option and check the sql

I can see the prepare sql statement recd by mysql but not the execute statement when using PrepareSQL

I try different sql statement also but no result

May be you can test any sql with PrepareSqlStatement with mysql and check