Variable in a MySQL string

Hi, I’m trying to add a variable in a MySQL string, but nothing.
Variable is t1 and I tried to add in any way… example: ‘t1’ , ‘t1%’, +‘t1%’, " ’ t1 ’ "… and everything you can imagine!
I’ve added a message box to be sure that the variable imput is done properly.

What is wrong ? How can I add a variable in any occasion, in a MySQL string ?
Thanks !

Dim t1 As String
t1= TextField1.Text

MsgBox(t1)
Dim fab As RecordSet
fab = db.SQLSelect("SELECT * FROM domande WHERE testo LIKE t1’%’ " )
If fab <> Nil Then
fab.MoveFirst
While Not fab.EOF
Listbox2.AddRow “”
ListBox2.Cell(Listbox2.LastIndex,0) = fab.Field(“testo”).StringValue
fab.MoveNext
Wend
Else
If db.Error Then MsgBox(db.ErrorMessage)
End If
db.Close

fab = db.SQLSelect("SELECT * FROM domande WHERE testo LIKE "+t1+"'%' " )

but use prepared statements instead.

Thank you Dave, can you give me an example of statements ? I’m learning Xojo from scratch, it’s not so simple to find arguments in manual !

I tried to add the line as you wrote, but “You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘’%’’ at line 1”

look up MySQLPreparedStatement in the LangRef

error in my response

fab = db.SQLSelect("SELECT * FROM domande WHERE testo LIKE '"+t1+"%' " )

Yes, prepared statements are the safer way to go, but before learning that you need to properly understand how to create SQL queries in Xojo.

You need to understand that the SQLSelect command takes a single string parameter. The entire query is a single string. When you say you want to add a variable to the query, what you really mean is you want to add the contents of a variable to a query, which means adding it in a way that produces a single string that is a valid SQL query.

The best way to verify that you have correctly created this query string is to output the final string (MsgBox, debugger, log, etc.). If you can copy and paste that output into a query tool and get the expected result, then you know you have properly created the query string. So in your example it would be:

Dim sql As String sql = "SELECT * FROM domande WHERE testo LIKE '" + t1 + "'%' " MsgBox(sql)

Notice that since the column testo is a string (I’m assuming), the comparison value (your t1 variable) has to be quoted within the query just as you would when writing the query directly in a query tool. If the column was a numeric type, then it wouldn’t have to be quoted within the query, but you would have to convert the variable into to a string in order to concatenate it into the query string, like so:

Dim t1 As Integer t1 = 5 Dim sql As String sql = "SELECT * FROM domande WHERE testn = " + Str( t1 ) MsgBox(sql)

Once you understand this, you can then understand how using user-entered values directly in a query like this opens you to possible malicious actions, called SQL Injection. Read about it here under “Technical Implementations”. The best way to prevent SQL Injection is to use Prepared Statements. These handle the insertion of variables into your query in a way that prevents nefarious input values from causing problems. You also don’t have to deal with properly quoting string values within the query.

Thank you Dave for code, it works perfectly !
Jay I will use this complete description and advice to do as you write, I hope I will not find any problems in complex query, but I must try before.
Infact I am trying to move a ChatBot software I have created on Filemaker, which I know well, to xojo and mysql.
This ChatBot tries to reply to any question based upon a different way to search questions/answers.
Thank you for your kind help, I am sure I have learned a lot from you both !

Never, never, never ever use variables in queries! Except you really really really know what you are doing!
Use prepared statements whenever you want to use variables. I saw so much Databases dropped because of variables…

[quote=426713:@Marius Dieter Noetzel]Never, never, never ever use variables in queries! Except you really really really know what you are doing!
Use prepared statements whenever you want to use variables. I saw so much Databases dropped because of variables…[/quote]
Marius… had you read the above topics you would have noticed that this had already been impressed… and that the solution was presented as a learning experience…

TL;DR: Please look at the example at the bottom of my post here instead.

I know that this was discussed but the technique of building SQL strings manually is known to be a very serious security issue, and I feel that it should not be an accepted answer to such a question, unless also paired with an example of why it is dangerous to do this or at least a safe version.

