Error on MS Access Query - sql

I am having an issue with a query on Microsoft Access 2007. I've developed query which runs correctly when I run it from the query editor of Access. My problem is that I have put this very same query inside a string literal in a VBA code of a Report, on the event On Open' handler. My purpose is to assign this query to the property RecordSource of that Report, allowing the Report to be created dynamically with whatever query I want.
The issue arises when I actually open and run the Report. When the handler for the event Open finishes its execution I get the error: you tried to execute a query that does not include the specified expression "ID" as part of an aggregate function.
Here is the query (inside the VBA code for the open event handler).
Private Sub Report_Open(Cancel As Integer)
Dim Query As String
Dim WhereClause As String
WhereClause = [Forms]![Main Form]!
[WindowPrintOptions]![CustomizedReport]![txtResponsibility]
Query = "SELECT AllInfo.*
FROM (SELECT i.ID,
i.[Number],
i.Responsability.Value AS Responsability
FROM tbl_Projects AS p RIGHT JOIN
((tb_Items AS i LEFT JOIN tb_F_projects AS fp
ON i.ProjectID = fp.Id) LEFT JOIN
tb_items_comments AS ic ON ic.ItemID = i.ID)
ON i.ProjectID = p.Id WHERE ( (i.Status = 'Status 1')
AND (i.DateOpened >= #9/9/2014#) AND
(i.DateOpened <= #9/11/2014#) AND
(i.DueDate >= #9/12/2014#) AND (i.DueDate <= #9/12/2014#)
AND (i.Category = 'C1') AND (i.Deliverables LIKE '*'
& 'dates' & '*') AND (i.Responsability.Value = 'Some name')
) ) AS AllInfo"
Me.RecordSource = Query
End Sub
Note that I don't use 'WhereClause' yet. It will be inserted afterwards into the query. I just removed it for the purpose of testing the query alone, and check if it was ok without any change and found it actually wasn't. So, just remembering: this very same query does work when I run it from MS Access query builder, but not here, dynamically. What may be the problem?

Related

Complex JOINS in Access SQL difficult to convert to JET OLEDB

I'm a long time follower of Stack overflow but this is my first post. I'm hoping the community can help.
I have a successful Access Query that returns the required results - Perfect!
HOWEVER, I'm trying to return the same using OLEDB connection to the database within an ASP script. This is all legacy stuff however we are allowing web access to this legacy information.
MS Access (2016) shows Query as this... (works)
SELECT [EventName] & ": " & [RoundCaption] AS RoundTitle, ChunkEntryTable.WinPos
FROM ((EventTable INNER JOIN EventRoundTable ON EventTable.EventId = EventRoundTable.EventId) INNER JOIN ((RoundHeatTable INNER JOIN ChunkTable ON RoundHeatTable.RoundHeatId = ChunkTable.RoundHeatId) INNER JOIN (EventEntryTable INNER JOIN ChunkEntryTable ON EventEntryTable.EventEntryId = ChunkEntryTable.EventEntryId) ON ChunkTable.ChunkId = ChunkEntryTable.ChunkId) ON EventRoundTable.RoundKeyId = RoundHeatTable.RoundKeyId) LEFT JOIN EventEntryMemberTable ON EventEntryTable.EventEntryId = EventEntryMemberTable.EventEntryId
WHERE (((EventEntryTable.Entry1Id)=[EntryId])) OR (((EventEntryTable.Entry2Id)=[EntryId])) OR (((EventEntryTable.Entry3Id)=[EntryId])) OR (((EventEntryMemberTable.MemberId)=[EntryId]))
ORDER BY EventTable.SortIdx, EventRoundTable.RoundId DESC , EventRoundTable.IsRepechage DESC;
Doing this in OLEDB. Connection string as follows...
<%
' FileName="Connection_ado_conn_string.htm"
' Type="ADO"
' DesigntimeType="ADO"
' HTTP="true"
' Catalog=""
' Schema=""
Dim MM_csresultdb_STRING
MM_csresultdb_STRING = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=xyz.mde;Jet OLEDB:Database Password=xxxxxxxxx;"
%>
Connection works perfectly but I can't seem to get the SQL command to work. I get "No value given for one or more required parameters".
NOTE: I have replaced [EntryID] in 4 places with a valid value and it works perfectly in Access just not outside of Access using OLEDB. Here's what the SQL is I'm using...
SELECT EventTable.EventName & ": " & EventRoundTable.RoundCaption AS RoundTitle, ChunkEntryTable.WinPos FROM
((EventTable INNER JOIN EventRoundTable ON EventTable.EventId = EventRoundTable.EventId) INNER JOIN
((RoundHeatTable INNER JOIN ChunkTable ON RoundHeatTable.RoundHeatId = ChunkTable.RoundHeatId) INNER JOIN
(EventEntryTable INNER JOIN ChunkEntryTable ON EventEntryTable.EventEntryId = ChunkEntryTable.EventEntryId) ON ChunkTable.ChunkId = ChunkEntryTable.ChunkId) ON ChunkTable.ChunkId = ChunkEntryTable.ChunkId)
ON EventRoundTable.RoundKeyId = RoundHeatTable.RoundKeyId)
WHERE ((EventEntryTable.Entry1Id)=4741) OR ((EventEntryTable.Entry2Id)=4741) OR ((EventEntryTable.Entry3Id)=4741)
ORDER BY EventTable.SortIdx, EventRoundTable.RoundId DESC , EventRoundTable.IsRepechage DESC;
FOUND PROBLEM ** See answer below
FOUND PROBLEM ** It's to do with this part of the SQL...
[EventName] & ": " & [RoundCaption] AS RoundTitle
Changed to
[EventName], [RoundCaption] AS RoundTitle
and it works but gives me two separate fields rather than the one concatenated field called "RoundTitle". So I'll join the two result fields during the display output rather than at the query stage.
Whew! That many days to figure out. Thanks to the comments that kinda steered me in that direction of the AS part of the statement.

MS Access using forms in a pass-through query

I have a form named FietsAantDagen, a query named QueryFietsAantDagen and a textbox named Txtinput. I am trying to use a pass-through query to SQL Server and use a text form's input as a input in my query.
Query:
SELECT
Fiets_id,
Fiets_Type,
SUM(DATEDIFF(DAY, Huurovereenkomst_Begin_datum, Huurovereenkomst_Eind_datum)) AS AantalDagen
FROM
Fiets
INNER JOIN
HuurovereenkomstFiets
ON HuurovereenkomstFiets_Fiets_id = Fiets_id
INNER JOIN
Huurovereenkomst
ON Huurovereenkomst_id = HuurovereenkomstFiets_Huurovereenkomst_id
WHERE
YEAR(Huurovereenkomst_Begin_datum) = [Forms]![FietsAantDagen]![Txtinput]
AND YEAR(Huurovereenkomst_Eind_datum) = [Forms]![FietsAantDagen]![Txtinput]
GROUP BY
Fiets_id,
Fiets_Type
While running this query as a pass-through query I get the following error:
ODBC: Runtime error [Microsoft][SQL Server Native Client 11.0][SQL
Server]Incorrect syntax near the keyword 'WHERE'/ (#156)
Is the problem that I am using an Access text form value in a pass-through query, if so what can I do to solve it?
I read in another Overflow question you needed to add (), which I did and now I get the error:
JOIN-expression is not supported.
I'm going crazy...
If you don’t have direct use of SQL server, then likely best to create two pass though queries.
Query #1 – this is your raw SQL as you have
Eg:
SELECT
Fiets_id,
Fiets_Type,
SUM(DATEDIFF(DAY, Huurovereenkomst_Begin_datum,
Huurovereenkomst_Eind_datum)) AS AantalDagen
FROM
Fiets
INNER JOIN
HuurovereenkomstFiets
ON HuurovereenkomstFiets_Fiets_id = Fiets_id
INNER JOIN
Huurovereenkomst
ON Huurovereenkomst_id = HuurovereenkomstFiets_Huurovereenkomst_id
WHERE
YEAR(Huurovereenkomst_Begin_datum) = [StartYear]
AND YEAR(Huurovereenkomst_Eind_datum) = [EndYear]
GROUP BY
Fiets_id,
Fiets_Type
Query #2 – this is an application wide query you make that you can re-use over and over for any raw t-SQL (SQL server pass though). You then in code go like this:
Dim rst As DAO.Recordset
Dim strSQL As String
strSQL = CurrentDb.QueryDefs("MyQ1").SQL
srtSQL = Replace(strSQL, "[YearStart]", [Forms]![FietsAantDagen]![Txtinput])
strSQL = Replace(strSQL, "[YearEnd]", [Forms]![FietsAantDagen]![Txtinput])
With CurrentDb.QueryDefs("qryPassR")
.SQL = strSQL
.ReturnsRecords = True
Set rst = .OpenRecordset
End With
However, if you have the ability to use SQL server, and create a proc, then I would suggest you create store procedure like this:
CREATE PROCEDURE SelectDates
#StartYear int,
#EndYear int
AS
BEGIN
SET NOCOUNT ON;
SELECT
Fiets_id,
Fiets_Type,
SUM(DATEDIFF(DAY, Huurovereenkomst_Begin_datum, Huurovereenkomst_Eind_datum)) AS AantalDagen
FROM
Fiets
INNER JOIN
HuurovereenkomstFiets
ON HuurovereenkomstFiets_Fiets_id = Fiets_id
INNER JOIN
Huurovereenkomst
ON Huurovereenkomst_id = HuurovereenkomstFiets_Huurovereenkomst_id
WHERE
YEAR(Huurovereenkomst_Begin_datum) = #StartYear
AND YEAR(Huurovereenkomst_Eind_datum) = #EndYear
GROUP BY
Fiets_id,
Fiets_Type
END
Then in access, you use this:
Dim rst As DAO.Recordset
With CurrentDb.QueryDefs("qryPassR")
.SQL = "exec SelectDates " & [Forms]![FietsAantDagen]![Txtinput] & "," & _
[Forms]![FietsAantDagen]![Txtinput]
.ReturnsRecords = True
Set rst = .OpenRecordset
End With
So by passing parameters you reduce most of issues in regards to SQL injection.
Of course if you can’t create store procs, or don’t have permissions, then you have to adopt the first idea above. You can also of course in the first suggestion insert the raw SQL into the code editor, but I find using up an extra query to “just” hold the raw SQL, and then modifying the SQL into the 2nd pass-through query eliminates the need for messy SQL in the VBA code editor.
When you run a Pass-Through query, its SQL text gets sent to the DB server as-is, nothing is evaluated. So including [Forms]![FietsAantDagen]![Txtinput] in a Pass-Through query will never work.
You're on the right track with
SELECT * FROM fnFietsAantDagenPerJaar([Forms]![FietsAantDagen]![Txtinput])‌​
but you need to supply the parameter yourself, because (see above).
So you need to build the Pass-Through SQL, e.g. with this VBA procedure:
Private Sub txtInput_AfterUpdate()
Dim QD As DAO.QueryDef
Dim lYear As Long
' Make sure we pass a number to the SQL Server function
lYear = Val(Me!txtInput)
If lYear > 0 Then
Set QD = CurrentDb.QueryDefs("QueryFietsAantDagen")
QD.SQL = "SELECT * FROM fnFietsAantDagenPerJaar(" & lYear & ")"
Set QD = Nothing
' After changing the query SQL, requery the form
' This assumes that your form is bound to Pass-Through query QueryFietsAantDagen
Me.Requery
End If
End Sub
Pass-through queries run exclusively on the connected, external database engine, here being SQL Server, and does not see anything in MS Access, only everything in that external environment.
Consider adjusting pass-through query to avoid any MS Access evaluations and add year groupings to aggregate query. Then query this resultset in a local Access query filtering for needed year conditions using form values. Below adds table aliases for clarity (adjust if not correct).
Pass-Through (no WHERE clause, but extended SELECT and GROUP BY)
SELECT
f.Fiets_id,
f.Fiets_Type,
YEAR(h.Huurovereenkomst_Begin_datum) As BeginYear,
YEAR(h.Huurovereenkomst_Eind_datum) As EndYear,
SUM(DATEDIFF('d', h.Huurovereenkomst_Begin_datum,
h.Huurovereenkomst_Eind_datum)) AS AantalDagen
FROM
HuurovereenkomstFiets_LinkTable hf
INNER JOIN
Fiets_LinkTable f
ON hf.HuurovereenkomstFiets_Fiets_id = f.Fiets_id
INNER JOIN
Huurovereenkomst_LinkTable h
ON h.Huurovereenkomst_id = hf.HuurovereenkomstFiets_Huurovereenkomst_id
GROUP BY
f.Fiets_id,
f.Fiets_Type,
YEAR(h.Huurovereenkomst_Begin_datum),
YEAR(h.Huurovereenkomst_Eind_datum)
Local Query
SELECT
t.Fiets_id,
t.Fiets_Type,
t.AantalDagen
FROM
myPassThroughQuery t
WHERE t.BeginYear = [Forms]![FietsAantDagen]![Txtinput]
AND t.EndYear = [Forms]![FietsAantDagen]![Txtinput]
Alternatively, consider using linked tables from SQL Server (with same ODBC connection as pass-through) where Access can treat them as local tables. Hence, you can run your query using form date values. Do note you will have to convert syntax to adhere to Access' SQL dialect like DATEDIFF and JOIN parentheses. Performance may differ due to changed engines but test.
Linked Tables Local Query
SELECT
f.Fiets_id,
f.Fiets_Type,
SUM(DATEDIFF('d', h.Huurovereenkomst_Begin_datum,
h.Huurovereenkomst_Eind_datum)) AS AantalDagen
FROM
(HuurovereenkomstFiets_LinkTable hf
INNER JOIN
Fiets_LinkTable f
ON hf.HuurovereenkomstFiets_Fiets_id = f.Fiets_id)
INNER JOIN
Huurovereenkomst_LinkTable h
ON h.Huurovereenkomst_id = hf.HuurovereenkomstFiets_Huurovereenkomst_id
WHERE YEAR(h.Huurovereenkomst_Begin_datum) = [Forms]![FietsAantDagen]![Txtinput]
AND YEAR(h.Huurovereenkomst_Eind_datum) = [Forms]![FietsAantDagen]![Txtinput]
GROUP BY
f.Fiets_id,
f.Fiets_Type
To create linked tables automatically, use DoCmd.TransferDatabase. Otherwise, use the External Data / ODBC Database icon on ribbon and walk through setup wizard.
DoCmd.TransferDatabase acLink, "ODBC Database", _
"ODBC;DRIVER={SQL Server};Server=<ServerAddress>;Database=<DBname>;Trusted_Connection=Yes;", _
acTable, "HuurovereenkomstFiets", "HuurovereenkomstFiets_LinkedTable"

Run SQL Update Query in MS Access VBA

I am trying to run this code to fire an update query from VBA. Access is giving me a syntax error. I suspect this has to do with the fact that I'm trying to run an update query using an INNER JOIN with a form. Is what I'm trying to do at all possible?
Private Sub Btn_Edit_Data_Click()
Dim db As DAO.Database
Dim UpdateQdf As DAO.QueryDef
Dim UpdateSQL As String
Set db = CurrentDb()
Set UpdateQdf = db.QueryDefs("Qry_Update_Counterparty_Data")
UpdateSQL = "UPDATE Repository_Redux INNER JOIN [Forms]![Frm_Reject_Button] ON Repository_Redux.[Counterparty ID] = [Forms]![Frm_Reject_Button]![Txt_CP_ID] " & _
"SET Repository_Redux.[Counterparty Name] = [Forms]![Frm_Reject_Button]![Txt_CP_Name_Edit]"
UpdateQdf.SQL = UpdateSQL
DoCmd.OpenQuery "Qry_Update_Counterparty_Data"
Set db = Nothing
Set qdf = Nothing
End Sub
I solved it this way, thanks everyone:
UpdateSQL = "UPDATE Repository_Redux SET Repository_Redux.[Counterparty Name] = [Forms]![Frm_Reject_Button]![Txt_CP_Name_Edit] WHERE Repository_Redux.[Counterparty ID] = [Forms]![Frm_Reject_Button]![Txt_CP_ID]"
Just a suggestion, I've not tried this...
On your form you have have an event handler that stores in a global variable (yes, I know that's dodgy) the values from your form that you intend to use in the query. Then you can define a function that reads the global variable. Then you can use the function in the SQL query.
Let us know how you get on.
Googling suggests other have tried this
Global Variable as query parameter - PC Review
How to put global variable name in query
Anybody else got a better "global state machine" to bridge the form to the SQL?
No, you can never join a form in a query (or SELECT FROM a form, for that matter). You can only join in tables or other queries.
You can, however, try to join in a forms record source.

VBA / Visual Basic. Simple String SQL

I'm creating a Voting System. so it's like this every time A Button1 is pressed + 1 or it will increase the vote in the Access database. I can't find anything in Google.
trx = "update [Table1] SET [Vote] = Vote + 1, (WHERE ID = 1)"
Don't include a comma before the WHERE clause. Also you don't need to put the WHERE clause inside parentheses.
Test this as a new query in the Access query designer.
update [Table1] SET [Vote] = Vote + 1 WHERE ID = 1
Fine tune as needed. And once you have it working in the query designer, adapt your VBA code to use that working statement.
Remove comma before Where and brackets around where clause
trx = "update [Table1] SET [Vote] = Vote + 1 WHERE ID = 1"

access 2010 docmd.runSQL

I am using ACCESS 2010 and trying to run a simple command in one of my form buttons btnRemove_Click() and for some reason it always returns an error "Run-Time error '2342' A RunSQL action requires an argument consisting of an SQL statement"
my code is here...
Private Sub btnRemove_Click()
Dim srtSQL As String
StrSQL = "SELECT TblProduct.Product
, TblItem.Product_ID
, TblOrder.OrderID
FROM TblProduct
INNER JOIN (TblOrder
INNER JOIN TblItem
ON TblOrder.OrderID = TblItem.OrderID)
ON TblProduct.ProductID = TblItem.Product_ID
WHERE (((TblOrder.OrderID)=3));"
DoCmd.RunSQL StrSQL
Text62.SetFocus
Text62.Text = StrSQL
End Sub
the reason I want to run the DoCmd.RunSQL command as string is that later I will remove the (TblOrder.OrderID)=3 by a field in my form and I can see many people using this command normally in there videos in YouTube and tutorials, but seriously I have no idea why does not work.
Might be a bit late on this one. But the problem is DoCmd.RunSQL is for running Updates/Delete type SQL and not SELECT. You need to Open a Recordset to "use" the Data returned.