Getting "final" prepared statement from MySqlCommand - mysql

I have the following MySqlCommand:
Dim cmd As New MySqlCommand
cmd.CommandText = "REPLACE INTO `customer` VALUES( ?customerID, ?firstName, ?lastName)"
With cmd.Parameters
.AddWithValue("?customerID", m_CustomerID)
.AddWithValue("?firstName", m_FirstName)
.AddWithValue("?lastName", m_LastName)
End With
I have a class that handles execution of MySqlCommands and I'd like to have it log every query to a file. I can retrieve the query/command being executed with:
cmd.CommandText
but that just returns the original CommandText with the parameters (?customerID, ?firstName, etc.) and not the actual substituted values added by the AddWithValue functions. How can I find out the actual "final" query that was executed?

I did the following:
dim tmpstring as string = MySqlCommand.CommandText
For each p as MySqlParameter in MySqlCommand.parameters
tmpstring = tmpstring.replace(p.ParameterName, p.Value)
Next
This seems to output everything you need

I havn't seen a method for this.
And in any case, prepared statements are sent to the server with the ?customerID,?firstname parameters, and then the actual parameters are sent seperately - the mysql driver doesn't build up a final sql query like you'd do if you didn't use prepared statements.

The parameterised method you're using should be okay for preventing SQL injection.
.AddWithValue("?customerID", m_CustomerID)
If m_CustomerID contains the text
Haha I'm stealing your data; drop table whatever;
Then it won't end up being executed on the server as such. The AddWithValue sorts that out for you.
As for the actual executed query, you should be able to get that from the query-log, if it's enabled.

You would have to build it yourself.
Parameters are not just plopped into a string and then run as a SQL statement. The RDBMS will actually prepare the SQL and then use the parameter values as needed. Therefore, there's not a single SQL statement going to the server. To see what the SQL would be, you would have to do:
Console.WriteLine("REPLACE INTO `customer` VALUES('" & m_CustomerID & _
"', '" & m_FirstName & "', '" & m_LastName & "')")

I have the same need.
From what I've read, the query text isn't combined with the param values in the client - they are sent to the server for that.
To inspect what query was actually being sent to the server, I used mysqld logging. For my version of MySQL, I added this entry to the my.cnf:
log=queries.txt
Then, I was able to see clearly the effect of combining command text with parameters: in my case, after restarting the mysqld, I ran my unit tests and then opened the queries.txt file.
HTH!

If you want to manage logging yourself from the .NET application, your best bet is to continue using the MySqlCommand class with parameters to avoid SQL injection; however, when you log the CommandText, loop through the Parameters collection and log each one by name/type/value.

Related

VB.NET MYSQL Displaying Data using MySQL Error

