Query by date with ASP and MySQL - mysql

I need to make a query in a MySQL database returning records with the current date.
I found the command below and it works perfectly inside MySQL:
SELECT * FROM TBAvaliacoes WHERE DataHora = (Date_Format(Now(),'%Y-%m-%d'))
But when I do this inside ASP, it returns me the error below:
See how I am doing:
' ## LISTA RAMAIS
Set cmdListaAvaliacoes = Server.CreateObject("ADODB.Command")
cmdListaAvaliacoes.ActiveConnection = conn
cmdListaAvaliacoes.CommandText = "SELECT * FROM TBAvaliacoes WHERE DataHora = (Date_Format("&Now()&",'%Y-%m-%d'))"
response.write cmdListaAvaliacoes.CommandText
cmdListaAvaliacoes.CommandType = 1
Set rsListaAvaliacoes = Server.CreateObject("ADODB.Recordset")
rsListaAvaliacoes.Open cmdListaAvaliacoes, , 3, 3
If I enclose Now () in single quotation marks, it gives no error, but returns nothing.
Does anyone know how to get around this?
Awaiting,

If you want to call the Now() function defined by MySql then you shouldn't use the VB.NET function and concatenate its output to your sql. Just write the code exactly how you write it in the MySql Workbench
cmdListaAvaliacoes.CommandText = "SELECT * FROM TBAvaliacoes
WHERE DataHora = (Date_Format(Now(),'%Y-%m-%d'))"
If you want to pass a particular date then you need to format your date as expected by MySql
Dim myDate As DateTime = new DateTime(2019,8,10)
cmdListaAvaliacoes.CommandText = "SELECT * FROM TBAvaliacoes
WHERE DataHora = '" & myDate.ToString("yyyy-MM-dd") & "'"
But in this case the better approach is to use parameters (even if you have full control of what your date is)
Dim myDate As DateTime = new DateTime(2019,8,10)
cmdListaAvaliacoes.CommandText = "SELECT * FROM TBAvaliacoes
WHERE DataHora = #dat"
Dim prm = cmdListaAvaliacoes.CreateParameter("#dat", adDBDate, adParamInput)
prm.Value = myDate
cmdListaAvaliacoes.parameters.Append prm
Side note
A lot of time has passed from the last time I have used ADODB. So the parameter solution is how I remember it. Search on the net for more complete CreateParameter examples

Related

How to check only month and year in MySQL DateTime column in Vb.net

