Last 'OR' statement Ignored in OLEDB command - vb.net

I'm trying to filter a OLEDB command by having multiple 'OR' statements work on a single database field but the last in the chain gets ignored and doesn't return anything.
I have a work around for now with a #null request that returns "DBNull.value" but if I remove "[doctype] = #null" from below it ignores "[doctype] = doctype3"
& "WHERE [doctype] = #doctype OR [doctype] = #doctype2 OR [doctype] = #doctype3 OR [doctype] = #null " _
I can increase or decrease the 'OR Statements' as I like but it is always the last 'OR Statement' that is ignored.
I've tried putting the 'OR statements' in brackets but then it returns nothing, or I'm doing it wrong.
I'm looking for simply why the last 'or statement' is ignored in the oledbcommand string but if you can improve any code I've wrote please do, but explain to me why/how.
Where they are used (Every other value has DBNull.value for testing purposes)
f_doctype = "MS"
f_doctype2 = "TMS"
f_doctype3 = "CS"
With cmdaRefresh.Parameters
.AddWithValue("doctype", CType(f_doctype, String))
.AddWithValue("doctype2", CType(f_doctype2, String))
.AddWithValue("doctype3", CType(f_doctype3, String))
.AddWithValue("null", DBNull.Value)
.AddWithValue("docnum", DBNull.Value)
.AddWithValue("docrev", DBNull.Value)
.AddWithValue("matname", DBNull.Value)
.AddWithValue("status", DBNull.Value)
.AddWithValue("actionreq", DBNull.Value)
.AddWithValue("createdby", DBNull.Value)
.AddWithValue("createddate", DBNull.Value)
.AddWithValue("finalby", DBNull.Value)
.AddWithValue("finaldate", DBNull.Value)
End With
Dim cmdRefresh As New OleDbDataAdapter(cmdaRefresh)
'open connection
myconnection.Open()
'read and fill dataset for gridview
cmdRefresh.Fill(dsRefresh, tbl_string.tablename)
'close connection
myconnection.Close()
'fill datagrid with values from database and alter column headers to match criteria
With dg_speclog
.DataSource = dsRefresh.Tables(0)
.RowHeadersVisible = False
.Columns(0).HeaderCell.Value = "Category"
...
End With
Full 'oledbcommand' creation
Dim cmdaRefresh As OleDbCommand = New OleDbCommand(" SELECT [doctype], [docnum], [docrev], [matname], [status], [actionreq], [createdby], [createddate], [finalby], [finaldate] " _
& "FROM " & tbl_string.tablename & " " _
& "WHERE [doctype] = #doctype OR [doctype] = #doctype2 OR [doctype] = #doctype3 OR [doctype] = #null " _
& "AND [docnum] = #docnum " _
& "AND [docrev] = #docrev " _
& "AND [matname] = #matname " _
& "AND [status] = #status " _
& "AND [actionreq] = #actionreq " _
& "AND [createdby] = #createdby " _
& "AND [createddate] = #createddate " _
& "AND [finalby] = #finalby " _
& "AND [finaldate] = #finaldate " _
& "ORDER BY [docnum] ASC, [docrev] ASC " _
, myconnection)

You need to use IS NULL to check for null values (in most, perhaps all, databases, null does not equal null, so you need to use the IS operator instead). This also means you don't need all those parameters.
Depending on how you intend to combine the [doctype] IS NULL check with the other null checks, you may also need to wrap the ORs in parentheses, since AND may have higher precedence than OR.
Dim cmdaRefresh As OleDbCommand = New OleDbCommand(
" SELECT [doctype], [docnum], [docrev], [matname], [status], [actionreq], [createdby], [createddate], [finalby], [finaldate] " _
& "FROM " & tbl_string.tablename & " " _
& "WHERE ([doctype] = #doctype OR [doctype] = #doctype2 OR [doctype] = #doctype3 OR [doctype] IS NULL) " _
& "AND [docnum] IS NULL " _
& "AND [docrev] IS NULL " _
& "AND [matname] IS NULL " _
& "AND [status] IS NULL " _
& "AND [actionreq] IS NULL " _
& "AND [createdby] IS NULL " _
& "AND [createddate] IS NULL " _
& "AND [finalby] IS NULL " _
& "AND [finaldate] IS NULL " _
& "ORDER BY [docnum] ASC, [docrev] ASC " _
, myconnection)
If the[doctype] IS NULL check belongs with the other NULL checks then you don't need the parens.

