Skip to main content
Previous sectionNext section

TSTART

Marks the beginning of a transaction.

Synopsis

TSTART:pc
TS:pc

Argument

Argument Description
pc Optional — A postconditional expression.

Description

TSTART marks the beginning of a transaction. Following TSTART, database operations are journaled to enable a subsequent TCOMMIT or TROLLBACK command.

TSTART increments the value of the $TLEVEL special variable. A $TLEVEL value of 0 indicates that no transaction is in effect. The first TSTART begins a transaction and increments $TLEVEL to 1. Subsequent TSTART commands can create nested transactions, further incrementing $TLEVEL.

Not all operations that occur within a transaction can be rolled back. For example, setting global variables within a transaction can be rolled back; setting local variables within a transaction cannot be rolled back. Refer to Using ObjectScript for Transaction Processing in Using ObjectScript for further details.

By default, a lock issued within a transaction will be held until the end of the transaction, even if the lock is released within the transaction. This default can be overridden when setting the lock. Refer to the LOCK command for more details.

Nested Transactions

If you issue a TSTART within a transaction it begins a nested transaction. Issuing a TSTART increments the $TLEVEL value, indicating the number of levels of transaction nesting. You end a nested transaction by issuing either a TCOMMIT to commit the nested transaction, or a TROLLBACK 1 to roll back the nested transaction. Ending a nested transaction decrements the $TLEVEL value by 1.

  • Issuing a TROLLBACK 1 for a nested transaction rolls back changes made in that nested transaction and decrements $TLEVEL. You can issue a TROLLBACK to roll back the whole transaction, no matter how many levels of TSTART were issued.

  • Issuing a TCOMMIT for a nested transaction decrements $TLEVEL, but the actual commitment of the nested transaction is deferred. Changes made during a nested transaction are only irreversibly committed when the outermost transaction is committed; that is, when a TCOMMIT decrements the $TLEVEL value to 0.

You can use the GetImageJournalInfo() method of the %SYS.Journal.System class to search the journal file for TSTART commands, and thus identify open transactions. A TSTART writes either a “BT” (Begin Transaction) journal file record if $TLEVEL was zero, or a “BTL” (Begin Transaction with Level) journal file record if $TLEVEL was greater than 0.

The maximum number of levels of nested transactions is 255. Attempting to exceed this nesting levels limit results in a <TRANSACTION LEVEL> error.

SQL and Transactions

ObjectScript and SQL transaction commands are fully compatible and interchangeable, with the following exception:

ObjectScript TSTART and SQL START TRANSACTION both start a transaction if no transaction is current. However, START TRANSACTION does not support nested transactions. Therefore, if you need (or may need) nested transactions, it is preferable to start the transaction with TSTART. If you need compatibility with the SQL standard, use START TRANSACTION.

ObjectScript transaction processing provides limited support for nested transactions. SQL transaction processing supplies support for savepoints within transactions.

Argument

pc

An optional postconditional expression. InterSystems IRIS executes the TSTART command if the postconditional expression is true and does not execute the TSTART command if the postconditional expression is false. For further details, refer to Command Postconditional Expressions in Using ObjectScript.

Examples

The following example uses a single-level transaction to transfer a random amount of money from one account to another. If the transfer amount is more than the available balance, the program rolls back the transaction:

SetupBankAccounts
   SET num=12345
   SET ^CHECKING(num,"balance")=500.99
   SET ^SAVINGS(num,"balance")=100.22
   IF $DATA(^NumberOfTransfers)=0 {SET ^NumberOfTransfers=0}
BankTransfer
   WRITE "Before transfer:",!,"Checking=$",^CHECKING(num,"balance")," Savings=$",^SAVINGS(num,"balance"),!
   // Transfer funds from one account to another
   SET transfer=$RANDOM(1000)
   WRITE "transfer amount $",transfer,!
   DO CkToSav(num,transfer)
   IF ok=1 {WRITE "sucessful transfer",!,"Number of transfers to date=",^NumberOfTransfers,!}
   ELSE {WRITE "*** INSUFFICIENT FUNDS ***",!}
   WRITE "After transfer:",!,"Checking=$",^CHECKING(num,"balance")," Savings=$",^SAVINGS(num,"balance"),!
   RETURN
