On 12-Apr-2012 14:34 , Thomas Garvey wrote:
CRPence on Wednesday, April 11, 2012 5:22 PM wrote:
<<SNIP>> If a SEQUENCE could possibly be used instead, <<SNIP>>
On 11-Apr-2012 09:47 , Thomas Garvey wrote:
I'm using embedded SQL to update a counter in a database field,
but would also like to know the new value of that counter without
having to retrieve the newly updated record.
For example, using embedded SQL in my RPGLE, as follows...
exec sql
update fileX
  set counter = counter + 1
  where keyfield = :something
  Since the "counter" value in the original example [snippet inserted 
above] seemed to be tied to a particular key value, I figured that using 
a SEQUENCE would probably be impractical :-(
  I do not recall a release level ever being mentioned.?
I can't use the SEQUENCE or IDENTITY phrase.  My understanding is
that their scope is table wide, and my intention is subsidiary to
other fields.
  The IDENTITY is.  The SEQUENCE however, is separate from a TABLE, so 
the application(s) decide for what and how the sequence is utilized.
MY use would be similar to a count of how many times a record has
been changed. So, the counter is not a key value or a sequence that
is unique across the table.
  The SEQUENCE could be used, even in the described scenario, although 
probably not very succinctly.  Establishing a SEQUENCE for each 
effective 'group' of data, for example, would be an undesirable 
implementation due to the potentially large number of sequence objects 
to maintain.
  Presumably the keyfield is uniquely keyed such that just one counter 
value is tracked to each key value.?  And is the limit also specific to 
each key value?  If so, then the limit would seem best stored in the 
same row, in another column.  A CHECK CONSTRAINT could then enforce the 
maximum in that case; e.g. alter table fileX add constraint 
fileX_ck_counter check (counter < max_counter).  This is easiest, if 
possible; other applications could even remain unchanged, referring to a 
LF without the new column.
  Especially if the previous comments seem silly... Perhaps offering a 
more explicit example(s) than the very generically described example 
originally given, to include DDL with constraints and\or unique indexes 
and sample data, would assist to better describe the data and scenario.?
I'd like to be able to execute the SQL UPDATE, incrementing the
counter field (multiple programs will be able to update this
counter),
  Where are the limits defined\stored; a limits_test() function, a 
limits database file, other...?  Obviously the program that would be 
doing the UPDATE knows the limits, because that program is supposed to 
know to respond if the limit is reached.
  Consider that the following statement variations for which "row not 
found" is the result, the counter is known to have previously grown to 
its limit [if the key value can be assumed to exist; e.g. in the second 
statement that would be ensured when the limits_file is also a parent 
file off fileX in a referential constraint]:
     update fileX set counter=counter+1
     where keyfield=:something
       and counter<limits_test(:something)
     update fileX set counter=counter+1
     where keyfield=:something
       and counter<(select counter_limit from limits_file
                    where keyfield=:something)
  As a variation of the above... two separate updates could detect both 
the will-become-maximum and the at-maximum, performing just one update 
however in all but the /boundary/ cases.  Using the UDF model from 
above, in pseudo-code:
     execsql
     update fileX set counter=counter+1
     where keyfield=:something
       and counter<limits_test(:something)-1 -- two down from max
     ; -- if row-found and updated, increment done within bounds
     if row-not-found then do // already one down from, or at max
      notify(verging-on-max);
      execsql
      update fileX set counter=counter+1
      where keyfield=:something
        and counter<limits_test(:something)
      ; -- if row-found and updated, then increment was to maximum
      if row-not-found then do // already at max, do not increment
       notify(at-max);
      end;
     end;
and when the counter has reached a variable limit, subsequent logic
would send a message to a user that the limit has been reached.
  Presumably a hard-stop on any other requests since having hit the 
limit?  That is, if the user who was notified of the condition has not 
effected some resolution nor any other automation having effected 
resolution, than surely any other increment should fail.?
  FWiW:
  While the standalone UPDATE is nice to just let the DB do the work 
atomically, the row data is still paged [or faulted] into memory.  If 
the reason for not wanting "to retrieve the newly updated record" is 
mostly about performance, actual testing may prove concerns to be 
unfounded or at least subdued.
  There would be other /tricks/ to get the column value from elsewhere, 
for example via a TRIGGER or the journal receiver, but obtaining the 
value from the row itself is most obvious [for the code].  With IBM i 
7.1 the SQL Global Variables may enable a more integrated means; i.e. 
less of a "trick".
  Consider encapsulating the work in an atomic SQL or External stored 
PROCEDURE, or if already running with isolation perhaps make the work 
part of an overall transaction that is later committed after both the 
increment activity and the remaining work in that transaction is deemed 
complete:
     declare cursor as select for update of counter
     open
     fetch
     if below-limit then update set increment where current of
     if limit-reached by increment then optionally:
      feedback\signal sqlstate to inform of at-maximum
     set an output variable with the new counter
     the program, instead of the SQL UPDATE uses SQL CALL:
     call theProc(:something, :rtn_counter)
     if so_informed then this program notifies user of limit-reached; 
either by returned counter value or failure
  As a procedure instead of inline to the program, all programs 
[including external client requester] that update the field could use 
the same interface.  However....
  Having suggested that "multiple programs will be able to update this 
counter" I wonder if that might intend to imply that all interfaces for 
which an update might be requested should enforce that notification of 
the verging-on-max condition, as a "business rule".?  If so, then 
perhaps the work might best be pushed down to a TRIGGER; if there could 
not be an assurance that all programs would be coded to use a common 
ROUTINE to effect the update\increment.?
Regards, Chuck
As an Amazon Associate we earn from qualifying purchases.