Found the reason why it wasn't working. Somewhere during my search I read that DBNull.value would return anything from the database when used with a .addwithvalue statement (which might of confused the whole thing). Which is not correct, it returns anything that has a value of nothing as in no white space or value. Which is why [doctype] IS NULL gave the same issue as above, it does the same thing, I think.
What I was looking for was a way to search through my [doctype]'s and return any value from the other database fields without having to specify anything 'for testing'
The statement I was looking for was [docnum] LIKE '%' this is called a Wildcard. A wildcard character can be used to substitute for any other character(s) in a string, so that mean anything is returned. However if the database field is of value Null then a IS NULL statement is still require, hence my [finalyby] & [finaldate] alterations below.
What I've came up with now is:
'CHANGED (dataadapter > command)
Dim cmdaRefresh As OleDbCommand = New OleDbCommand(" SELECT [doctype], [docnum], [docrev], [matname], [status], [actionreq], [createdby], [createddate], [finalby], [finaldate] " _
& "FROM " & tbl_string.tablename & " " _
& "WHERE [doctype] IN (#doctype, #doctype2 ,#doctype3) " _
& "AND [docnum] LIKE '%' " _
& "AND [docrev] LIKE '%' " _
& "AND [matname] LIKE '%' " _
& "AND [status] LIKE '%' " _
& "AND [actionreq] LIKE '%' " _
& "AND [createdby] LIKE '%' " _
& "AND [createddate] LIKE '%' " _
& "AND ([finalby] LIKE '%' OR [finalby] IS NULL) " _
& "AND ([finaldate] LIKE '%' OR [finaldate] IS NULL) " _
& "ORDER BY [docnum] ASC, [docrev] ASC " _
, myconnection)
Thank you to who helped.

Related

How to Pass SQL Parameter to Form Using OpenArgs?