CkToSav(acct,amt)
  TSTART
  SET ^CHECKING(acct,"balance") = ^CHECKING(acct,"balance") - amt
  SET ^SAVINGS(acct,"balance") = ^SAVINGS(acct,"balance") + amt
  SET ^NumberOfTransfers=^NumberOfTransfers + 1
  IF ^CHECKING(acct,"balance") > 0 {TCOMMIT  SET ok=1 QUIT:ok}
  ELSE {TROLLBACK  SET ok=0 QUIT:ok}
Copy code to clipboard

The following examples use TSTART to create nested transactions. They show three scenarios for rollback of nested transactions:

Roll back the innermost transaction, commit the middle transaction, commit the outermost transaction:

  KILL ^a,^b,^c
  TSTART  SET ^a=1 WRITE "tlevel=",$TLEVEL,!
    TSTART  SET ^b=2 WRITE "tlevel=",$TLEVEL,!
      TSTART  SET ^c=3 WRITE "tlevel=",$TLEVEL,!
      TROLLBACK 1 WRITE "tlevel=",$TLEVEL,!
    TCOMMIT  WRITE "tlevel=",$TLEVEL,!
  TCOMMIT  WRITE "tlevel=",$TLEVEL,!
  IF $DATA(^a) {WRITE "^a=",^a,!} ELSE {WRITE "^a is undefined",!}
  IF $DATA(^b) {WRITE "^b=",^b,!} ELSE {WRITE "^b is undefined",!}
  IF $DATA(^c) {WRITE "^c=",^c,!} ELSE {WRITE "^c is undefined",!}
Copy code to clipboard

Commit the innermost transaction, roll back the middle transaction, commit the outermost transaction:

  KILL ^a,^b,^c
  TSTART  SET ^a=1 WRITE "tlevel=",$TLEVEL,!
    TSTART  SET ^b=2 WRITE "tlevel=",$TLEVEL,!
      TSTART  SET ^c=3 WRITE "tlevel=",$TLEVEL,!
      TCOMMIT  WRITE "tlevel=",$TLEVEL,!
    TROLLBACK 1 WRITE "tlevel=",$TLEVEL,!
  TCOMMIT  WRITE "tlevel=",$TLEVEL,!
  IF $DATA(^a) {WRITE "^a=",^a,!} ELSE {WRITE "^a is undefined",!}
  IF $DATA(^b) {WRITE "^b=",^b,!} ELSE {WRITE "^b is undefined",!}
  IF $DATA(^c) {WRITE "^c=",^c,!} ELSE {WRITE "^c is undefined",!}
Copy code to clipboard

Commit the innermost transaction, commit the middle transaction, roll back the outermost transaction:

  KILL ^a,^b,^c
  TSTART  SET ^a=1  WRITE "tlevel=",$TLEVEL,!
    TSTART  SET ^b=2  WRITE "tlevel=",$TLEVEL,!
      TSTART  SET ^c=3  WRITE "tlevel=",$TLEVEL,!
      TCOMMIT  WRITE "tlevel=",$TLEVEL,!
    TCOMMIT  WRITE "tlevel=",$TLEVEL,!
  TROLLBACK 1  WRITE "tlevel=",$TLEVEL,!
  IF $DATA(^a) {WRITE "^a=",^a,!} ELSE {WRITE "^a is undefined",!}
  IF $DATA(^b) {WRITE "^b=",^b,!} ELSE {WRITE "^b is undefined",!}
  IF $DATA(^c) {WRITE "^c=",^c,!} ELSE {WRITE "^c is undefined",!}
Copy code to clipboard

Note that in this third case, TROLLBACK 1 and TROLLBACK would have the same result, because both would decrement $TLEVEL to 0.

See Also