Access 2003: count(*) produces syntax error - sql

I am using ms-access and for some reason, the code here produces a Syntax error which I dont understand.
UPDATE Korrekturentlastung
SET Schueler = SELECT COUNT(*)
FROM Korrekturentlastung
WHERE
Korrekturentlastung_Kurs.Kuerzel = Korrekturentlastung.Kuerzel
AND Korrekturentlastung_Kurs.Klasse = Korrekturentlastung.Klasse
AND Korrekturentlastung_Kurs.Fach = Korrekturentlastung.Fach
AND Korrekturentlastung_Kurs.Kursart = Korrekturentlastung.Kursart
The error is:
Syntax error. in query expression 'SELECT COUNT(*)
FROM Korrekturentlastung'

Whilst #Gordon Linoff has correctly identified the syntax error in your query, if you were to run the query in MS Access, you'll likely receive the familiar response:
Operation must use an updateable query.
This arises as a result of a restriction of the JET database engined used by MS Access whereby no part of an update query can use aggregation. In your case, this arises as a result of the use of count(*).
One possible alternative is to use the DCount domain aggregate function, which is evaluated separately from the evaluation of the main query and therefore retains the "updateability" of the query.
update korrekturentlastung
set schueler =
dcount
(
"*",
"Korrekturentlastung",
"Kuerzel = " & Korrekturentlastung.Kuerzel & " and "
"Klasse = " & Korrekturentlastung.Klasse & " and "
"Fach = " & Korrekturentlastung.Fach & " and "
"Kursart = " & Korrekturentlastung.Kursart
)
Note that if your fields are text fields, you'll also need to surround the above values with single or double quotes, e.g.:
update korrekturentlastung
set schueler =
dcount
(
"*",
"Korrekturentlastung",
"Kuerzel = '" & Korrekturentlastung.Kuerzel & "' and "
"Klasse = '" & Korrekturentlastung.Klasse & "' and "
"Fach = '" & Korrekturentlastung.Fach & "' and "
"Kursart = '" & Korrekturentlastung.Kursart & "'"
)

Subqueries need their own parentheses:
UPDATE Korrekturentlastung
SET Schueler = (SELECT COUNT(*)
FROM Korrekturentlastung
WHERE Korrekturentlastung_Kurs.Kuerzel = Korrekturentlastung.Kuerzel
AND Korrekturentlastung_Kurs.Klasse = Korrekturentlastung.Klasse
AND Korrekturentlastung_Kurs.Fach = Korrekturentlastung.Fach
AND Korrekturentlastung_Kurs.Kursart = Korrekturentlastung.Kursart
);

Related

Syntax error (missing operator) in query expression - VBA

This is my code:
M_BKID = DMax("BK_ID", "BookingMain")
FSQL = " UPDATE Q_HrsToBeRefund_Writeable " & _
" SET BD_ToBeRefund = False, BD_Refunded = True, BD_RefundedRef = " & M_BKID & " " & _
" ORDER BY BD_Dt DESC LIMIT " & M_Refunded & " "
Debug.Print FSQL ' ********************************
DoCmd.RunSQL FSQL
I get an error
Syntax error (missing operator) in query expression '184 ORDER BY BD_Dt DESC Limit 3
Can anyone help me solve this?
MS Access definitely doesn't support LIMIT in UPDATE. I don't think it supports TOP either. But you can do:
UPDATE Q_HrsToBeRefund_Writeable as
SET BD_ToBeRefund = False,
BD_Refunded = True,
BD_RefundedRef = ?
WHERE <primary key> IN (SELECT TOP (M_Refunded) <primary key>
FROM Q_HrsToBeRefund_Writeable
ORDER BY BD_Dt DESC
);
Note:
This assumes your table has a primary key.
Note the use of ?. That is an indication that you should use a parameter for this value, rather than munging the query string.
I'm not sure if the number of rows can be passed in as a parameter.

VBA bad syntax in dlookup function with global variables

I am using 8 similar functions in my code and they all work, but this one is not working:
global_var_13=DLookup("[amount]", "[tabla amortizacion real]","[no contract]= get_global('global_var_10') and [ident]=get_global('global_var_11') and [cuota]= get_global('global_var_12')")
var_10 is a string, var_11, var_12, and var_13 are numeric.
The values are var_10= "GAF-27/2013", var_11=1, var_12=1
global_var_13 is returning NULL
Any thoughts about the syntax?
Try to concatenate the clause elements:
global_var_13 = DLookup("[amount]", "[tabla amortizacion real]", "[no contract] = '" & get_global("global_var_10") & "' and [ident] = " & get_global("global_var_11") & " and [cuota] = " & get_global("global_var_12") & "")

Query database and check not equal to