I have a Database (not built by me) that uses 3 separate forms to accomplish 1 thing.
I would instead like to pass a SQL string to the OpenArgs in order to utilize 1 form.
Original Code for form I'd like to utilize:
Private Sub Form_Open(Cancel As Integer)
Dim strSQL As String
If Not IsNull(Me.OpenArgs) Then
strSQL = "SELECT tbl_COMBINED.[First Name] AS [Name Badge], 'P' AS Logo, Format(Now(),""yyyy"") & STOCKHOLDERS MEETING' AS MEETING " _
& "FROM tbl_COMBINED " _
& "GROUP BY tbl_COMBINED.[First Name], 'P', Format(Now(),""yyyy"") & ' STOCKHOLDERS MEETING', " _
& "tbl_COMBINED.ACCOUNT, tbl_COMBINED.Came " _
& "HAVING tbl_COMBINED.ACCOUNT = '" & CStr(Me.OpenArgs) & "' " _
& "AND ((tbl_COMBINED.Came) Is Null Or (tbl_COMBINED.Came)) = 0"
Me.RecordSource = strSQL
End If
End Sub
Each of the other forms is called by using
DoCmd.OpenForm "frm_newmanualnamebadge", "", "",, acNormal
from the Main form and has the SQL string in the row source. I would like to eliminate the row source and utilize the 1 form. I set the string from each button to:
strManuel = "SELECT tbl_manual_name_badge.NAMEBADGE1, tbl_manual_name_badge.MEETING, " _
& "tbl_manual_name_badge.LOGO, tbl_manual_name_badge.Stockerholder " _
& "FROM tbl_manual_name_badge"
DoCmd.OpenForm "frm_newmanualnamebadge", "", "",, acNormal, strManual
Passing the strManual to the form as a SQL string, however, every time I run it I get a "#Name?" in the name field instead of the name entered.
Here is the code I used on the form:
If Not IsNull(Me.OpenArgs) Then
strSQL = "SELECT tbl_COMBINED.[First Name] AS [Name Badge], 'P' AS Logo " _
& "FROM tbl_COMBINED " _
& "GROUP BY tbl_COMBINED.[First Name], 'P', " _
& "tbl_COMBINED.ACCOUNT, tbl_COMBINED.Came " _
& "HAVING tbl_COMBINED.ACCOUNT = '" & CStr(Me.OpenArgs) & "' " _
& "AND ((tbl_COMBINED.Came) Is Null Or (tbl_COMBINED.Came)) = 0"
Me.RecordSource = strSQL
ElseIf IsNull(Me.OpenArgs) Then
strSQL = "SELECT tbl_manual_name_badge.NAMEBADGE1, tbl_manual_name_badge.MEETING, " _
& "tbl_manual_name_badge.LOGO, tbl_manual_name_badge.Stockerholder " _
& "FROM tbl_manual_name_badge"
Me.RecordSource = strSQL
End If
Well, you either pass one value, or you pass the whole sql string.
But, if you passing the WHOLE sql string for the form, then this makes no sense:
If Not IsNull(Me.OpenArgs) Then
strSQL = "SELECT tbl_COMBINED.[First Name] AS [Name Badge], 'P' AS Logo " _
& "FROM tbl_COMBINED " _
& "GROUP BY tbl_COMBINED.[First Name], 'P', " _
& "tbl_COMBINED.ACCOUNT, tbl_COMBINED.Came " _
& "HAVING tbl_COMBINED.ACCOUNT = '" & CStr(Me.OpenArgs) & "' " _
& "AND ((tbl_COMBINED.Came) Is Null Or (tbl_COMBINED.Came)) = 0"
Me.RecordSource = strSQL
I mean, OpenArgs is a WHOLE sel string, and I am VERY sure that ACCOUNT = " some huge sql string" will NEVER work.
So, you would want this:
Dim strSQL As String
If Not IsNull(Me.OpenArgs) Then
strSQL = me.OpenArgs
else
strSQL = "SELECT tbl_manual_name_badge.NAMEBADGE1, tbl_manual_name_badge.MEETING, " _
& "tbl_manual_name_badge.LOGO, tbl_manual_name_badge.Stockerholder " _
& "FROM tbl_manual_name_badge"
End If
Me.RecordSource = strSQL
So, our logic is now:
if passed sql string (openargs), then that becomes our sql
if no open arges, then use the defined sql we have in the on-load

Run time error 3061 Too few parameters expected 4

CurrentDb.Execute "UPDATE Customer set [FirstName] = " & Me.FirstName & _
" ,[LastName] = " & Me.LastName & _
" ,[PhoneNumber] = '" & Me.PhoneNumber & _
"' ,[Address] = '" & Me.Address & _
"' ,[City] = " & Me.City & _
" ,[State] = " & Me.State & _
" ,[ZipCode] = " & Me.ZipCode & " WHERE ([E-mail] = '" & Me.email & "')"
what is wrong with this update query. Please help.
Once again, consider SQL parameterization, an industry best practice when working with SQL, which is supported in MS Access using PARAMETERS clause and QueryDefs. You avoid messy concatenation, quote enclosures (which you are missing quite a bit for your text fields), and possibly SQL injection as such fields are open to users.
SQL (save as a stored Access query)
PARAMETERS [FirstNameParam] Text(255), [LastNameParam] Text(255),
[PhoneNumberParam] Text(255), [AddressParam] Text(255),
[CityParam] Text(255), [StateParam] Text(255),
[ZipCodeParam] Text(255), [EmailParam] Text(255);
UPDATE Customer
SET [FirstName] = [FirstNameParam],
[LastName] = [LastNameParam],
[PhoneNumber] = [PhoneNumberParam],
[Address] = [AddressParam],
[City] = [CityParam],
[State] = [StateParam],
[ZipCode] = [ZipCodeParam]
WHERE ([E-mail] = [EmailParam]);
VBA
Dim qdef As QueryDef
Set qdef = CurrentDb.QueryDefs("mySavedParameterQuery")
' BIND VALUES TO PARAMETER PLACEHOLDERS
qdef![FirstNameParam] = Me.FirstName
qdef![LastNameParam] = Me.LastName
qdef![PhoneNumberParam] = Me.PhoneNumber
qdef![AddressParam] = Me.Address
qdef![CityParam] = Me.City
qdef![StateParam] = Me.State
qdef![ZipCodeParam] = Me.ZipCode
qdef![EmailParam] = Me.Email
' EXECUTE ACTION QUERY
qdef.Execute dbFailOnError
Set qdef = Nothing
Just a guess from looking at your SQL and the error - I suspect your 4 field names with two words should likely have spaces between the two words: [FirstName] becomes [First Name], [Last Name] becomes [Last Name] and so on
So SQL string should actually be
"UPDATE Customer set [First Name] = " & Me.FirstName & _
" ,[Last Name] = " & Me.LastName & _
" ,[Phone Number] = '" & Me.PhoneNumber & _
"' ,[Address] = '" & Me.Address & _
"' ,[City] = " & Me.City & _
" ,[State] = " & Me.State & _
" ,[Zip Code] = " & Me.ZipCode & " WHERE ([E-mail] = '" & Me.email & "')"
As #Jiggles32 says - the only way to know for sure is to show us your field names from the Customer table