As an example of why this is dangerous, unless the driver is protecting against this sort of thing by blocking the execution of multiple statements in a single DB call (it very well may), the following value could easily cause “problems” for you if entered into TextField1 (depending on the exact way you construct the query, you may need to swap ’ for " in this example):

1'; DROP TABLE domande; SELECT * FROM domande WHERE testo LIKE '

If not handled correctly, this value injected into the query above would drop the domande table. Some drivers do protect against this but you cannot always rely on this.

Another example (again, type this into TextField1, and again perhaps swap ’ for "):

1' OR 1=1 OR '

This example should cause all items in the table to be returned even if they do NOT match the LIKE clause. This is a serious issue for security reasons, typically. A local application may not very much care of course. This example cannot be blocked by a driver as it is a single statement still.

The least harmful but most likely example is simply:

'Hello there' he said

This example would simply cause a syntax error. The quotation characters ’ or " could never be safely used in a value provided by a user for use in such a query, as they would cause syntax errors. This example also cannot be blocked by a driver as it remains a single statement.

In an effort to complete the picture here, I have provided a version using prepared statements below. I believe this is not actually any harder to understand and I guarantee that it is much safer.

Dim t1 As String
t1= TextField1.Text

MsgBox(t1)
Dim fab As RecordSet

// Create the "template" for our SQL query -- each ? will be safely bound to a type and value below
Dim ps As PreparedSQLStatement = db.Prepare("SELECT * FROM domande WHERE testo LIKE ?")
// Tell the statement that we expect a string to be used for the first parameter (number 0)
ps.BindType(0, MySQLPreparedStatement.MYSQL_TYPE_STRING)
// Add our value from the Xojo variable, with a wildcard added to the end (for the first
// parameter, number 0 again)
ps.Bind(0, t1+"%")
// If you have more than one parmaeter (e.g. more than one ? in the SQL above) then continue
// binding types and values to parameters 1, 2, 3, etc.

// Get the results, returns a RecordSet exactly like calling db.SQLSelect would
fab = ps.SQLSelect

If fab <> Nil Then
    fab.MoveFirst
    While Not fab.EOF
        Listbox2.AddRow ""
        ListBox2.Cell(Listbox2.LastIndex,0) = fab.Field("testo").StringValue
        fab.MoveNext
    Wend
Else
    If db.Error Then MsgBox(db.ErrorMessage)
End If
db.Close

I hope that this example helps someone write safer code, we need to look out for each other out there.

I tried, but the line

ps.BindType(0, MySQLPreparedStatement.MYSQL_TYPE_STRING)

Seems to have any problem, Xojo blocks and a bug is found there…

please post your sql-statement

This can happen if there is not a valid database connection, or if you are not actually using a MySQL connection perhaps, as well as if you have invalid SQL (as Marius implied), double check that it is connected. How are you creating the db object?

Yes, I have just checked again db connection, everything is ok.

“Domanda” is a simple text box

Here’s:

//Prepariamo la connessione

Dim db as New MySQLCommunityServer
db.Host=“XXX”
db.port = 3306
db.DatabaseName=“lXXX”
db.UserName=“XXX”
db.Password=“XXX”

Listbox2.DeleteAllRows

Dim t1 As String
t1= Domanda.Text

MsgBox(t1)
Dim fab As RecordSet

// Create the “template” for our SQL query – each ? will be safely bound to a type and value below
Dim ps As PreparedSQLStatement = db.Prepare(“SELECT * FROM domande WHERE testo LIKE ?”)
// Tell the statement that we expect a string to be used for the first parameter (number 0)
ps.BindType(0, MySQLPreparedStatement.MYSQL_TYPE_STRING)
// Add our value from the Xojo variable, with a wildcard added to the end (for the first
// parameter, number 0 again)
ps.Bind(0, t1+"%")
// If you have more than one parmaeter (e.g. more than one ? in the SQL above) then continue
// binding types and values to parameters 1, 2, 3, etc.

// Get the results, returns a RecordSet exactly like calling db.SQLSelect would
fab = ps.SQLSelect

If fab <> Nil Then
fab.MoveFirst
While Not fab.EOF
Listbox2.AddRow “”
ListBox2.Cell(Listbox2.LastIndex,0) = fab.Field(“testo”).StringValue
fab.MoveNext
Wend
Else
If db.Error Then MsgBox(db.ErrorMessage)
End If
db.Close

You may want to edit your post to remove just the lines with the IP address, username, and password, or change them to samples.

Ah I see, you need to call db.Connect, place this after the db.Password is set:

if not db.Connect then MsgBox("Cannot connect to db")

Use As mysqlPreparedSQLStatement

Isaac, thank you, now it works !
But I cannot uderstand which is the difference ? This is an “if”

The bit that makes it work is the db.Connect part, which is a method call. I have a bad habit of not putting () after a method call, so this should more properly be like so:

if not db.Connect() then MsgBox("Cannot connect to db")

Anyway, the Connect method is needed to actually establish a connection to the database server.

You could also write this like so:

dim connected as boolean = db.Connect()
if not connected then MsgBox("Cannot connect to db")

Or even ignore the result by using call:

call db.Connect()

However, it’s best to check the result of such a function and show an error to the user so they know something went wrong.

Thank you, now everything is clear!
I will try to transfer my Filemaker ChatBot in Xojo, I think you will see my name again in this forum !

Thank you so much