I have a data set in excel that I am querying info in a database using that data set. However, when checking against the database I get the "too few parameters. Expected 1" error.
Query:
Set rex = db.OpenRecordset("SELECT * FROM [CallQuality] WHERE ([Racf] = '" & sRacf & "') AND ([DateChecked] = #" & sDateChecked & "#) AND ([Overall] <> '" & sOverall & "') ;")
Literal:
SELECT * FROM [CallQuality] WHERE ([Racf] = 'SMITHJ') AND ([DateChecked] = #2017/05/17#) AND ([Overall] <> 'Development Required') ;
I have tried without the brackets and using != instead of <>. I am sure it is something simple I am missing.
Edit:
Error in this section:
Set rex = db.OpenRecordset("SELECT * FROM [CallQuality] WHERE ([Overall] <> '" & sOverall & "')")
Edit2:
The field name was wrong. Sorry guys! Not sure why it didnt give me the name error when it didnt find the field.
Thank you for your help.
use a + instead of & in the query.
So use this:
Set rex = db.OpenRecordset("SELECT * FROM [CallQuality] WHERE ([Racf] = '" + sRacf + "') AND ([DateChecked] = #" + sDateChecked + "#) AND ([Overall] <> '" + sOverall + "') ;");
If you look in the Error List you should get:
Error CS0019 Operator '&' cannot be applied to operands of type
'string' and 'string'
I can see why you put the & instead. Simple mistake :-)
It was an issue with the field name in the query.

Not match the datatypes of the criteria expression ms access