Im saving some calculated values in to database each month.Before saving, i want to check data is already available for this month and year. IF the same month exists, then user has to select another month or leaving without saving that. In Vb.net, im using DateTimepicker for selecting month and save that in DateTIme format in mysql. In that i want to check only month and year is existing.
Mysql:
1 2019-05-01 14:24:20 ProA 8.34 3.59
2 2019-05-01 14:24:20 ProB 9.21 5.54
Here record available for ProA for May2019 is available. So user cannot save for may 2019 again.
Dim selectedDate = DateTimePicker1.Value
Dim startDate = New Date(selectedDate.Year, selectedDate.Month, 1)
conn.Open()
sQuery = "SELECT * FROM riskanalysis WHERE DATE_FORMAT(reportdate,'%c %Y') >= #StartDate "
cmd_listview = New MySqlCommand(sQuery, conn)
cmd_listview.Parameters.AddWithValue("#StartDate", startDate)
Using reader As MySqlDataReader = cmd_listview.ExecuteReader()
If reader.HasRows Then
' User already exists
MsgBox("Record Already Exist for this Month!", MsgBoxStyle.Exclamation, "Select another month!")
Else
sQuery = "INSERT INTO riskanalysis (reportdate, process, avgrisk, avgriskafterImp) VALUES (#dat, #process, #avgrisk, #riskafterimp);"
For i As Integer = 0 To ProcessRiskGridView.Rows.Count - 1
cmd_listview = New MySqlCommand(sQuery, conn)
cmd_listview.Parameters.AddWithValue("dat", DateTimePicker1.Value)
cmd_listview.Parameters.AddWithValue("process", ProcessRiskGridView.Rows(i).Cells(0).Value)
cmd_listview.Parameters.AddWithValue("avgrisk", ProcessRiskGridView.Rows(i).Cells(1).Value)
cmd_listview.Parameters.AddWithValue("riskafterimp", ProcessRiskGridView.Rows(i).Cells(2).Value)
cmd_listview.ExecuteNonQuery()
Next
End Using
conn.Close()
I tried for some mysql command but it didnt work.
You don't need to Select * to find out if a record exists. Just get the count. Don't retrieve data you don't need. You certainly don't need a reader.
Keep your database objects local so you can be sure they are closed and disposed. `Using...End Using blocks will handle this for you even if there is an error.
Don't use .AddWithValue See http://www.dbdelta.com/addwithvalue-is-evil/
and
https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
and another one:
https://dba.stackexchange.com/questions/195937/addwithvalue-performance-and-plan-cache-implications
You keep adding parameters to the collection over and over on each iteration. They only need to be added once. The value of #dat remains the same for all iterations. Only the values of the last 3 parameters change. You seem to be mixing up column names and parameter names. We are dealing with parameter names.
I have guessed at datatypes. Check your database for the actual datatypes and be sure to convert the values from the grid cells to the proper type if necessary. I don't know what kind of grid you are using and if it returns proper datatypes for .Value.
Example:
cmd.Parameters("#avgrisk") = CDbl(ProcessRiskGridView.Rows(i).Cells(1).Value)
Private Sub MySql()
Dim retVal As Integer
Dim selectedDate = DateTimePicker1.Value
Dim startDate = New Date(selectedDate.Year, selectedDate.Month, 1)
Dim sQuery = "SELECT Count(*) FROM riskanalysis WHERE DateTimeColumnName >= #StartDate; "
Using conn As New MySqlConnection("Your connection string")
Using cmd As New MySqlCommand(sQuery, conn)
cmd.Parameters.Add("#StartDate", MySqlDbType.DateTime).Value = startDate
conn.Open()
retVal = CInt(cmd.ExecuteScalar)
End Using
End Using
If retVal <> 0 Then
MessageBox.Show("Record Already Exist for this Month!")
Return
End If
sQuery = "INSERT INTO riskanalysis (reportdate, process, avgrisk, avgriskafterImp) VALUES (#dat, #process, #avgrisk, #riskafterimp);"
Using cn As New MySqlConnection("Your connection string")
Using cmd As New MySqlCommand(sQuery, cn)
With cmd.Parameters
.Add("#dat", MySqlDbType.DateTime).Value = selectedDate
.Add("#process", MySqlDbType.VarChar)
.Add("#avgrisk", MySqlDbType.Double)
.Add("#riskafterimp", MySqlDbType.Double)
End With
cn.Open()
For i As Integer = 0 To ProcessRiskGridView.Rows.Count - 1
cmd.Parameters("#process").Value = ProcessRiskGridView.Rows(i).Cells(0).Value
cmd.Parameters("#avgrisk") = ProcessRiskGridView.Rows(i).Cells(1).Value
cmd.Parameters("#riskafterimp") = ProcessRiskGridView.Rows(i).Cells(2).Value
cmd.ExecuteNonQuery()
Next
End Using
End Using
End Sub

vb.net with mysql how to pick between to dates of different years?

I have a vb.net program that queries a mysql database. i can search and get records between to dates with this code:
sqlQRY12 = "SELECT * from mating WHERE date BETWEEN '" & export_daily_date_DateTimePicker1.Text & "' AND '" & export_daily_date_DateTimePicker2.Text & "' AND chkbox = '0' ORDER BY lot_id ASC"
my format for my date is:
export_daily_date_DateTimePicker1.Format = DateTimePickerFormat.Custom
export_daily_date_DateTimePicker1.CustomFormat = "MM/dd/yy"
export_daily_date_DateTimePicker2.Format = DateTimePickerFormat.Custom
export_daily_date_DateTimePicker2.CustomFormat = "MM/dd/yy"
however if i try to search between two years like 12/20/13 - 02/20/14 I return no records when i know they exist? Any help would be great ty
Generally dates expressed as strings in database queries should be in the format "YYYY-MM-DD".
You essentially want your executed query to be this:
SELECT * from mating
WHERE date BETWEEN '2013-12-20' AND '2014-02-20'
So change the format of your dtpickers to be yyyy-mm-dd like this:
export_daily_date_DateTimePicker1.Format = DateTimePickerFormat.Custom
export_daily_date_DateTimePicker1.CustomFormat = "yyyy-MM-dd"
export_daily_date_DateTimePicker2.Format = DateTimePickerFormat.Custom
export_daily_date_DateTimePicker2.CustomFormat = "yyyy-MM-dd"
You should never concatenate values into your SQL commands. If at all possible, you should use parameters. With parameters, you can specify the value as it's actual type (Date) rather than as the string representation. The ADO Provider will handle converting the value correctly for you.
cmd.CommandText = "SELECT * from mating WHERE date BETWEEN #date1 AND #date2 AND chkbox = '0' ORDER BY lot_id ASC"
cmd.Parameters.AddWithValue("#date1", export_daily_date_DateTimePicker2.Value)
cmd.Parameters.AddWithValue("#date2", export_daily_date_DateTimePicker2.Value)

passing an Array as a Parameter to be used in a SQL Query using the "IN" Command

Good Afternoon to All,
I have a question concerning on SQL Queries. is it possible to use an array as a parameter to a query using the "IN" command?
for example,
int x = {2,3,4,5}
UPDATE 'table_name' set 'field' = data WHERE field_ID IN (x)
the reason I am asking this is to avoid an iterative SQL Statement when I have to update data in a database.
I also thought of using a for each statement in for the UPDATE Query but I don't know if it will affect the performance of the query if it will slow down the system if ever 100+ records are updated.
I am using VB.Net btw.
My Database is MySQL Workbench.
I have gotten the answer. I just simply need to convert each elements to a String then concatenate it with a "," for each element. so the parameter that i will pass will be a string.
ANSWER:
int x = {2,3,4,5}
will become
string x = "2,3,4,5"
My Query string will become "UPDATE tablename SET field=value WHERE ID IN("&x&")"
Thank you to all who helped.
If you have the query in a variable (not a stored procedure) and you don't have a huge amount of ids, you could built your own IN. I haven't tested the speed of this approach.
This code won't compile, it's just to give you an idea.
query = "SELECT * FROM table WHERE col IN ("
For t = 0 TO x.Length-1
If t > 0 Then query &= ","
query &= "#var" & t
Next
query &= ")"
...
For t = 0 TO x.Length-1
cmd.Parameters.Add("#var" & t, SqlDbType.Int).Value = x(t)
Next
i am not familiar with mySQL, but when dealing with MSSQL, I normally have a split function in DB so that I can use it to split concatenated integer values as a table, at VB side, something like:
Dim myIds = {1, 2, 3, 4}
Dim sql = <sql>
SELECT m.* FROM dbo.tblMyData m
INNER JOIN dbo.fncSplitIntegerValues(#Ids, ',') t ON t.id = m.Id
</sql>.Value
Using con As New SqlConnection("My connection string..."),
cmd As New SqlCommand(sql, con)
cmd.Parameters.Add("#Ids", SqlDbType.VarChar).Value =
myIds.Select(Function(m) m.ToString).Aggregate(Function(m, n) m & "," & n)
con.Open()
Dim rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)
While rdr.Read()
Console.WriteLine(rdr.GetValue(0))
' do something else...
End While
End Using
dbo.fncSplitIntegerValues is a db function to split concatenated integer varchar into integer Id with given separator.
it's important not to use plain sql, instead, use sql parameters.
Note: above sample is not tested...

How to select by date entered by the user?

I am using the below query to run an sql statement. It works fine. I wish to know how I can modify the query to select by a date which the user enters in ASP.NET. This means that I need to modify the part:
WHERE TRANSACTION_DATE = '02-AUG-2006'
Any ideas please?
The query I am using is this:
INSERT INTO TRANSACTION (TRX_UNIT, TRX_DATE, TRX_USR)
SELECT SOURCE_SYSTEM_CHANNEL_CODE, TRANSACTION_DATE, USER_CODE
FROM FCR_TRANSACTION
WHERE TRANSACTION_DATE = '02-AUG-2006'
What about:
// Create a connection object and data adapter
MySqlConnection cnx = new MySqlConnection(connectionString);
// Create a SQL command object
string cmdText = "INSERT INTO TRANSACTION (TRX_UNIT, TRX, TRX_USR) ";
cmdText += "SELECT SOURCE_SYSTEM_CHANNEL_CODE, TRANSACTION_DATE, USER_CODE ";
cmdText += "FROM FCR_TRANSACTION ";
cmdText += "WHERE TRANSACTION_DATE = #TransactionDate";
MySqlCommand cmd = new MySqlCommand(cmdText, cnx);
cmd .Parameters.Add("#TransactionDate", YourDate); // <-- Insert date here
// Set the command type to text
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
you must have a name for the date field where the user enters a date. let us say you decide to name it 'datename'
after that the $_POST("datename") returns the text entered in the field.
so now the WHERE statement becomes
WHERE TRANSACTION_DATE = '$_POST("datename")'
if that doesnt work, try
WHERE TRANSACTION_DATE = $_POST("datename")
all this is assuming you kept method of form transfer as POST....if you have it as GET, simply replace $_POST with $_GET here..
This should work. If it doesnt, my apologies.
If you really want to query by the exact Date, you have to validate the Userinput, and add a parameter
to the query (this is only pseudocode) :
string userInput = txtDate.Text;
DateTime parsedDate;
if (DateTime.TryParse(userInput, out parsedDate)) {
// valid date, add a Parameter to your command
var cmd = ... // create your DB Command here
cmd.CommandText = "SELECT .... WHERE Transaction_Date = #txDate";
cmd .Parameters.Add("#txDate", parsedDate);
// execute your command ...
}

Why would AccessDataSource return different results to query in Access?

I have a query to return random distinct rows from an Access database. Here is the query:
SELECT * FROM
(SELECT DISTINCT m.MemberID, m.Title, m.FullName, m.Address,
m.Phone, m.EmailAddress, m.WebsiteAddress FROM Members AS m INNER JOIN MembersForType AS t ON m.MemberID = t.MemberID WHERE
(Category = 'MemberType1' OR Category = 'MemberType2')) as Members
ORDER BY RND(members.MemberID) DESC
When I run this in Access it returns the rows in different order every time, as per the random sort order. When I run it through my web app however the rows return in the same order every time. Here is how I call it in my code-behind:
private void BindData()
{
using (AccessDataSource ds = new AccessDataSource("~/App_Data/mydb.mdb", GetSQLStatement()))
{
ds.DataSourceMode = SqlDataSourceMode.DataReader;
ds.CacheDuration = 0;
ds.CacheExpirationPolicy = DataSourceCacheExpiry.Absolute;
ds.EnableCaching = false;
listing.DataSource = ds.Select(new DataSourceSelectArguments());
listing.DataBind();
if (listing.Items.Count == 0)
noResults.Visible = true;
else
noResults.Visible = false;
}
}
I added in all that stuff about caching because I thought maybe the query was being cached but the result was the same. I put a breakpoint in the code to make sure the query was the same as above and it was.
Any ideas? This is driving me nuts.
When executing the ACE/Jet RND function against a new connection the same seed value is used each time. When using MS Access you are using the same connection each time, which explains why you get a different value each time.
Consider these VBA examples: the first uses a new connection on each iteration:
Sub TestDiff()
Dim con As Object
Set con = CreateObject("ADODB.Connection")
With con
.ConnectionString = _
"Provider=MSDataShape;Data " & _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=C:\Tempo\Test_Access2007.accdb"
.CursorLocation = 3
Dim i As Long
For i = 0 To 2
.Open
Debug.Print .Execute("SELECT RND FROM OneRowTable;")(0)
.Close
Next
End With
End Sub
Output:
0.705547511577606
0.705547511577606
0.705547511577606
Note the same value each time.
The second example uses the same connection on each iteration (the .Open and .Close statements are relocated outside the loop):
Sub TestSame()
Dim con As Object
Set con = CreateObject("ADODB.Connection")
With con
.ConnectionString = _
"Provider=MSDataShape;Data " & _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=C:\Tempo\Test_Access2007.accdb"
.CursorLocation = 3
.Open
Dim i As Long
For i = 0 To 2
Debug.Print .Execute("SELECT RND FROM OneRowTable;")(0)
Next
.Close
End With
End Sub
Output:
0.705547511577606
0.533424019813538
0.579518616199493
Note different values each time.
In VBA code you can use the Randomize keyword to seed the Rnd() function but I don't think this can be done in ACE/Jet. One workaround is to use the least significant decimal portion of the ACE/Jet the NOW() niladic function e.g. something like:
SELECT CDBL(NOW()) - ROUND(CDBL(NOW()), 4) FROM OneRowTable
I would move the RND into the inner SELECT
SELECT * FROM
(SELECT DISTINCT m.MemberID, RND(m.MemberID) as SortOrder, m.Title,
m.FullName, m.Address, m.Phone, m.EmailAddress, m.WebsiteAddress
FROM Members AS m
INNER JOIN MembersForType AS t ON m.MemberID = t.MemberID
WHERE
(Category = 'MemberType1' OR Category = 'MemberType2')) as Members
ORDER BY
Members.SortOrder DESC
You can use time as one argument to the RND field
Dim Now As DateTime = DateTime.Now
Dim millSec As Integer = Now.Millisecond
finalQuery = "SELECT * FROM wordInfo ORDER BY Rnd(-(1000* ROUND(" + millSec.ToString("N") + ", 0)) * [ID])"
So here from date and time value, millisecond value is taken which will be integer and it is used in sql query by rounding it.
wordInfo is table name
ID is the column name in database table
This gives random order every time (since millisecond value is different) be it same connection or new connection.