tags:

views:

498

answers:

5
SELECT
    (SELECT 
     IIF(IsNull(sum(b.AmountCharged) - sum(b.AmountPaid)),
                a.Balance, 
                (sum(b.AmountCharged) - sum(b.AmountPaid)))
     FROM tblCurrentTransaction AS b
     WHERE b.TenantTransactionID <= a.TenantTransactionID 
                AND b.Tenant = a.Tenant
     GROUP BY b.Tenant
    ) AS TrueBalance, a.TenantTransactionID
    FROM tblCurrentTransaction AS a
    ORDER BY a.Tenant, a.TenantTransactionID;
UNION
UPDATE tblCurrentTransaction SET tblCurrentTransaction.Balance = TrueBalance
WHERE tblCurrentTransaction.TenantTransactionID = a.TenantTransactionID;

Basically what happens is I get a result set from the first query, then I match it's TenantTransactionID with the update query. However Access complains: "An action query cannot be used as a row source"

How can I fix this?

This is the query without the UNION

UPDATE tblCurrentTransaction SET tblCurrentTransaction.Balance = (SELECT
    (SELECT 
     IIF(IsNull(sum(b.AmountCharged) - sum(b.AmountPaid)),
                a.Balance, 
                (sum(b.AmountCharged) - sum(b.AmountPaid)))
     FROM tblCurrentTransaction AS b
     WHERE b.TenantTransactionID <= a.TenantTransactionID 
                AND b.Tenant = a.Tenant
     GROUP BY b.Tenant
    ) AS TrueBalance
    FROM tblCurrentTransaction AS a
    WHERE a.TenantTransactionID = tblCurrentTransaction.TenantTransactionID
    ORDER BY a.Tenant, a.TenantTransactionID;
);

But it doesn't do anything, and Access complains "Operation must use an updateable query"

This is the query that gathers the data This query returns the true balance, and the transaction ID it belongs to. This is what I need to insert into the table.

SELECT (SELECT IIF(IsNull(sum(b.AmountCharged) - sum(b.AmountPaid)),a.Balance, (sum(b.AmountCharged) - sum(b.AmountPaid)))
          FROM tblCurrentTransaction AS b
          WHERE b.TenantTransactionID <= a.TenantTransactionID AND b.Tenant = a.Tenant
          GROUP BY b.Tenant
        ) AS TrueBalance, a.TenantTransactionID
FROM tblCurrentTransaction AS a
ORDER BY a.Tenant, a.TenantTransactionID;
A: 

You need to reorder your query, so you're performing an UPDATE ... WHERE (criteria) IN (SELECT ...). Basically, use your SELECT as a subselection to provide a resultset for the IN.

McWafflestix
+1  A: 

SELECT UNION UPDATE. Wow. Never seen anybody try that one before.

If this really has to be done in SQL, I'd say rewrite the whole thing as an UPDATE with subqueries.

If it doesn't really have to be done in SQL, I'd say rewrite the whole process so the logic is in your application language and the SQL queries are simple UPDATEs.

Edit: OP and I went through quite some adventures, as you can see in the comments. The final resolution was to use a scratch table to do the calculations in and push the results from there back into tblCurrentTransaction. I blame Access.

