Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Trigger -> Wrong Results
Message
From
14/02/2004 07:30:42
 
General information
Forum:
Visual FoxPro
Category:
Databases,Tables, Views, Indexing and SQL syntax
Miscellaneous
Thread ID:
00877268
Message ID:
00877377
Views:
11
This message has been marked as a message which has helped to the initial question of the thread.
>Hello.
>
>Let me try to explain my problem!
>
>TableA -> Id_A, Total_A
>TableB -> Id_A, Id_B, Total_B
>
>Both tables have triggers for insert, update and delete. My problem is in Table_B, that calls the function TableB_Trigger for Insert, Update and Delete.
>
>
>Function TableB_Trigger
>m.Id_A = TableB.Id_A
>m.Id_B = TableB.Id_B
>Select Sum(Total_B) From TableB Where Id_B = m.Id_B Into Array Total_A
>m.Total_A = Iif(Type("Total_A[1]")#"N",0,Total_A[1])
>Update Table_A Where Id_A = m.Id_A Set Total_A = m.Total_A
>
>
>Ok. The code works fine, but the results doesn't!
>
>If I open the Table_B (Use) and change the value of field Total_B (from 10 to 50), my trigger is fired and the code returns Total_A = 10 ... and it should be 50, ok?
>
>I think the Select Sum(Total_B) is taking the "old value" in the table... because VFP doesn't know if that transaction will complete or won't.
>
>I just want to calculate this total and put it in other table...
>
>Do you have some "magic potion" to fix it?
>
>TIA! TIA! TIA!

Rodolfo,

(1) Select sql returns the oldvalue as you noticed since the new value isn't committed until the triggers exit with a .T. value
(2) do not prefix the table fields with the tablename in the trigger (TableB.Id_A) since you do not know what the alias of tableB will be. Instead use Id_A. Once yiu enter a trigger for TableX your current selected area is TableX.

(3) Code could be somthing like
function TableB_Trigger(TriggerType)
    local Success, Ids[2], Delta[2], AliasName, s, i
    
    Success = .T.
    AliasName = sys(2015)
    do case
    case TriggerType == 'I' && for insert
        Ids[1] = Id_A
        Delta[1] = Total_B
        

    Case TriggerType == 'U' && for update
        DO case
        case oldval('Id_A') == Id_A && key not changed
           Ids[1] = Id_A
           Delta[1] = - oldval('Total_B') + Total_b
          

        otherwise
            Ids[1] = oldval('Id_A')
            Delta[1] = - oldval('Total_B')
            Ids[2] = Id_a
            Delta[2] = Total_B
       endcase

     case TriggerType = 'D'  && for delete
         Ids[1] =  oldval('Id_A')
         Delta[1] = - oldval('Total_B')

     otherwise
        assert .F.
        Success = .F.

     endcase

     do case
     case !Success

     case empty(Delta[1]) and empty(Delta[2])
        && nothing to do

    otherwise
       use Table_A in 0 alias (AliasName) order Id && order of Id_A
       s = select(0)
       select (AliasName)
       for i = 1 to 2
          do case
          case !Success

          case empty(Delta[i])

          case seek(Ids[i])
             do case
             case !_TriggerLockRecord()
                 Success = .F.
             otherwise
                 repl Total_A with Total_a + Delta[i]
                 Success = Success and _TriggerTableUpdate()
                 =_TriggerUnLockRecord()
              endcase
          
          otherwise
              insert into (AliasName) (Id_a, Total_a) values (Ids[i], Delta[i])
              Success = Success and _TriggerTableUpdate()
          endcase
       endfor
       use in (AliasName)
       select (s)
    endcase

    return Success
endfunc
*---------------------------------------------------------------------------
function _TriggerTableUpdate()
	
	do case
	case (CursorGetProp('Buffering') > 1)
		do case
		case !TableUpdate()
			=TableRevert()
			return FALSE
		endcase
	endcase

endfunc
*---------------------------------------------------------------------------
&& change for deadlocks
function _TriggerLockRecord()

	local Success
	Success = TRUE
	
	do case
	case (IsRLocked() and !Deleted())
		Success = FALSE
	case !RLock()
		Success = FALSE
	endcase
	
	do case
	case !Success
		local msg, _table
		_table = CursorGetProp('SourceName')
		msg = 'Cannot lock record in ' + _table
		
		=_TriggerError(-1, 'Cannot lock record', '', '', msg, ;
								_Table, '', '', '' )
	endcase
	return Success
endfunc
*---------------------------------------------------------------------------
function _TriggerUnLockRecord()

	unlock record (recno())
endfunc
*---------------------------------------------------------------------------
I would use a view. Much simpler
Gregory
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform