views:

4523

answers:

5

How can I UPDATE a field of a table with the result of a SELECT query in Microsoft Access 2007.

Here's the Select Query:

SELECT Min(TAX.Tax_Code) AS MinOfTax_Code
FROM TAX, FUNCTIONS

WHERE (((FUNCTIONS.Func_Pure)<=[Tax_ToPrice]) AND ((FUNCTIONS.Func_Year)=[Tax_Year]))

GROUP BY FUNCTIONS.Func_ID;

And here's the Update Query:

UPDATE FUNCTIONS

 SET FUNCTIONS.Func_TaxRef = [Result of Select query]
A: 

If you are trying to do something special 90% it's a hack.
Just think if it makes sense.
I'm hoping that your database is normalized.
Take a look at this question.

the_drow
Hack? ;)It's just a University project.
mammadalius
the Link was not helpful
mammadalius
Where you given the database structure beforehand?If not then Google database normalization.
the_drow
Here's the Database Scheme http://i44.tinypic.com/35l6hoj.jpg
mammadalius
A: 

Does this work? Untested but should get the point across.

UPDATE FUNCTIONS
SET Func_TaxRef = 
(
  SELECT Min(TAX.Tax_Code) AS MinOfTax_Code
  FROM TAX, FUNCTIONS F1
  WHERE F1.Func_Pure <= [Tax_ToPrice]
    AND F1.Func_Year=[Tax_Year]
    AND F1.Func_ID = FUNCTIONS.Func_ID
  GROUP BY F1.Func_ID;
)

Basically for each row in FUNCTIONS, the subquery determines the minimum current tax code and sets FUNCTIONS.Func_TaxRef to that value. This is assuming that FUNCTIONS.Func_ID is a Primary or Unique key.

beach
Access saysL: "Operations must use an Updateable query."
mammadalius
@mammadalius Added TAKE 2. See if that makes a difference.
beach
Access Says: "Syntax Error"
mammadalius
A google search says that "Operations must use an Updateable query." could be related to "write permissions on the database and/or folder containing the database." Are you sure the database is not read-only? Check the access file to verify it is not readonly? I'll remove TAKE 2 because of the syntax error.
beach
Permissions are ok and other updates work well.
mammadalius
Does the following work? Basically have to narrow it down to see where it is breaking.UPDATE FUNCTIONSSET Func_TaxRef = ( SELECT 1)
beach
No, it's what I myself tried first and get no result.Here's the Database Scheme http://i44.tinypic.com/35l6hoj.jpg
mammadalius
The ACE/Jet engine simply does not support this syntax. It has its own, proprietary UPDATE..JOIN syntax. The error "Operations must use an Updateable query" is kind of generic, meaning, "I can't do this."
onedaywhen
A: 

See the answer to the question "MySQL/SQL: Update with correlated subquery from the updated table itself", maybe it will help.

Roee Adler
I also get "Syntax Error" with this.UPDATE FUNCTIONS AS fncINNER JOIN{SELECT Min(TAX.Tax_Code) AS MinOfTax_CodeFROM TAX, FUNCTIONSWHERE (((FUNCTIONS.Func_Pure)<=[Tax_ToPrice]) AND ((FUNCTIONS.Func_Year)=[Tax_Year]))GROUP BY FUNCTIONS.Func_ID}ON fnc.Func_Pure = TAX.Tax_ToPriceSET fnc.Func_Tax_Ref = TAX. MinOfTax_Code
mammadalius
+2  A: 

I wrote about some of the limitations of correlated subqueries in Access/JET SQL a while back, and noted the syntax for joining multiple tables for SQL UPDATEs. Based on that info and some quick testing, I don't believe there's any way to do what you want with Access/JET in a single SQL UPDATE statement. If you could, the statement would read something like this:

UPDATE FUNCTIONS A
INNER JOIN (
  SELECT AA.Func_ID, Min(BB.Tax_Code) AS MinOfTax_Code
  FROM TAX BB, FUNCTIONS AA
  WHERE AA.Func_Pure<=BB.Tax_ToPrice AND AA.Func_Year= BB.Tax_Year
  GROUP BY AA.Func_ID
) B 
ON B.Func_ID = A.Func_ID
SET A.Func_TaxRef = B.MinOfTax_Code

Alternatively, Access/JET will sometimes let you get away with saving a subquery as a separate query and then joining it in the UPDATE statement in a more traditional way. So, for instance, if we saved the SELECT subquery above as a separate query named FUNCTIONS_TAX, then the UPDATE statement would be:

UPDATE FUNCTIONS
INNER JOIN FUNCTIONS_TAX
ON FUNCTIONS.Func_ID = FUNCTIONS_TAX.Func_ID
SET FUNCTIONS.Func_TaxRef = FUNCTIONS_TAX.MinOfTax_Code

However, this still doesn't work.

I believe the only way you will make this work is to move the selection and aggregation of the minimum Tax_Code value out-of-band. You could do this with a VBA function, or more easily using the Access DLookup function. Save the GROUP BY subquery above to a separate query named FUNCTIONS_TAX and rewrite the UPDATE statement as:

UPDATE FUNCTIONS
SET Func_TaxRef = DLookup(
  "MinOfTax_Code", 
  "FUNCTIONS_TAX", 
  "Func_ID = '" & Func_ID & "'"
)

Note that the DLookup function prevents this query from being used outside of Access, for instance via JET OLEDB. Also, the performance of this approach can be pretty terrible depending on how many rows you're targeting, as the subquery is being executed for each FUNCTIONS row (because, of course, it is no longer correlated, which is the whole point in order for it to work).

Good luck!

ewbi
+1 Nice, DLookup(), even tough it will be slow for big tables. Btw it seems Access UPDATE does not allow a join on a query, but it does allow a join on a table (see my post.) Access = Weird
Andomar
@ewbi: you may be interested in this KB article, Update Query Based on Totals Query Fails (http://support.microsoft.com/kb/116142).
onedaywhen
@onedaywhen: thanks!
ewbi
A: 

Well, it looks like Access can't do aggregates in UPDATE queries. But it can do aggregates in SELECT queries. So create a query with a definition like:

SELECT func_id, min(tax_code) as MinOfTax_Code
FROM Functions
INNER JOIN Tax 
ON (Functions.Func_Year = Tax.Tax_Year) 
AND (Functions.Func_Pure <= Tax.Tax_ToPrice) 
GROUP BY Func_Id

And save it as YourQuery. Now we have to work around another Access restriction. UPDATE queries can't operate on queries, but they can operate on multiple tables. So let's turn the query into a table with a Make Table query:

SELECT YourQuery.* 
INTO MinOfTax_Code
FROM YourQuery

This stores the content of the view in a table called MinOfTax_Code. Now you can do an UPDATE query:

UPDATE MinOfTax_Code 
INNER JOIN Functions ON MinOfTax_Code.func_id = Functions.Func_ID 
SET Functions.Func_TaxRef = [MinOfTax_Code].[MinOfTax_Code]

Doing SQL in Access is a bit of a stretch, I'd look into Sql Server Express Edition for your project!

Andomar