I need to get data from a recordset. The SQL query works fine in MS Access and returns exactly the expected values, but when the same query is lunched in VBA Excel, I get the following error:
No value given for one or more required parameters
Do you have any ideas why this problem occurs?
Thank you.
Philippe-Olivier Roussel
Private Sub CBtype_AfterUpdate()
Dim strConnexion As String
Dim connexion As New ADODB.Connection
strConnexion = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source= " & Database & ""
connexion.Open strConnexion
Dim rsMarque As New ADODB.Recordset
Dim seltype As String
seltype = CBtype.Value
rsMarque.Open "SELECT DISTINCT tblMarque.marque_nom FROM tblMarque, tblModele WHERE " & _
" tblMarque.marque_id = tblModele.marque_id AND tblModele.marque_id IN " & _
" (SELECT DISTINCT tblModele.marque_id FROM tblModele, tblType " & _
" WHERE tblModele.type_id = tblType.type_id AND tblModele.type_id = " & _
" (SELECT tblType.type_id FROM tblType WHERE " & _
" (tblType.type_nom = " & seltype & ")))", connexion, adOpenStatic
rsMarque.MoveFirst
With UserForm2.CBmarque
.Clear
Do
.AddItem rsMarque!marque_nom
rsMarque.MoveNext
Loop Until rsMarque.EOF
End With
End Sub
This error message looks like an output from the DBMS rather than Excel
I think you might be missing the apostrophe before and after your string variable. See if
" (tblType.type_nom = '" & seltype & "')))" works (I'm assuming the column you're querying is varchar type, since you declared seltype as string)
I found the following query in order to find out if a database table was created already or not:
if db_id('thedbName') is not null
--code mine :)
print 'db exists'
else
print 'nope'
Now I am wanting to use that same query within my VB.net application. This is the code I currently have elsewhere that connects to the database (that I am wanting to see if its there before doing all this):
Dim cn As SqlConnection = New SqlConnection("Data Source=DAVIDSDESKTOP;" & _
"Initial Catalog=thedbName;" & _
"Integrated Security=True;" & _
"Pooling=False")
Dim sql As String = "if db_id('thedbName') is not null " & vbCrLf & _
"Print() 'exists' " & vbCrLf & _
"else " & vbCrLf & _
"Print() 'nope'"
Dim cmd As SqlCommand = New SqlCommand(sql, cn)
cmd.Connection.Open()
Dim blah As String = cmd.ExecuteNonQuery()
cmd.Connection.Close()
Of course the issue with this is that I have to know the database name first in order to connect to the database.
I then seem to be able to connect to the master database using this:
Dim cn As SqlConnection = New SqlConnection("Data Source=DAVIDSDESKTOP;" & _
"Integrated Security=True;" & _
"Pooling=False")
Dim sql As String = "if db_id('thedbName') is not null " & vbCrLf & _
"Print() 'exists' " & vbCrLf & _
"else " & vbCrLf & _
"Print() 'nope'"
Dim cmd As SqlCommand = New SqlCommand(sql, cn)
cmd.Connection.Open()
Dim blah As String = cmd.ExecuteNonQuery()
cmd.Connection.Close()
But that query seems to throw an error on Dim blah As String = cmd.ExecuteNonQuery() of:
Additional information: Incorrect syntax near ')'.
So I'm not all sure what I am missing in order to correct the issue with the query?
Need to know how to have the query come back and say 'exists' or 'nope'
Change Print() to Print (remove the parentheses.)
Better, don't use Print at all, use select.
Dim sql As String = "if db_id('thedbName') is not null " & vbCrLf & _
"select 'exists' " & vbCrLf & _
"else " & vbCrLf & _
"select 'nope'"
Dim blah As String = CType(cmd.ExecuteScalar(), string)
ExecuteNonQuery returns the number of affected rows for updates and inserts. But what you are executing is a query.
ExecuteScalar returns the first column of the first row selected. The query above only returns one row with one value, so that's what it will return.
or do it like this
select * from sys.databases where [name] = 'thedbName'
if it returns a row, then the database exists, if not then it doesn't.
To check if a table exists within a database, use this
select * from sys.objects where [name] = 'theTableName' and type_desc = 'USER_TABLE'
I'm trying to reference userform data in SQL queries in excel 2010. When running the following code as my form submit action, I get an error that one or more parameters have not been provided in the SQL query.
Private Sub SubmitButton_Click()
Dim Connection As ADODB.Connection
Dim ConnectionString As String
ConnectionString = "Provider = Microsoft.ACE.OLEDB.12.0; Data Source=I:\DB.xlsx; Extended Properties=""Excel 12.0 Xml; HDR=YES"";"
Dim SQL As String
'Transfer information
SQL = "INSERT INTO [Tests$]" & _
"(PartNo, RootCause, CorrectiveAction, AssignedTo, Verification, Comments, DateOpened, DateClosed, " & _
"Status, Purpose, ProdDate, ShipDate, TestDate, SampleDate, CusName, Facility, Result, Wire, StartingDia, " & _
"WireType, IncomingDia, FailMode, RootCauseDetail)" & _
"VALUES" & _
"([Forms][frmTesting]![PartNo], [Forms][frmTesting]![RCause], [Forms][frmTesting]![Corrective], " & _
"[Forms][frmTesting]![Assigned], [Forms][frmTesting]![Verification], [Forms][frmTesting]![Comments], " & _
"[Forms][frmTesting]![OpenDate], [Forms][frmTesting]![CloseDate], [Forms][frmTesting]![Status], " & _
"[Forms][frmTesting]![Purpose], [Forms][frmTesting]![ProdDate], [Forms][frmTesting]![ShipDate], " & _
"[Forms][frmTesting]![TestDate], [Forms][frmTesting]![SampleDate], [Forms][frmTesting]![Customer], [Forms][frmTesting]![Facility], " & _
"[Forms][frmTesting]![Result], [Forms][frmTesting]![Wire], [Forms][frmTesting]![StartingDia], " & _
"[Forms][frmTesting]![WireType], [Forms][frmTesting]![IncomingDia], [Forms][frmTesting]![FailMode], [Forms][frmTesting]![RCDetail])"
Set Connection = New ADODB.Connection
Call Connection.Open(ConnectionString)
Call Connection.Execute(SQL, , CommandTypeEnum.adCmdText Or ExecuteOptionEnum.adExecuteNoRecords)
Connection.Close
Set Connection = Nothing
End Sub
Am I using the correct form object reference syntax for SQL queries? Is there a difference between Excel and Access with how to reference form data?
In case any viewers run across the same issue and are interested. I found the easiest solution to be something like SQL = "INSERT INTO [Tests$] (PartNo) Values ('" & frmTesting.PartNo & "')"
I am doing the programming on my computer and it works fine-the program, the database itself, inserting to the database is also working fine. But when I publish it and install the program on another computer. It crashes and does not execute the INSERT command.
Here is my code.
Private Sub cmdBlank_Click(sender As System.Object, e As System.EventArgs) Handles cmdBlank.Click
strTariff1 = txtPart1.Text & " " & txtPName1.Text & " " & txtQty1.Text & " " & txtU1.Text
strTariff2 = txtPart2.Text & " " & txtPName2.Text & " " & txtQty2.Text & " " & txtU2.Text
strTariff3 = txtPart3.Text & " " & txtPName3.Text & " " & txtQty3.Text & " " & txtU3.Text
strTariff4 = txtPart4.Text & " " & txtPName4.Text & " " & txtQty4.Text & " " & txtU4.Text
'strTariff5 = txtPart5.Text & " " & txtPName5.Text & " " & txtQty5.Text & " " & txtU5.Text
Call saveToDb()
frmreportax.Show()
End Sub
Private Function saveToDb()
conn.Close()
Dim cmdAdd, cmdCount, cmdAdd2 As New iDB2Command
Dim sqlAdd, sqlCount, sqlAdd2 As String
Dim curr1, curr2, curr3, curr4 As String
Dim count As Integer
conn.ConnectionString = str
conn.Open()
'Check for duplicate entry
sqlCount = "SELECT COUNT(*) AS count FROM cewe WHERE transport=#transport AND blnum=#blnum"
With cmdCount
.CommandText = sqlCount
.Connection = conn
.Parameters.AddWithValue("#transport", frmPart1.txtTransport.Text)
.Parameters.AddWithValue("#blnum", frmPart1.txtNo.Text)
End With
count = Convert.ToInt32(cmdCount.ExecuteScalar())
If count <> 0 Then
MsgBox("Duplicate Entry: " & frmPart1.txtTransport.Text, vbOKOnly + vbExclamation)
Else
sqlAdd = "INSERT INTO cewe (page) " & _
"VALUES (#page) "
With cmdAdd
.Parameters.AddWithValue("#page", Val(frmPart1.txtPage.Text))
.CommandText = sqlAdd
.Connection = conn
.ExecuteNonQuery()
End With
end if
cmdAdd.Dispose()
cmdAdd2.Dispose()
conn.Close()
end function
Please tell me what I am doing wrong? When I run and install the program on my PC, it works perfectly fine. But when I run/install it on another PC, it crashes after the cmdBlank is clicked.
There could be a number of things causing the issue but the first place to look is any error logs or crash report that may give some indication of the problem. Try debugging or logging to get a better picture. Beyond that there are some small suggestions that may help below.
Does the other computer have access to the database you are pointing to? Is the database connection pointing to localhost? In which case you will want to ensure that you have the same credentials (host, username, password, port etc.) set up on the database server on new computer. Are database drivers installed on new computer? What are the fundamental differences between the two machines?
AS400 iSeries DB2 needs to be updated to version 6.xx.0800 and did the tweak!
Installer can be found here
http://www-03.ibm.com/systems/power/software/i/access/windows_sp.html
Problem solved!
How can I change the following code to write to the database null instead of empty strings?
Public Sub SetChangeRequest(ByVal referenceLeaseID As Integer, _
ByVal referenceCustomerID As Integer, _
Optional ByVal custUnitNum As Object = Nothing, _
Optional ByVal driverFirstName As Object = Nothing, _
Optional ByVal driverLastName As Object = Nothing, _
Optional ByVal driverEmail As Object = Nothing, _
Optional ByVal plateNumber As Object = Nothing, _
Optional ByVal plateProvince As Object = Nothing, _
Optional ByVal usageProvince As Object = Nothing, _
Optional ByVal invoiceGroups As Object = Nothing)
mcmd = New SqlCommand
mcmd.CommandType = CommandType.Text
mcmd.Connection = mcn
mcmd.CommandText = "IF EXISTS (SELECT * FROM ChangeRequest WHERE ReferenceLeaseID = " & referenceLeaseID & ")" & vbNewLine & _
"DELETE FROM ChangeRequest WHERE ReferenceLeaseID = " & referenceLeaseID & vbNewLine & _
"INSERT INTO ChangeRequest (ReferenceLeaseID, ReferenceCustomerID, CustomerUnitNum, DriverFirstName, DriverLastName, DriverEmail, PlateNumber, PlateProvince, UsageProvince, InvGroupID)" & vbNewLine & _
"VALUES ('" & referenceLeaseID & "', '" & referenceCustomerID & "', '" & custUnitNum & "', '" & driverFirstName & "', '" & driverLastName & "', '" & driverEmail & "', '" & plateNumber & "', '" & plateProvince & "', '" & usageProvince & "', '" & invoiceGroups & "')"
mcn.Open()
mcmd.ExecuteScalar()
mcn.Close()
End Sub
Cheers,
Mike
They way you're constructing your query is inefficient, hard to read, error prone, and worst of all open to SQL injection attacks. You should use SQL parameters:
mcmd.CommandText = "IF EXISTS (SELECT * FROM ChangeRequest WHERE ReferenceLeaseID = #referenceLeaseID") " _
"DELETE FROM ChangeRequest WHERE ReferenceLeaseID = #referenceLeaseID " & _
"INSERT INTO ChangeRequest (ReferenceLeaseID, ReferenceCustomerID, CustomerUnitNum, DriverFirstName, DriverLastName, DriverEmail, PlateNumber, PlateProvince, UsageProvince, InvGroupID) " & _
"VALUES (#referenceLeaseID, #referenceCustomerID, #custUnitNum, #driverFirstName, #driverLastName, #driverEmail, #plateNumber, #plateProvince, #usageProvince, #invoiceGroups)"
You can specify values for parameters like:
mcmd.Parameters.Add("#parameterName", If(ParameterValue Is Nothing, DBNull.Value, ParameterValue))
Biggest thing I'd suggest is you use a parameterised sql statement as you're opening up yourself to sql injection.
e.g.
command.CommandText = "INSERT SomeTable (SomeField) VALUES (#SomeField)";
And then add the named parameters to the command using command.Parameters.Add
For values you want to store as NULL, set the parameter value to DBNull.Value.
You can use DBNull.Value.
http://msdn.microsoft.com/en-us/library/system.dbnull.value.aspx
Use a parameterized query instead of putting the values in SQL. Besides fixing the nulls issue, it will also protect against SQL injection.
Public Sub SetChangeRequest(ByVal referenceLeaseID As Integer, _
ByVal referenceCustomerID As Integer, _
Optional ByVal custUnitNum As Object = Nothing, _
Optional ByVal driverFirstName As Object = Nothing, _
Optional ByVal driverLastName As Object = Nothing, _
Optional ByVal driverEmail As Object = Nothing, _
Optional ByVal plateNumber As Object = Nothing, _
Optional ByVal plateProvince As Object = Nothing, _
Optional ByVal usageProvince As Object = Nothing, _
Optional ByVal invoiceGroups As Object = Nothing)
mcmd = New SqlCommand
mcmd.CommandType = CommandType.Text
mcmd.Connection = mcn
mcmd.CommandText = "IF EXISTS (SELECT * FROM ChangeRequest WHERE ReferenceLeaseID = " & referenceLeaseID & ")" & vbNewLine & _
"DELETE FROM ChangeRequest WHERE ReferenceLeaseID = " & referenceLeaseID & vbNewLine & _
"INSERT INTO ChangeRequest (ReferenceLeaseID, ReferenceCustomerID, CustomerUnitNum, DriverFirstName, DriverLastName, DriverEmail, PlateNumber, PlateProvince, UsageProvince, InvGroupID)" & vbNewLine & _
"VALUES (#ReferenceLeaseID, #ReferenceCustomerID, #CustomerUnitNum, #DriverFirstName, #DriverLastName, #DriverEmail, #PlateNumber, #PlateProvince, #UsageProvince, #InvGroupID)"
mcmd.Parameters.AddWithValue("ReferenceLeaseID", referenceLeaseID)
mcmd.Parameters.AddWithValue("ReferenceCustomerID", referenceCustomerID )
mcmd.Parameters.AddWithValue("CustomerUnitNum", custUnitNum)
mcmd.Parameters.AddWithValue("DriverFirstName", driverFirstName)
mcmd.Parameters.AddWithValue("DriverLastName", driverLastName)
mcmd.Parameters.AddWithValue("DriverEmail", driverEmail)
mcmd.Parameters.AddWithValue("PlateNumber", plateNumber)
mcmd.Parameters.AddWithValue("PlateProvince", plateProvince)
mcmd.Parameters.AddWithValue("UsageProvince", usageProvince)
mcmd.Parameters.AddWithValue("InvGroupID", invoiceGroups)
mcn.Open()
mcmd.ExecuteScalar()
mcn.Close()
End Sub
If you really, really wanted to, you make the query you're constructing work by doing something like the following:
"VALUES (" & IIf(referenceLeaseID Is Nothing, "NULL", "'" & referenceLeaseID & "'"))
...but please, please don't do that. The code is ugly, hard to maintain, and allows for all kinds of unpleasantness like SQL injection.
Instead, use a parameterized query -- the entire process is pretty well explained in this MSDN article.
After the first pass, your code will then look something like this:
Dim cmd = New SqlCommand(".... VALUES (#p0)")
cmd.Parameters.Add(New SqlParameter("#p0", referenceLeaseID))
...which is still not pretty: the long multi-line SQL queries will continue to clutter your code.
To fix that issue as well, move your query into a stored procedure. This has the huge advantage of being able to compose your SQL in an editor that is intended for this purpose, instead of kludging it up in code. If you use a recent version of SQL Server Studio, or of course the indispensable SQL Prompt utility, you'll even have some nice Intellisense support.
The stored procedure will be pretty much identical to your current query, with some additional parameter declarations:
CREATE PROCEDURE UpdateDriverRecord
#referenceLeaseID NVARCHAR(42)
BEGIN
...VALUES(referenceLeaseID = #referenceLeaseID)
END
Your final code will the look something like:
Dim cmd = New SqlCommand("UpdateDriverRecord")
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("#referenceLeaseID", SqlDbType.NVarChar, 42)
This may seem like a lot of changes to work around a simple issue, but your code will be much more secure, readable and maintainable.