I have a update like this in a module of ms access:
sql = "ALTER TABLE Carrera "
sql = sql & "ADD COLUMN carrera_nombre TEXT(25);"
Application.CurrentDb.Execute (sql)
sql = "UPDATE Carrera "
sql = sql & "SET Carrera.[carrera_nombre] = '" & strFunction(Carrera.[NombreCarrera]) & "' "
sql = sql & "WHERE Carrera.[CarreraId] > 1000;"
Application.CurrentDb.Execute (sql)
In database the column NombreCarrera exist, and I declared the function:
Function strFunction(str) As String
strFunction = str & "test"
End Function
But I get the error 3464 Not match the datatypes of the criteria expression, and I don't understand why, the strFunction return a String and the carrera_nombre and CarreraNombre columns type is TEXT.
EDIT: If I check string sql through MsgBox(sql) y get the right query: UPDATE Carrera SET Carrera.[carrera_nombre] = 'mathtest' WHERE Carrera.[CarreraId] > 1000;
I believe since you declare the sql command as a string, you will have to get it first.
so one of your code
sql = sql & "SET Carrera.[carrera_nombre] = strFunction(Carrera.[NombreCarrera])"
Should become
sql = sql & "SET Carrera.[carrera_nombre] = " & strFunction(Carrera.[NombreCarrera]) & """

Query will not run with variables, will work when variable's definitions are pasted in

This is a Query in VBA (Access 2007)
I have 3 strings defined:
str_a = "db.col1 = 5"
str_b = " and db.col2 = 123"
str_c = " and db.col3 = 42"
Then I use these in the WHERE part of my Query:
"WHERE '" & str_a & "' '" & str_b & "' '" & str_c & "' ;"
This fails, but If I paste in the strings like this:
"WHERE db.col1 = 5 and db.col2 = 123 and db.col3 = 42;"
It works perfectly. I'm guessing the syntax is wrong when using multiple variables in a string.
Anyone have any hints?
"WHERE '" & str_a & "' '" & str_b & "' '" & str_c & "' ;"
will include single quotes within your completed WHERE clause. And the working version you showed us has none:
"WHERE db.col1 = 5 and db.col2 = 123 and db.col3 = 42;"
So, try constructing the WHERE clause with no single quotes:
"WHERE " & str_a & " " & str_b & " " & str_c & ";"
For debugging purposes, it's useful to view the final string after VBA has finished constructing it. If you're storing the string in a variable named strSQL, you can use:
Debug.Print strSQL
to display the finished string in the Immediate Window of the VB Editor. (You can get to the Immediate Window with the CTRL+g keyboard shortcut.)
Alternatively, you could display the finished string in a message box window:
MsgBox strSQL
You've got some extra single quotes in there.
Try this:
"WHERE " & str_a & str_b & str_c
Note: In general, you shouldn't build query strings by concatenating strings, because this leaves you vulnerable to SQL injection, and mishandles special characters. A better solution is to use prepared statements. But assuming you're operating in a very controlled environment the solution I gave should work.
Quick tip about troubleshooting SQL that is built dynamically: echo the SQL string resulting from all the concatenation and interpolation, instead of staring at your code.
WHERE 'db.col1 = 5' ' and db.col2 = 123' ' and db.col3 = 42';
Nine times out of ten, the problem becomes a lot more clear.
For VB6/VBA dynamic SQL, I always find it more readable to create an SQL template, and then use the Replace() function to add in the dynamic parts. Try this out:
Dim sql As String
Dim condition1 As String
Dim condition2 As String
Dim condition3 As String
sql = "SELECT db.col1, db.col2, db.col3 FROM db WHERE <condition1> AND <condition2> AND <condition3>;"
condition1 = "db.col1 = 5"
condition2 = "db.col2 = 123"
condition3 = "db.col3 = 'ABCXYZ'"
sql = Replace(sql, "<condition1>", condition1)
sql = Replace(sql, "<condition2>", condition2)
sql = Replace(sql, "<condition3>", condition3)
However, in this case, the values in the WHERE clause would change, not the fields themselves, so you could rewrite this as:
Dim sql As String
sql = "SELECT col1, col2, col3 FROM db "
sql = sql & "WHERE col1 = <condition1> AND col2 = <condition2> AND col3 = '<condition3>';"
sql = Replace(sql, "<condition1>", txtCol1.Text)
sql = Replace(sql, "<condition2>", txtCol2.Text)
sql = Replace(sql, "<condition3>", txtCol3.Text)
Some comments on constructing WHERE clauses in VBA.
Your example is by definition going to be incorrect, because you're putting single quotes where they aren't needed. This:
str_a = "db.col1 = 5"
str_b = " and db.col2 = 123"
str_c = " and db.col3 = 42"
"WHERE '" & str_a & "' '" & str_b & "' '" & str_c & "' ;"
...will produce this result:
WHERE 'db.col1 = 5' ' and db.col2 = 123' ' and db.col3 = 42' ;
This is obviously not going to work.
Take the single quotes out and it should work.
Now, that said, I'd never do it that way. I'd never put the AND in the substrings that are used to construct the WHERE clause, because what would I do if I have a value for the second string but not for the first?
When you have to concatenate a number of strings with a delimiter and some can be unassigned, one thing to do is to just concatenate them all and not worry if the string before the concatenation is unassigned of not:
str_a = "db.col1 = 5"
str_b = "db.col2 = 123"
str_c = "db.col3 = 42"
To concatenate that, you'd do:
If Len(str_a) > 0 Then
strWhere = strWhere & " AND " str_a
End If
If Len(str_b) > 0 Then
strWhere = strWhere & " AND " str_b
End If
If Len(str_c) > 0 Then
strWhere = strWhere & " AND " str_c
End If
When all three strings are assigned, that would give you:
" AND db.col1 = 5 AND db.col2 = 123 AND db.col3 = 42"
Just use Mid() to chop of the first 5 characters and it will always come out correct, regardless of which of the variables have values assigned:
strWhere = Mid(strWhere, 6)
If none of them are assigned, you'll get a zero-length string, which is what you want. If any one of them is assigned, you'll first get " AND ...", which is an erroneous leading operator, which you just chop out with the Mid() command. This works because you know that all the results before the Mid() will start with " AND " no matter what -- no needless tests for whether or not strWhere already has been assigned a value -- just stick the AND in there and chop it off at the end.
On another note, someone mentioned SQL injection. In regards to Access, there was a lengthy discussion of that which considers a lot of issues close to this thread:
Non-Web SQL Injection
I have my favorite "addANDclause" function, with the following parameters:
public addANDclause( _
m_originalQuery as string, _
m_newClause as string) _
as string
if m_originalQuery doe not contains the WHERE keyword then addANDClause() will return the original query with a " WHERE " added to it.
if m_orginalQuery already contains the WHERE keyword then addANDClause() will return the original query with a " AND " added to it.
So I can add as many "AND" clauses as possible. With your example, I would write the following to create my SQL query on the fly:
m_SQLquery = "SELECT db.* FROM db"
m_SQLquery = addANDClause(m_SQLQuery, "db.col1 = 5")
m_SQLQuery = addANDClause(m_SQLQuery, "db.col2 = 123")
m_SQLQuery = addANDClause(m_SQLQuery, "db.col3 = 42")
Of course, instead of these fixed values, such a function can pick up values available in bound or unbound form controls to build recordset filters on the fly. It is also possible to send parameters such as:
m_SQLQuery = addANDClause(m_SQLQuery, "db.text1 like 'abc*'")
While dynamic SQL can be more efficient for the engine, some of the comments here seem to endorse my view that dynamic SQL can be confusing to the human reader, especially when they didn't write the code (think of the person who will inherit your code).
I prefer static SQL in a PROCEDURE and make the call to the proc dynamic at runtime by choosing appropriate values; if you use SQL DDL (example below) to define the proc you can specify DEFAULT values (e.g. NULL) for the parameters so the caller can simply omit the ones that are not needed e.g. see if you can follow the logic in this proc:
CREATE PROCEDURE MyProc
(
arg_col1 INTEGER = NULL,
arg_col2 INTEGER = NULL,
arg_col3 INTEGER = NULL
)
AS
SELECT col1, col2, col3
FROM db
WHERE col1 = IIF(arg_col1 IS NULL, col1, arg_col1)
AND col2 = IIF(arg_col2 IS NULL, col2, arg_col2)
AND col3 = IIF(arg_col3 IS NULL, col3, arg_col3);
Sure, it may not yield the best execution plan but IMO you have to balance optimization against good design principles (and it runs really quick on my machine :)