insert query in MySQL error - asp.net

I have create a function. When the user click the button, data will automatic inset into order table. But it keep give me error. I use the way to do my register page is working fine.
Error Message:
An exception of type 'MySql.Data.MySqlClient.MySqlException' occurred in MySql.Data.dll but was not handled in user code
Additional information: 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 'order(UserId, OrderStatus, OrderDate) values ('kit', 'Pending', '2014-12-08 22:4' at line 1
If Session("OrderId") Is Nothing Then
Dim conn As New MySqlConnection
conn.ConnectionString = "server = localhost; user id = root; password = root; database = db_fyp"
Dim com As New MySqlCommand
conn.Open()
Dim query As String
query = "insert into order(UserId, OrderStatus, OrderDate) values (#UserId, #OrderStatus, #OrderDate)"
com = New MySqlCommand(query, conn)
com.Parameters.AddWithValue("#UserId", Session("Username"))
com.Parameters.AddWithValue("#OrderStatus", "Pending")
com.Parameters.AddWithValue("#OrderDate", Now())
com.ExecuteNonQuery()
conn.Close()
End If
Return Nothing
End Function

Order is a reserved keyword in any SQL language known. I really suggest to change that table name to something less problematic. In the meantime you could change the query to
query = "insert into `order` (UserId, OrderStatus, OrderDate) " & _
"values (#UserId, #OrderStatus, #OrderDate)"

Related

Parameterizing sql in asp

I'm not terribly familiar with asp, but I have one project with a page of it.
<%
'declare the variables
Dim Connection
Dim ConnString
Dim Recordset
Dim SQL
Dim userName
userName = Request.Form("userName")
'define the connection string, specify database driver
ConnString="JJJJJ"//connection information
'declare the SQL statement that will query the database
SQL = "SELECT info AS Lunch, "
SQL = SQL & "FROM dbo.AgentActivityLog WHERE UserId = '" & userName & "'
'create an instance of the ADO connection and recordset objects
Set Connection = Server.CreateObject("ADODB.Connection")
Set Recordset = Server.CreateObject("ADODB.Recordset")
'Open the connection to the database
Connection.Open ConnString
'Open the recordset object executing the SQL statement and return records
Recordset.Open SQL,Connection
'first of all determine whether there are any records
If Recordset.EOF Then
Response.Write("No records returned.")
Else
'process record
Next
Recordset.MoveNext
Loop
End If
'close the connection and recordset objects to free up resources
Recordset.Close
Set Recordset=nothing
Connection.Close
Set Connection=nothing
%>
How do I parameterize the username? I have no way to debug, no knowledge of how this language works, so whatever I tried failed and I have no idea why.
I would suggest you look at the Answer on following link as it will fill in the answers you seek:
VBA, ADO.Connection and query parameters
From the code provided critical missing piece is the ADODB.Command for the SQL to actually be run and to add the parameter the query you would :
Set Param = Command.CreateParameter("#userid",adVarChar,adParamInput)
Param.Value = userName
Command.Paramters.Append Param

insert multiple rows with one query using ms access db