SQL query assistance needed with 'NOT'

I'm working out of VB6 with SQL SERVER 2012. I found myself in a pickle. Basically i have a query that works fine and pulls the necessary data in SQL SERVER, however, I'm having a difficult time translating it to vb6 SQL code. Here's a working query in SQL SERVER...
SELECT 'TotalSum' = SUM(Units)
FROM tblDetail
WHERE MemberID = '117'
AND CAST(SStartD AS DATETIME) >= '4/1/2016'
AND CAST(SStartD AS DATETIME) <= '4/7/2016'
AND Service = 166
AND [CODE] IN('1919')
AND NOT(InvoiceNo = '11880'
AND DtlNo = 2
)
AND NOT(InvoiceNo = '11880'
AND AdjNo = 2
);
So when I try to write it in my vb6 application i do something like
SELECT 'TotalSum' = SUM(Units)
FROM tblDetail
WHERE MemberID = '117'
AND CAST(SStartD AS DATETIME) >= '4/1/2016'
AND CAST(SStartD AS DATETIME) <= '4/7/2016'
AND Service = 166
AND [CODE] IN('1919')
AND (InvoiceNo <> '11880'
AND DtlNo <> 2
)
AND (InvoiceNo <> '11880'
AND AdjNo <> 2
);
However, this is not giving me the same results. Whats happening is in my last two clauses
( InvoiceNo <> '11880' AND DtlNo<> 2) AND (InvoiceNo <> '11880' AND AdjNo <> 2)
When I run them finally in SQL SERVER don't have paranthesis and its absolutely detrimental that the 2 seperate clauses are in paranthesis. Anyone know what I can do? I think my last resort might be to create a store procedure but i don't really want to do that.
EDIT:
g_SQL = "SELECT 'SUM' = SUM(Units) " & _
"FROM tblDetail WHERE " & _
"MemID = " & udtCDtl.Lines(udtCDtlIdx).MemID & " AND " & _
"CAST(SStartD As DateTime) >= '" & StartDate & "' AND " & _
"CAST(SStartD As DateTime) <= '" & DateAdd("d", -1, EndDate) & "' AND " & _
"Service = 166 AND " & _
"[CODE] IN (‘1919’)) And " & _
("InvoiceNo <> " & InvoiceDtlRS!InvoiceHdrNo & " OR " & _
"DtlNo <> " & (InvoiceDtlRS! InvoiceDtlNo, "")) & " AND " & _
("InvoiceNo <> " & InvoiceDtlRS!InvoiceHdrNo & " OR " & _
"AdjNo <> " & InvoiceDtlRS! InvoiceDtlNo)
Your translation of NOT(InvoiceNo = '11880' AND DtlNo = 2) to (InvoiceNo <> '11880' AND DtlNo <> 2) is incorrect.
In formal logic, !(A & B) is equivalent to (!A or !B), so it should be:
(InvoiceNo <> '11880' OR DtlNo <> 2)
This is why you're getting different results. However, why not use the original query? There's nothing in VB6 which would prevent it.
EDIT
g_SQL = "SELECT 'SUM' = SUM(Units) " & _
"FROM tblDetail WHERE " & _
"MemID = " & udtCDtl.Lines(udtCDtlIdx).MemID & " AND " & _
"CAST(SStartD As DateTime) >= '" & StartDate & "' AND " & _
"CAST(SStartD As DateTime) <= '" & DateAdd("d", -1, EndDate) & "' AND " & _
"Service = 166 AND " & _
"[CODE] IN (‘1919’)) And " & _
("InvoiceNo <> " & InvoiceDtlRS!InvoiceHdrNo & " OR " & _
"DtlNo <> " & (InvoiceDtlRS! InvoiceDtlNo, "")) & " AND " & _
("InvoiceNo <> " & InvoiceDtlRS!InvoiceHdrNo & " OR " & _
"AdjNo <> " & InvoiceDtlRS! InvoiceDtlNo)
You've got a ) in the wrong place twice. Also, the ) on the final live would be a syntax error I think. The last 5 lines should be:
"[CODE] IN (‘1919’) And " & _
("InvoiceNo <> " & InvoiceDtlRS!InvoiceHdrNo & " OR " & _
"DtlNo <> " & (InvoiceDtlRS!InvoiceDtlNo, "") & " AND " & _
("InvoiceNo <> " & InvoiceDtlRS!InvoiceHdrNo & " OR " & _
"AdjNo <> " & InvoiceDtlRS!InvoiceDtlNo & ")"
This should work. I'm able to use SQL queries using NOT with ADODB in VB6.
g_SQL = "SELECT 'SUM' = SUM(Units) " & _
"FROM tblDetail WHERE " & _
"MemID = " & udtCDtl.Lines(udtCDtlIdx).MemID & " AND " & _
"CAST(SStartD As DateTime) >= '" & StartDate & "' AND " & _
"CAST(SStartD As DateTime) <= '" & DateAdd("d", -1, EndDate) & "' AND " & _
"Service = 166 AND " & _
"[CODE] IN ('1919')) And " & _
"NOT (InvoiceNo = " & InvoiceDtlRS!InvoiceHdrNo & " AND DtlNo = " & InvoiceDtlRS!InvoiceDtlNo & ") AND " & _
"NOT (InvoiceNo = " & InvoiceDtlRS!InvoiceHdrNo & " AND AdjNo = " & InvoiceDtlRS!InvoiceDtlNo & ")"
While Marc may have given you a query that works, Simon's question is still valid. The only reason your original query wouldn't work is because you munged the quotes. You'll notice that your parentheses by the reference to InvoiceNo are outside the quotes rather than inside them (there are other problems as well, from changing your original query, but I'll leave you to figure those out for yourself). That makes them not part of the quoted string, and instead part of the VB6 expression. Frankly, Marc isn't doing you any favors by providing an alternative SQL query that happens to have all the VB6 syntax correct, while yours does not. The real problem is that you haven't worked out how to put a SQL query into a quoted string carefully enough.
You can't afford that kind of carelessness if you want to be good at what you're doing. I don't say this to be offensive, but to get your attention. By adopting Marc's solution as the correct one, you haven't really solved your problem, because your problem is a mindset that doesn't think about anything except getting something to work. That mindset makes for the worst kind of programmer, the kind that writes terrible code (hundreds of lines of code where it could be done in 10, for example) that makes nightmares for people who have to maintain it later. Don't be one of those people. When you don't know why something isn't working, go to the trouble of figuring out why. You only have to do it once for each problem, and that mindset will stand you well as you continue to develop your skills.
Again, no disrespect intended. I'm just trying to get you to understand how to avoid getting in "pickles" like this one in future. Hopefully, the next time you post a question here, the "pickle" you're in will be more sophisticated. :)
EDIT: I guess I'm not making myself clear enough. The simple rule is that you need to enclose everything in the working SQL query in quoted strings, and replace the literal search values with references to text boxes, fields, or whatever. So:
sql = "SELECT 'TotalSum' = SUM(Units) " & _
"FROM tblDetail " & _
"WHERE MemberID = '" & myVariable & "' " & _
"AND CAST(SStartD AS DATETIME) >= '" & myVariable & "' " & _
"AND CAST(SStartD AS DATETIME) <= '" & myVariable & "' " & _
"AND Service = 166 " & _
"AND [CODE] IN('1919') " & _
"AND NOT(InvoiceNo = '" & myVariable & "' " & _
"AND DtlNo = " & myVariable & _
")" & _
"AND NOT(InvoiceNo = '" & myVariable & "' " & _
"AND AdjNo = " & myVariable & _
");"
Where myVariable is whatever variable reference you want to replace your literal string with. Any examples you've given have errors in placement of double quotes, which is why you aren't getting the result you want, which is presumably a replication of your working SQL query. The reason Marc's works is not because he altered your original query (it doesn't look like he has, except to put it on less lines) but because he placed his quotation marks correctly. The reason your and simon's solutions don't work is because neither of you have. Going back to your original post, the reason that the parentheses fail to show is because you haven't enclosed them in quotes. Marc has.