chaos
You have to have a pretty thin skin for that to be mockery. It's also not my intention; I try crazy things to see if they'll work all the time. I'm impressed that someone had tried a level of craziness I'd not seen or thought of.
chaos
I'm dealing with Access 97, and a terrible, terrible database that I can't change. I'm not familiar with Access Syntax, therefor I'm doing crazy things.
Malfist
@chaos: Fair enough, I read it as sarcasm because that's usually what goes through my head. I took it as mocking disbelief, rather than the intent. Another one to put into the annals of the written word being misconstrued.
Eric
Your query errors with "Operation must use an updateable query"
Malfist
I updated the question, maybe it'll help
Malfist
Made some further updates, trying to simplify the query and address the 'updateability' issue. Let me know what happens...
chaos
"Operation must use an updateable query" again...
Malfist
Okay. Now I'm thinking that what it means by that is that you can't do a subselect in the table you're doing an UPDATE on. Which is kind of rough, and the only way to get around it that I know of (without pulling the logic out into the application) is making a temporary table.
chaos
97 doesn't seem to support temp tables, I've already tried.
Malfist
Yeesh. Well, I guess you could make a permanent scratch table for you to do your calculations in, 1:1 with the Tenants in tblCurrentTransaction. Update that with your calculations per-tenant and then update tblCurrentTransaction from it.
chaos
That worked. I created a scratch table, ick.
Malfist
Sorry. It's very sad, the violations Access perpetrates upon us.
chaos
Well, the app to replace it will be released in a few weeks, but it's a big business and they have to have their tools working NOW. The new app is in C# with SQL Server 2008 with a redesigned, normalized database.
Malfist
I'm voting your answer down for badmouthing Access. Blaming the tools is the mark of an incompetent workman.
David-W-Fenton
Thanks for letting me know, so I understand what an idiot you are.
chaos
@David: Obviously you've never used Access. As somebody who marked himself as a fool early in this thread, I pass the torch on to you.
Eric
@David W. Fenton: "Blaming the tools is the mark of an incompetent workman" -- sure you've never badmouthed the technology: SQL DDL, JRO, ...?
onedaywhen
@David, QBasic, VisualBasic, battery powered soldering ironsl...
Malfist
I love how actually doing the work to help the guy solve his problem doesn't count for anything if someone's a product evangelist and you don't kiss its shiny ass.
chaos
Anyway, the thing that David doesn't get about the cliche about the workman and tools is that it doesn't mean there's no such thing as a bad tool. It means that a good workman can be expected to afford, choose and use good tools. Unfortunately, in many situations, such as THIS EXACT ONE, we do not get to choose our tools and are forced to use a bad one.
chaos
+1  A: 

Try this:

UPDATE tblCurrentTransaction SET tblCurrentTransaction.Balance = i.TrueBalance
FROM ((SELECT 
    IIF(IsNull(sum(b.AmountCharged) - sum(b.AmountPaid)), a.Balance, (sum(b.AmountCharged) - sum(b.AmountPaid)))
    FROM tblCurrentTransaction AS b
    WHERE b.TenantTransactionID <= a.TenantTransactionID AND b.Tenant = a.Tenant
    GROUP BY b.Tenant
  ) AS TrueBalance, a.TenantTransactionID
  FROM tblCurrentTransaction AS a
 )AS i
WHERE tblCurrentTransaction.TenantTransactionID = i.TenantTransactionID;
Ralph Wiggum
Syntax error (missing operator) in query expression 'i.TrueBalance ... AND b.Tenant = a'.
Malfist
UPDATE ... FROM doesn't work on Access97, I don't believe. On SQL Server and Oracle, it's golden, though.
Eric
Eric is correct. And it doesn't work in Access2000 either! :(
Ralph Wiggum
A: 

I have a recent experience similar to this. I needed to update a join and discovered that Access won't handle complex update queries like that. I suspect that this situation falls into that bucket, but that's really hard to establish since the Access docs aren't that definitive on what it will and won't do. I ended up moving the work to SQL Server.

Bottom line, I agree with CHAOS that you should simplify the query by surrounding it with app logic.

Greg Oliver
A: 

See MSDN:

ACC: Update Query Based on Totals Query Fails

[Quote] When you run an update query, you receive the following error message:

Operation must use an updatable query.

This error message occurs when the values in the query's Update To row are fields in ... a select query or subquery that contains aggregate (totals) functions...

This behavior is a design limitation. [Unquote]

[I hear someone here is down-voting people for dissing the Access database engine. Oh well, I guess I'll just have to put my reputation on the line...]

The Access database engine has many "design limitations" but for me its non-Standard (ISO/ANSI SQL Standard, that is), ambiguous and severely limited UPDATE syntax is its very worst feature. None of the workarounds are acceptable to me and is one of the genuine reasons why I moved all my serious projects to SQL Server years ago.

onedaywhen