I am trying to get multiple rows into a table hence my attempt to get the row number and put it into a for loop, the countC is exactly the same number of rows as the select statement, so the issue is not there
I'm using an oledb connection as my code is in vb asp.net but my database is in ms access 2003
For c As Integer = 1 To countC
Dim cmdstring As String
cmdstring = " INSERT INTO [KN - ProductionMachineAllocation] (BatchNo, ComponentID)
SELECT POH.BatchNo, SSCDD.ComponentID
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY BatchNo ASC) AS rownumber
([KN - ProductionOrderHeader] AS POH
INNER JOIN [FG - End Product Codes] AS EPC
ON POH.ProductID = EPC.ProductID)
INNER JOIN ([KN - ProductionOrderDetails] AS POD
INNER JOIN [FG - Style Size Comp Def Details] AS SSCDD
ON POD.SizeID = SSCDD.SizeID)
ON (POH.BatchNo = POD.BatchNo)
AND (EPC.StyleID = SSCDD.StyleID)
WHERE POH.BatchNo = '" & BatchNo & "'
) AS temptablename
WHERE rownumber IN (" & c & ");"
Dim con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Shantara Production IT.mdb")
Dim cmd As New OleDbCommand(cmdstring)
cmd.CommandType = CommandType.Text
cmd.Connection = con
cmd.Connection.Open()
cmd.ExecuteNonQuery()
cmd.Connection.Close()
Next
I found out that ms access doesn't support ROW_NUMBER() so I need to find another going through each row since ms access doesn't support multi row insert by insert into select statement such as mine, any suggestions around my problem?
Most databases are able to do all this work much more efficiently entirely in the database. Certainly in SQL Server I could get entire thing down to a single query. Access is a little different, since vbscript is its procedural language, rather than something more like t-sql. There's still probably a way to do it, but since what you have works, we can at least focus on making that better.
GridViews are visual constructs that will use up extra memory and resources. If Access won't do a real INSERT/SELECT, you can at least read direct from the previous result set into your insert. You can also improve on this significantly by using parameters and re-using a single open connection for all the inserts:
Dim cnString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Shantara Production IT.mdb"
Dim SQLDown As String = _
"SELECT DISTINCT POH.BatchNo, SSCDD.ComponentID
FROM ([KN - ProductionOrderHeader] AS POH
INNER Join [FG - End Product Codes] AS EPC
On POH.ProductID = EPC.ProductID)
INNER Join([KN - ProductionOrderDetails] AS POD
INNER Join [FG - Style Size Comp Def Details] AS SSCDD
On POD.SizeID = SSCDD.SizeID)
On (POH.BatchNo = POD.BatchNo)
And (EPC.StyleID = SSCDD.StyleID)
WHERE POH.BatchNo = ? "
Dim SQLUp As String = _
" INSERT INTO [KN - ProductionMachineAllocation]
(BatchNo, ComponentID)
VALUES( ?, ? )"
Dim dt As New DataTable
Using con As New OleDbConnection(cnString), _
cmd As New OleDbCommand(SQLDown, con)
'Guessing at parameter type/length here.
'Use the actual column type and size from your DB
cmd.Parameters.Add("#BatchNo", OleDbType.VarWChar, 10).Value = BatchNo
con.Open()
dt.Load(cmd.ExecuteReader())
End Using
Using con As New OleDbConnection(cnString), _
cmd As New OleDbCommand(SqlUp, con)
'Guessing at parameter types/lengths again
cmd.Parameters.Add("#BatchNo", OleDbType.VarWChar, 10)
cmd.Parameters.Add("#ComponentID", OleDbType.Integer)
'Connection is managed *outside of the loop*. Only one object created, only one negotiation with DB
con.Open()
For Each row As DataRow In dt.Rows
cmd.Parameters(0).Value = row(0)
cmd.Parameters(1).Value = row(1)
cmd.ExecuteNonQuery()
Next
End Using
Normally, with any ADO.Net provider you do not re-use your connection or command objects. You want a new connection object for every query sent to the DB to allow connection pooling to work correctly. Using the connection in a tight loop like this for the same query is one of the few exceptions.
I might be able to improve further by sticking with the active DataReader, rather than first loading it into a DataTable. That would allow us to avoid loading the entire result set into memory. You would only ever need one record in memory at a time. Certainly this would work for Sql Server. However, Access was designed mainly as a single-user database. It doesn't really like multiple active connections at once, and I'm not sure how it would respond.
It would also be nice to be able to do all of this work in a transactional way, where there's never any risk of it failing part way through the loop and getting stuck with half the updates. Sql Server would handle this via a single INSERT/SELECT query or with an explicit transaction. But, again, this isn't the kind of the Access is designed for. It probably does have a way to do this, but I'm not familiar with it.
OK SO I finally found a way around it, it's a bit of a long process but basically I loaded the SELECT statement(with multiple rows) into a gridview table and the used a for loop to insert it into my insert into statement. bellow is my code:
Displaying into a table
Dim Adapter As New OleDbDataAdapter
Dim Data As New DataTable
Dim SQL As String
Dim con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Shantara Production IT.mdb")
Dim cmd As New OleDbCommand()
grdvmachincomp.Visible = false
SQL = "SELECT DISTINCT POH.BatchNo, SSCDD.ComponentID
FROM ([KN - ProductionOrderHeader] AS POH
INNER Join [FG - End Product Codes] AS EPC
On POH.ProductID = EPC.ProductID)
INNER Join([KN - ProductionOrderDetails] AS POD
INNER Join [FG - Style Size Comp Def Details] AS SSCDD
On POD.SizeID = SSCDD.SizeID)
On (POH.BatchNo = POD.BatchNo)
And (EPC.StyleID = SSCDD.StyleID)
WHERE POH.BatchNo = '" & BatchNo & "'"
con.Open()
cmd.Connection = con
cmd.CommandText = SQL
Adapter.SelectCommand = cmd
Adapter.Fill(Data)
grdvmachincomp.DataSource = Data
grdvmachincomp.DataBind()
cmd.Connection.Close()
Insert into through for loop
For c As Integer = 0 To grdvmachincomp.Rows.Count - 1
Dim cmdstring As String
cmdstring = " INSERT INTO [KN - ProductionMachineAllocation] (BatchNo, ComponentID) VALUES('" & grdvmachincomp.Rows(c).Cells(0).Text & "', " & grdvmachincomp.Rows(c).Cells(1).Text & ");"
Dim con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Shantara Production IT.mdb")
Dim cmd As New OleDbCommand(cmdstring)
cmd.CommandType = CommandType.Text
cmd.Connection = con
cmd.Connection.Open()
cmd.ExecuteNonQuery()
cmd.Connection.Close()
Next

