Getting Error of type mismatch in vb6 - sql

I am using this code and getting error of type mismatch, runtime error '13'
Error is in line which is marked below, And specifically error is due to where condition (prereq.paid=" + rs1!paid + " ") in query...
rs1.Open "select name,nposts,postad.paid as paid from ad,post,postad where ad.adid = " +
cmbAdno.Text +
" and ad.adid=postad.adid and postad.pid=post.pid ", con, adOpenDynamic,
adLockOptimistic
While Not rs1.EOF
cmbTitle.AddItem (rs1!Name)
rs1.MoveNext
Wend
rs1.MoveFirst
cmbTitle.Text = rs1!Name
txtNposts.Text = rs1!nposts
If IsNumeric(rs1!paid) Then
MsgBox (rs1!paid + 1)
End If
**rs2.Open "select title from postad,prereq where postad.paid = prereq.paid and prereq.paid=" +
rs1!paid + " ", con, adOpenDynamic, adLockOptimistic**
While Not rs2.EOF
lstPrereq.AddItem (rs2!Title)
rs2.MoveNext
Wend
rs2.Close
rs1.Close

Whew, that code needs some work!
The plus operators are the culprit here though. You can easily verify this with a small test case.
Dim ADO_Field_Value As Variant
Dim S As String
ADO_Field_Value = True
On Error Resume Next
S = "text" + ADO_Field_Value + ""
If Err Then MsgBox "Plus failed, err " & CStr(Err)
Err.Clear
S = "text" & ADO_Field_Value & ""
If Err Then MsgBox "Amp failed, err " & CStr(Err)
If you run this the "+" yields an error 13 while the "&" works as expected.
Use the ampersand for concatenation. The plus only sorta, kinda works for backward compatibility with ancient times. Using it requires the compiler to guess at your intent in order to resolve the soft overloading of the operator.
Your "Null hack" concatenting an empty String to the .Value isn't particularly clever. If rs1 has a Null there you end up with a SQL syntax error, unless you use "+" which gets you an error 94.
ADO Field values are safer to access by explicitly using .Value instead of letting the compiler guess you want the default property of the Field. While/Wend is obsolete, and what's with those extraneous parentheses?
You are asking the compiler to do things it probably shouldn't in this code.

is rs1!paid a boolean in the database? if so, maybe there is an issue with the concat to make the query string.
In the old days, when i used VB6 i never accessed fields like that. I used something like rstRecordSet.Fields(0) or rstRecordSet.Fields("field1") but that should not be the problem if the field exists.
Create a string before and pass it the concatenation of the query and verify that it gets filled.
Also, you have "...postad.paid as paid...", why? you dont need to rename the field there...

Related

Validate SQL Query Integrity before Executing in VB6

I have a MS Access 2003 Application to port to Visual Basic 6.0 currently. For this purpose, I have written a copy of the usual DLookup commonly used in Access.
Here is the code so far.
Public Function cDLookup(TargetField As String, TargetTable As String, cTCondition As String) As String
'Eigene Implementation von DLookup
Dim result As String
Dim rs As New ADODB.Recordset
Dim SQL As String
On Error GoTo Fehlerbehandlung
'Zusammenbauen der Query
SQL = "SELECT " & TargetField & " FROM " & TargetTable & " WHERE " & cTCondition
Call dbConn
'Initiate Database connection object cn
rs.Open SQL, cn
If (rs.RecordCount = 1) Then
result = cleanString(rs.GetString)
Debug.Print ("[DLOOKUP] Erfolgreich Einen Datensatz gefunden und konvertiert. Output: " & result)
ElseIf (rs.RecordCount > 1) Then
result = "#ErrRC"
Debug.Print ("[DLOOKUP] Es wurden " & CStr(rs.RecordCount) & " Datensätze statt einem festgestellt. Dies ist nicht erlaubt")
Else
result = "#ErrGen"
Debug.Print ("[DLOOKUP] Es ist ein Fehler in der Abfrage aufgetreten")
End If
rs.Close
cDLookup = result
Exit Function
Fehlerbehandlung:
Debug.Print ("[DLOOKUP] Fehler im Ausführen der Prozedur cDLookup()]")
cDLookup = "#Fehler"
Exit Function
End Function
My main issue is with the generated Queries. If a user types garbage that gets inputted into this, there is a runtime error from ADODB when opening the recordset. Can I verify beforehand that a SQL query is not going to do that and catch it to not crash my entire program somehow?
No, not in the way you want. You need to just try to execute it, and handle the error gracefully. You could do something like create a function called "ValidateSQL" with its own error handler, try to execute it, and return false if the query failed. You could even pass the recordset in byref and set it to have the results if it passes.
It's been a long time so forgive syntax mistakes. Something like this:
Function ValidateSQL(ByRef rs as ADODB.Recordset) as Boolean
On Error GoTo Hell
ValidateSQL = True
'open recordset here
Set rs = ....
If False Then
Hell:
ValidateSQL = False
End If
End Function
If you know you're generating trash, why take the trash to the database and wait for the database to blow up to tell you it's trash? Fail Fast is a thing for a reason.
Hitting a database is not free. Even if it's relatively fast, it's orders of magnitude slower than plain code.
Don't get me wrong, I don't mean "validate that the specified field name does indeed exist in the table with the specified name" and "parse that where statement to see if it makes sense".
However, a few sanity-checks will cost much less than a useless trip to the database. You could:
Verify that the table and field names either don't contain any spaces, or are enclosed in square brackets;
Verify that the table and field names aren't empty;
Verify that the WHERE clause doesn't start with "WHERE", and that it's not empty.
If these simple checks pass, then have the database blow up if they're still wrong.

VBA Recordset - Object Doesn't support this property or method

Can anyone explain what is wrong with this code? There's a runtime error stating that the Object doesn't support this property or method
Set rst = DataFunctions.CheckCompanyID
If IsNull(rst.Fields("ID")) Then 'Error occurs here
ContactID = 0
Else
ContactID = rst!ID
End If
The CheckCompanyID method does as follows
CompanyValue = GetCurrentRecord
CheckData = "Select CompanyID, ID From Contacts Where Contacts.CompanyID = " & CompanyID & ";"
CheckCompanyID = CurrentDB.OpenRecordset(CheckData, dbOpenDynaset) 'Returns The Recordset
The If Is Null(rat.Fields("*FieldName*")) Then has been used elsewhere and works ok. I imagine the error is a result of returning the recordset object?
A suspected in my question comment, your function DataFunctions.CheckCompanyID does not return a recordset object, but Nothing instead. Nothing is VB's null.
This can happen if there is an unhandled error inside the function and On Error Resume Next is in effect, or simply because the function is implemented that way.
As a general tip: You should not use object references without checking that they are valid (i.e. not Nothing) to avoid run-time errors like this one.
You can check for Nothing easily:
Set rst = DataFunctions.CheckCompanyID
ContactID = 0
If Not rst Is Nothing
If IsNull(rst.Fields("ID")) Then
ContactID = rst!ID
End If
End If
Note: Classic VB does not support short-circuiting logical expressions, so you can't use the one-line form that other languages would allow:
If Not rst Is Nothing And Not IsNull(rst.Fields("ID")) Then
' This will cause an error because rst.Fields("ID") is always evaluated!
End If
check your rst, if it gets an recordset returned with results.
and try this:
IF nz(rst("ID"), "") = "" then
instead
If IsNull(rst.Fields("ID")) Then

OPTION STRICT OFF - NULL Exception

Please see the code below:
Dim strHideReason As String = strHideReason & " " & objDBDR.GetName(intHideCheck) & " is " & objDBDR(intHideCheck)
objDBDR(intHideCheck) is null. objDBDR is a datareader.
The code above compiles, however I am trying to set option strict to on, so I now have to do this:
Dim strHideReason As String = strHideReason & " " & objDBDR.GetName(intHideCheck) & " is " & cstr(objDBDR(intHideCheck))
It now throws an exception. I can refactor the code to resolve this, however I am confused why the first compiles. Does the compiler ignore objects that are null in string concatenations when option strict is off?
When you have OPTION STRICT OFF:
On runtime your object objDBDR(intHideCheck) will be automatically converted(if it possible) to type string.
From MSDN
For strings in Visual Basic, the empty string equals Nothing
objDBDR(intHideCheck) return Nothing which will be converted to string as empty string.
When you have OPTION STRICT ON:
This option restrict implicit conversions, and you must convert objects to string by your self.
For function Cstr if parameter is null, then runtime error will be throw
This answer will explain why runtime error will be thrown:
https://stackoverflow.com/a/979911/1565525

Error 440 in Visual Basic Application

There is an old VB application running at one of my clients.
An exception is throws in this peice of code:
cn=GetIndexDatabaseConnectionString()
sSql="SELECT * FROM Arh_Naroc WHERE StNarocila = '" & isci & "'"
rs=CreateObject("ADODB.Recordset")
Call rs.Open(sSql,cn)
The exception happens in rs.Open() function. "Error number 440 occured."
This are SBL scripts for KOFAX engine and it's many years old.
The whole SW was transferred from old XP computer to Windows 7 and looks like there are problems everywhere.
Can some one help me determine what is the problem here. At least if I could get a proper error message back in msgbox would be most helpful.
EDIT:
This is the connection string function.
Function GetIndexDatabaseConnectionString
Dim objXmlDocument As Object
Dim objXmlGlobalSettingsFileParh As Object
Dim objXmlIndexDatabaseConnectionString As Object
Dim strGlobalSettingsFilePath As String
Dim strTemp As String
Const strSettingsFilePath = "C:\Data\LocalDocsDistibutingSystem\Settings.xml"
Set objXmlDocument = CreateObject("MSXML2.DOMDocument")
objXmlDocument.Load strSettingsFilePath
Set objXmlGlobalSettingsFileParh = objXmlDocument.selectSingleNode("DocsDistributingSystem/GlobalSettingsFilePath")
strGlobalSettingsFilePath = objXmlGlobalSettingsFileParh.childNodes(0).Text
Set objXmlGlobalSettingsFileParh = Nothing
Set objXmlDocument = Nothing
Set objXmlDocument = CreateObject("MSXML2.DOMDocument")
objXmlDocument.Load strGlobalSettingsFilePath
Set objXmlIndexDatabaseConnectionString = objXmlDocument.selectSingleNode("DocsDistibutingSystem/AscentCapture/IndexDatabase/ConnectionString")
strTemp = objXmlIndexDatabaseConnectionString.childNodes(0).Text
Set objXmlIndexDatabaseConnectionString = Nothing
Set objXmlDocument = Nothing
GetIndexDatabaseConnectionString = strTemp
End Function
This is the relevant line from Settings.xml:
<ConnectionString> Provider=OraOLEDB.Oracle;Data Source=LINO2;User Id=****;Password=****;OLEDB.NET=True; </ConnectionString>
The real data is masked with *. The connection to Oracle appears to be ok. I created ODBC and linked server to sql using the provider and connection data. It works. It must be something missing installed on the computer for ADODB to work...
The connection appears to be working OK. There is no error when its initialized.
The error happens in Call rs.Open(sSql, cn). All i want is the detailed error message when the error happens...
Many thanks.
As it states on MS Knowledge Base
An error occurred while executing a method or getting or setting a
property of an object variable. The error was reported by the
application that created the object. Check the properties of the Err
object to determine the source and nature of the error. Also try using
the On Error Resume Next statement immediately before the accessing
statement, and then check for errors immediately following the
accessing statement.
So as they suggest check the Err object, in a similar fashion to:
If Err.Number <> 0 Then
Msg = "Error: " & Str(Err.Number) & ", generated by " _
& Err.Source & ControlChars.CrLf & Err.Description
MsgBox(Msg, MsgBoxStyle.Information, "Error")
End If
So this will bring back the error in a MsgBox, however you can just use Response.Write if you want it easier to copy & paste etc..
to get the error description you can do as follows :
Function GetIndexDatabaseConnectionString()
On Error GoTo Errorfound
'your
'function
'body
Exit Function
Errorfound:
With Err
MsgBox "Source: " & .Source & vbCrLf & "Desc: " & .Description, vbCritical, "Error " & CStr(.Number)
End With 'Err
End Function

Is it possible to submit data into a SQL database, wait for that to finish, and then return the ID generated from SQL, using Classic ASP?

I have an ASP form that needs to submit data to two different systems. First the data needs to go into an MS SQL database, which will get an ID. I then need to submit all that form data to an external system, along with that ID.
Pretty much everything in the code works just fine, the data goes into the database, and the data will go to the external system. The problem is I am not getting my ID back from SQL when I execute that query. I am under the impression this is happening because of how fast everything occurs in the code. The database is adding it's row at the same time my post page runs it's query to get the ID back, I think.
I need to know of a way to wait until SQL finished the insert or wait for a specific amount of time maybe. I already tried using the hacks to "sleep" with ASP, that did not help.
I am sure I could accomplish this in .Net, my background is more .Net than ASP, but this is what I have to work with on my current project.
Any ideas?
EDIT: Code from the the function writing to the DB.
driis - That was my understanding of how this should be working, but my follow up query for the ID returns nothing, so my though is that the row hasn't finished being inserted or updated yet. Maybe I am wrong on that, if so, that complicates this more. :(
Either way here is the code from the function to update the DB. Mind you this code is inherited, the rest of my project is being written by me, but I am stuck using these functions from a previous developer.
Sub DBWriteResult
Dim connLeads
Dim sSQL
Dim rsUser
Dim sErrorMsg
Dim sLeads_Connection
' Connect to the Leads database
' -------------------------------------------------------------------
sLeads_Connection = strDatabaseConnection
Set connLeads = CreateObject("ADODB.Connection")
connLeads.Provider = "SQLOLEDB.1"
On Error Resume Next
connLeads.Open sLeads_Connection
If Err.number <> 0 Then
' Bad connection display error
' -----------------------------------------------------------------
Response.Write "Database Write Error: 001 Contact Programmer"
Set connLeads = Nothing
Exit Sub
Else
' Verify the transaction does not already exist.
' -----------------------------------------------------------------------
Set rsUser = Server.CreateObject("ADODB.Recordset")
rsUser.LockType = 3
rsUser.CursorLocation = 3
sSQL = "SELECT * "
sSQL = sSQL & " FROM Leads;"
rsUser.Open sSQL, connLeads, adOpenDynamic
Response.Write Err.Description
If Err.number = 0 Then
' Add the record
' -----------------------------------------------------------
rsUser.AddNew
rsUser.Fields("LeadDate") = Date()&" "&Time()
rsUser.Fields("StageNum") = ESM_StageNum
rsUser.Fields("MarketingVendor") = ESMSourceData
rsUser.Fields("FirstName") = ESM_FirstName
rsUser.Fields("Prev_LName") = Request.Form ("Prev_LName")
rsUser.Fields("LastName") = ESM_LastName
rsUser.Fields("ProgramType") = ESM_ProgramType
rsUser.Fields("ProgramofInterest") = ESM_ProgramofInterest
rsUser.Fields("Phone1") = Phonenumber
rsUser.Fields("Phone2") = ESM_Phonenumber2
rsUser.Fields("Address1") = ESM_Address
rsUser.Fields("Address2") = ESM_Address2
rsUser.Fields("City") = ESM_City
rsUser.Fields("State") = ESM_State
rsUser.Fields("Region") = ESM_Region
rsUser.Fields("Zip") = ESM_Zip
rsUser.Fields("Country") = ESM_Country
rsUser.Fields("Email") = ESM_Email
rsUser.Fields("MilitaryBranch") = ESM_MilitaryBranch
rsUser.Fields("MilitaryStatus") = ESM_MilitaryStatus
rsUser.Fields("BestTimeToCall") = ESM_BestTimeToCall
rsUser.Fields("DateofBirth") = ESM_DateofBirth
rsUser.Update
Else
' There was an error
Response.Write "There was an error. Error code is: "&Err.number&" "&Err.Desc
End if
End If
' Close the recordset
' ---------------------------------------------------------------
Call rsUser.Close
Set rsUser.ActiveConnection = Nothing
Set rsUser = Nothing
' Destroy the connection to the database
' -------------------------------------------------------------------
Set connLeads = Nothing
End Sub
It sounds like you're trying to do this:
Insert some data in DB 1
Retrieve an ID from the inserted data
Send data + the ID to DB 2
It's been a good five years but I believe it looked something like this:
dim connStr1
connStr1 = "[connection string 1]"
dim conn1
set conn1 = server.createobject("adodb.connection")
conn1.open connStr1
dim sql
sql = " SET NOCOUNT ON " & vbCrLf & _
" INSERT FOO (a, b, c) VALUES (1, 2, 3) " & vbCrLf & _
" SET NOCOUNT OFF " & vbCrLf & _
" SELECT SCOPE_IDENTITY() "
dim rs
set rs = conn1.execute(sql)
rs.close
dim id
set id = CInt(rs(0))
conn1.close
dim connStr2
connStr2 = "[connection string 2]"
dim conn2
set conn2 = server.createobject("adodb.connection")
conn2.open connStr2
conn2.execute("INSERT FOO (id, a, b, c) VALUES (" & id & ", 1, 2, 3)")
conn2.close
Good luck, and get off my lawn!
Ok, so I figured this one out. The problem was insane, a typo. I am spoiled with .Net and the fact that if I use a variable that doesn't really exist, I get errors. I guess ASP doesn't care so much.
On the up side, driis was correct. The code does not continue until the database transaction is completed. That was my major concern, that had incorrectly assumed that was the case. I am glad I was right.
Thanks for the help, and hopefully the next time I post it'll be something better than a tyop.
;)