Empty field in .mdb to be filled with 9999 vba

I have tblTFM that has new inserts from TempTable_Update, and TempTable has an blank field, which I want to see ,for example, as 9999.
This is my code to insert new fields, it works fine.
myDB.Execute "INSERT INTO tblTFM(TFMAgreNu)" _
& "SELECT DISTINCT [TempTable_Update].[TFMAgreNu] " _
& "FROM TempTable_Update " _
& "WHERE (((Exists (SELECT TFMAgreNu FROM tblTFM WHERE tblTFM.TFMAgreNu = TempTable_Update.TFMAgreNu))=False));"
myDB.Execute "UPDATE TempTable_Update " _
& "INNER JOIN tblTFM ON [TempTable_Update].[TFMAgreNu] = [tblTFM].[TFMAgreNu] " _
& "SET [TempTable_Update].[TFM_ID] = [tblTFM].[TFM_ID] " _
& "WHERE [TempTable_Update].[TFMAgreNu] = [tblTFM].[TFMAgreNu];"
But I did research how to do UPDATE to set blank fields as 9999 and tried this...
strQuery = "UPDATE [tblTFM] SET [tblTFM].[TFMAgreNu] = 0 " _
& "WHERE ((([tblTFM].[TFMAgreNu])="")); " _
& "UPDATE [tblTFM] SET [tblTFM].[TFMArgeNu] = 9999 " _
& "WHERE ((([tblTFM].[TFMAgreNu])= 0 ));"
It didnt work well
and this...
strQuery = "UPDATE tblTFM SET tblTFM.TFMAgreNu = 9999 WHERE tblTFM.TFMAgreNu IS NULL
Didn't work as well...
Could somebody please help me with the code for this update?
You can't have two UPDATE statements in one query, as in your first try.
If TFMAgreNu is a number field, then this should work:
strQuery = "UPDATE tblTFM SET tblTFM.TFMAgreNu = 9999 " & _
"WHERE Nz(tblTFM.TFMAgreNu, 0) = 0"
It checks for NULL and 0 by using the Nz() function.
EDIT
For a text field, use
strQuery = "UPDATE tblTFM SET tblTFM.TFMAgreNu = '9999' " & _
"WHERE Nz(tblTFM.TFMAgreNu, '') = ''"

phone type in computed property

In the following code sample the property type for [MainSwitchBoardPhone] is "Phone". When I make the computed ClinicHospitalAddress property the summary property for the Entity I would like the phone number to show up in a data entry screen with (555) 555-5555 format rather than merely a string. i.e. 5555555555. Is there a way to do this?
Private Sub ClinicHospitalAddress_Compute(ByRef result As String)
' Set result to the desired field value
result = [ClinicHospital] & " " & [StreetAddress] & ", " & _
[City] & " " & [MainSwitchBoardPhone]
Try:
result = String.Format("{0} {1}, {2} (###) ###-####" _
, [ClinicHospital] _
, [StreetAddress] _
, [City] _
, Convert.ToInt64([MainSwitchBoardPhone]) _
)
Edit: Added Convert.ToInt64
as follows:
result = [ClinicHospital] & " " & [StreetAddress] & ", " & _
[City] & " " & Format([MainSwitchBoardPhone],"(###) ###-####")