Execute Scalar to Label. Subquery returned more than 1 value

So I have a label which shows the username of the user. I've used this value to return their ID which I then attach to a label. I used execute scalar to do this because I wasn't sure how else to get a single value on a label.
This works fine. I then use the ID from the label and put it in another table. I can do this twice and then the page crashes saying...
"Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression."
However I don't understand. I don't pull anything from the second table on the page. I don't know why it would affect it. I feel like I've tried everything. Taking out the line that posts the ID to the label lets the page run but I need it there.
Label2.Text = User.Identity.Name
Dim connetionString As String
Dim cnn As SqlConnection
Dim cmd As SqlCommand
Dim sql As String
connetionString = "Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\FYPMS_DB.mdf;Integrated Security=True"
sql = "SELECT SupID FROM Supervisor WHERE (Email = #Email)"
cnn = New SqlConnection(connetionString)
Try
cnn.Open()
cmd = New SqlCommand(sql, cnn)
cmd.Parameters.Add(New SqlParameter("#Email", User.Identity.Name))
Dim supid1 As Int32 = Convert.ToInt32(cmd.ExecuteScalar())
cmd.Dispose()
cnn.Close()
Label1.Text = supid1.ToString
Catch ex As Exception
MsgBox("Can not open connection ! ")
End Try
End Sub
This should return the first result for you. Also, it's a good idea to employ Using blocks for objects such as connections, commands, and readers.
Using cn = New SqlConnection("Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\FYPMS_DB.mdf;Integrated Security=True")
cn.Open()
Using cmd = New SqlCommand("SELECT SupID FROM Supervisor WHERE Email = #Email", cn)
cmd.Parameters.AddWithValue("#Email", User.Identity.Name)
Using dr = cmd.ExecuteReader
If dr.Read Then
Label1.Text = CInt(dr("SupID"))
End If
End Using
End Using
End Using
If you are not sure there are multiple rows for same email in that table, you can change the query to following, that will work for you with executescalar.
SELECT TOP 1 SupID FROM Supervisor WHERE (Email = #Email)
Horribly sorry! But yes you were right! There was another query going on in the background that I never noticed that was affecting it all. So sorry

Retrieve the Id of recently inserted record

I currently have this SQL insert code in code behind
Dim con As New SqlConnection
Dim conString As String
conString = ConfigurationManager.ConnectionStrings("MyConnection").ConnectionString
con = New SqlConnection(conString)
con.Open()
Dim cmd As New SqlCommand("INSERT INTO AdditionalDaysRequest(Status, AdditionalDays, Justification,RequestDaySubmitted) VALUES (#Status,#AdditionalDays,#Justification,#RequestDaySubmitted)", con)
cmd.Parameters.AddWithValue("#Status", "Pending Request")
cmd.Parameters.AddWithValue("#AdditionalDays", TB_Days.Text)
cmd.Parameters.AddWithValue("#Justification", TB_Justification.Text)
cmd.Parameters.AddWithValue("#RequestDaySubmitted", Date.Now)
cmd.ExecuteNonQuery()
con.Close()
The Id in this table is automatically generated and incremented
What I would like to have now is the Id of this record inserted to add it to another table
Change your query text to add a second statement:
...;SELECT SCOPE_IDENTITY();
The SELECT SCOPE_IDENTITY() statement Returns the last identity value inserted into an identity column in the same scope as from the MSDN article above.
In addition, you can use the ability of the Sql engine to understand and process two or more command statements passed as a single string if you separe the statements with a semicolon.
In this way you have the great benefit to execute a single trip to the database.
Dim cmd As New SqlCommand("INSERT INTO AdditionalDaysRequest(Status, " & _
"AdditionalDays, Justification,RequestDaySubmitted) VALUES " & _
"(#Status,#AdditionalDays,#Justification,#RequestDaySubmitted);" & _
"SELECT SCOPE_IDENTITY()", con)
cmd.Parameters.AddWithValue("#Status", "Pending Request")
cmd.Parameters.AddWithValue("#AdditionalDays", TB_Days.Text)
cmd.Parameters.AddWithValue("#Justification", TB_Justification.Text)
cmd.Parameters.AddWithValue("#RequestDaySubmitted", Date.Now)
Dim result = cmd.ExecuteScalar()
con.Close()
if result IsNot Nothing Then
Dim lastInsertId = Convert.ToInt32(result)
End If
Notice that the two statements are now executed using ExecuteScalar instead of ExecuteNonQuery because we want to catch the result of the last command.
You will want to run a new SqlCommand. Set the value of lastInsertId with this statement:
SELECT SCOPE_IDENTITY()
This would be an additional knowledge.
we have multiple options like:
##IDENTITY
SCOPE_IDENTITY
IDENT_CURRENT
All three functions return last-generated identity values. However
IDENT_CURRENT returns the last identity value generated for a specific table in any session and any scope.
##IDENTITY returns the last identity value generated for any table in the current session, across all scopes.
SCOPE_IDENTITY returns the last identity value generated for any table in the current session and the current scope.

ASP.NET - VB.NET - Updating MS_Access table

I'm trying to update a record from an Ms-Access table with VB.NET and ASP.NET. I'm getting 2 errors:
On the web page that's opened I'm getting Thread was being aborted
Web Developer 2010 gives me an error says there's an error in the
UPDATE statement
This is the code so far:
Imports System.Data.OleDb
Partial Class ChangePassword
Inherits System.Web.UI.Page
Protected Sub btnChange_Click(sender As Object, e As System.EventArgs) Handles btnChange.Click
Dim tUserID As String = Session("UserID")
Dim conn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Brian\Documents\Visual Studio 2010\WebSites\WebSite3\db.mdb;")
conn.Open()
Dim cmd As OleDbCommand = New OleDbCommand("SELECT * FROM [User] where UserID=?", conn)
Dim cmd2 = New OleDbCommand("UPDATE USER SET [Password] = '" + txtConfPass.Text + "' where UserID = '" + tUserID + "'", conn)
cmd.Parameters.AddWithValue("#UserID", tUserID)
Dim read As OleDbDataReader = cmd.ExecuteReader()
Dim read2 As OleDbDataReader = cmd2.ExecuteReader()
lblUser.Text = tUserID.ToString
lblUser.Visible = True
If read.HasRows Then
While read.Read()
If txtOldPass.Text = read.Item("Password").ToString Then
cmd2.ExecuteNonQuery()
lblPass.Visible = True
End If
End While
Else
lblPass.Text = "Invalid Password."
lblPass.Visible = True
End If
conn.Close()
lblPass.Text = tUserID.ToString
lblPass.Visible = True
Any help would be appreciated.
Thanks !
First, your cmd2 fails because USER is a reserved word. Enclose in
square brackets as you already do in the first OleDbCommand.
Second, to execute a statement like UPDATE, INSERT, DELETE you call
cmd2.ExecuteNonQuery not ExecuteReader. Don't really needed that call
after the first for cmd.
Third, in the first OleDbCommand (cmd) you use a parameter for
UserID, why in the second one you revert to string concatenation for
user and password? This opens the door to any kind of Sql Injection
Attack.
Fourth, the Using statement assure that every Disposable object
used in your code will be CLOSED thus freeing the memory used by
this commands ALSO IN CASE OF EXCEPTIONS. An example of Using
statement here
(1)
Dim read2 As OleDbDataReader = cmd2.ExecuteReader()
and then
(2)
cmd2.ExecuteNonQuery()
Remove (1) - ExecuteNonQuery should do the update.
USER is a keyword in Access, add brackets the same way you have added in the Select statement. Next time, you are faced with a similar problem, print out the statement as Access would see it and try executing it on the database directly - that will point out the errors accurately.
Please use place holders for the update statement similar to the select statement.

Resources