Hello I'm trying to display data in vb.net using MySQL syntax here is my Mysql syntax
SELECT COUNT(status) as 'Number of Grade School for the Month of January'
FROM blhtraining.userinfo
Where survey_at='Talisay'
and status='College' and Month(member_since)='1' and
Year(member_since)='2021'
And this code works in Mysql but when i modify it like this in vb.net
Dim count_gradeSchool1 As String = "Select Case COUNT(status) As 'Members'
From training.userinfo
Where survey_at='" & txtmonthlylocation.Text & "'
And status ='College'
And Month(member_since)='" & monthly_reports & "'
And YEAR(member_since)='" & txtmyear.Text & "'
And Day(member_since)='11'"
da = New MySqlDataAdapter(count_gradeSchool1, mycon)
dt = New DataTable()
da.Fill(dt)
lblgs1.Text = dt.Rows(0)("Members")
I recieved this error
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'As 'Members'
From training.u' at line 1
I'm sure the syntax is correct is it the variable declared?
Your problems probably came about because you pasted the SQL into your code without starting a string first, so VB saw "select" and helped you out by adding "case". So, here is code that...
...has fixed SQL syntax
...uses parameters. Always use parameters. You've no idea how many times a day I say this, trying to stem the tide of future SQL injection hacks. Writing code that doesn't use parameters will get you fired, or you'll have to live with the consequences of writing hack prone code on your conscience. Don't ever skip on using parameters in your SQLs, even if it's "only an app to track your grandma's record collection"
...doesn't call functions on columns in the where clause - don't do it; it's a huge waste of resources and kills opportunities to use indexes. Always, always try to leave table data alone, untransformed. In 99% of cases there is another way to write the query
...uses executescalar - you only want one value, pointless using an adapter/table for it
...doesn't use column alises with spaces in - as noted in the comments - don't do it; it's not the database's job to format your column names, it's the front end's job.
Dim count_gradeSchool1 As String = "Select COUNT(*) as c
FROM training.userinfo
Where survey_at = #loc
And status = 'College'
And member_since = #ms"
Using c = New MySqlCommand(count_gradeSchool1, mycon)
c.Parameters.AddWithValue("#loc", txtmonthlylocation.Text)
c.Parameters.AddWithValue("#ms", new Date(CInt(txtmyear.Text), CInt(monthly_reports), 11)
c.Connection.Open() 'if it's not already open
lblgs1.Text = c.ExecuteScalar().ToString()
End Using

Unable to resolve "Error 3061. Too few parameters. Expected 1"

I have these lines in VBA
strTOP = "SELECT * FROM CM_qryBOM WHERE BOM_Address Like '*" & Me.Part_No & "'"
Set rsTOP = CurrentDb.OpenRecordset(strTOP, dbOpenSnapshot)
Which results in the following SQL statement that I verified in the Immediate window.
SELECT * FROM CM_qryBOM WHERE BOM_Address Like '*601541-19'
The query does not execute and throws error code 3061 when running from VBA. However, when I copy and paste the same query into Query Design SQL view it runs just fine.
Never encountered this before and not sure how to fix. Tried bracketing the [table name] and [field name] but that didn't help either.
The usual suspect, in this case, is the query you're selecting from (CM_qryBOM).
It likely is using form or report values as parameters (or querying off other queries that do). Those aren't available when using CurrentDb.OpenRecordset.
You can manually set them by using a querydef and parameters, or you can construct a query that only queries tables, not other queries, to be safe.

Difference between "?" and "#" in visual basic

I just want to ask what is the difference between ? and # when inserting data to mysql in visual basic. So I have this query:
Dim sql As String = "INSERT INTO users(firstname, lastname, position) VALUES(?fname, ?lname, ?pos)"
cmd = New MySqlCommand(sql, conn)
cmd.Parameters.AddWithValue("?fname", TextBox1.Text)
cmd.Parameters.AddWithValue("?lname", TextBox2.Text)
cmd.Parameters.AddWithValue("?pos", TextBox3.Text)
I first use the #param but it is not inserting data to mysql but when I use ?param it inserts data. What is the difference between them?
When CommandType is set to Text, the .NET Framework Data Provider for
ODBC does not support passing named parameters to an SQL statement or
to a stored procedure called by an OdbcCommand. In either of these
cases, use the question mark (?) placeholder.
Direct quote from here:
named parameters with .NET Framework Data Provider for ODBC

How in VB.net we can encode string for SQL

For example, in sql
all ` should be replaced with `` right?
Well, is there a function built in by vb.net that does that sort of thing already?
That way I do not have to encode it.
By the way, I do not access sql database directly. Basically I am creating a text file and that text file contains raw sql statements. Most of the answers deal with accessing sql data directly.
I don't think so as I think the only case where something like this would be relevant is if you were doing inline SQL Commands without parameters.
This has a risk of SQL Injection, and therefore you should create commands like this:
Dim cmd As New SqlCommand("UPDATE [TableA] SET ColumnA=#ColumnA WHERE ID=#ID", Conn)
cmd.Parameters.Add("#ColumnA", SqlDbType.NVarChar).Value = txtColumnA.Text
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = ID
cmd.ExecuteNonQuery()
Dont try and do this! I know you are trying to avoid SQL Injection so you are to be commended for thinking about security. However rolling your own sanitisation routine is something that is easy to get wrong.
Use parameters in your query along the lines of
cmd.CommandText = "select * from customer where id=?id";
cmd.Parameters.AddWithValue("?id",CustomerIDValue);
If you are using a string then you'll be using " in your code so you won't need to escape these characters.
Dim mySql As String = "SELECT `MyColumn` FROM `Table`"

error code 3021 either bof or eof is true or the current record has been deleted

I have an Access 2003 database with some visual basic code using ADO calls in it. When I do a
strsql0 = "SELECT lnk_stockitm.C_C FROM lnk_stockitm WHERE (((lnk_stockitm.C_C) Like 'T*'));"
newRS.Open strsql0, cn1, adOpenKeyset, adLockReadOnly
newRS.movelast
I get this error:
3021 either bof or eof is true or the current record has been deleted
When I run the exact same query in the same function without the WHERE clause, like this:
strsql0 = "SELECT lnk_stockitm.C_C FROM lnk_stockitm;
I get the correct result of 56,000 records. If I paste the full SQL statement with the WHERE clause into a regular query, like so:
SELECT lnk_stockitm.C_C FROM lnk_stockitm WHERE (((lnk_stockitm.C_C) Like 'T*'));
it returns the correct subset of the results (2800 records).
Can anyone tell me what I am doing wrong?
The wildcard difference is the cause for difference between what you execute from ADO and within your access database. Convert your statement to use "%" rather than "*". As a general rule of thumb, it may be a good idea to encapsulate your code by checking for eof before calling MoveLast. If your query has zero results it'll bomb out every time.
strsql0 = "SELECT lnk_stockitm.C_C FROM lnk_stockitm WHERE (((lnk_stockitm.C_C) Like 'T*'));"
newRS.Open strsql0, cn1, adOpenKeyset, adLockReadOnly
if not newRs.eof then
newRS.movelast
else
' do something here if necessary to handle blank results
end if
You need to use the '%' character as wildcard when using ADO.
MSDN Article: Using the Right Wildcard Characters in SQL Statements