Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / FoxPro, Visual FoxPro Новый топик    Ответить
 Журнал изменений  [new]
no.exit | tex
Guest
Есть база данных, в которой необходимо вести журнал изменений по полям. Так вот иногда при добавлении записи, почему-то в журнал информация о добавлении не записывается, т.е. добавили в две таблицы записи, например в 1-ю 2, а во 2-ю 10, в следующем порядке, сначала 1-у в 1-ю табл. потом 5 во 2-ю, далее опять 1-у в первую, и оставшиеся 5 во вторую. Так вот информация о добавлении, почему-то не проходит при добавлении 5 записей на первом шаге, т.е. во вторую таблицу, но по остальным все ок. Ниже приведен код.


FUNCTION MainTrigger(c_TableName)
	
	LOCAL ln_arrValue[1]
	ln_arrValue(1)=0
	
	SELECT COUNT(centerid) FROM tcenters ;
		WHERE source = .T. ;
		INTO ARRAY ln_arrValue
	
	IF(ln_arrValue(1)>0)
	
		* проверка на курсор
		IF (JUSTEXT(DBF()) = "TMP")
			RETURN .T.
		ENDIF
		 
		LOCAL lcAlias
		IF TYPE("c_TableName")<>"C" OR EMPTY(m.c_TableName)=.T.
			lcAlias = UPPER(JUSTSTEM(DBF()))
		ELSE
			lcAlias = UPPER(AllTrim(m.c_TableName))
		ENDIF
	
		LOCAL lc_returnval
		lc_returnval = .F.

		DO CASE  
			CASE Deleted()
				lc_returnval = TRIGGERPROCESS(lcAlias,"D",dbid,recid)		&& вызов из триггера на удаление  
			CASE NVL(OldVal("Deleted()"),.T.)  
				lc_returnval = TRIGGERPROCESS(lcAlias,"A",dbid,recid)		&& вызов из триггера на вставку  
			OTHERWISE  
				lc_returnval = TRIGGERPROCESS(lcAlias,"M",dbid,recid)		&& вызов из триггера на модификацию
		ENDCASE  
	ENDIF

	RETURN lc_returnval
ENDFUNC
*<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>




*<<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>
* основное тело триггера
* вх. параметры
*         c_Table_name 	- имя таблицы
*         c_Act 		- дествие произведенное оператором
*         i_dbid 		- идентификатор базы данных (часть составного ключа)
*         i_recid 		- идентификатор записи в таблице (часть составного ключа)
FUNCTION TRIGGERPROCESS(c_TableName,c_Act,i_dbid,i_recid)

	LOCAL ln_DBID			&& идентификатор БД для записи
	LOCAL ln_RecID			&& идентификатор номера записи
	LOCAL lc_Act			&& A - добавлена, E - изменена, D - удалена
	LOCAL lt_DateTime			&& дата и время изменения
	LOCAL ln_State			&& тек. состояние записи
	LOCAL lc_fldstate			&& строка, в кот. закодировано какие поля изменились
	LOCAL ln_len			&& длина строки
	LOCAL lc_fldname			&& имя поля
	LOCAL lc_symbol			&& символ состояния поля == 1-не изм,2-изм,3-доб.не изм,4-доб.изм.
	LOCAL lc_OldDecimal		&& переменная установки среды
	LOCAL lc_OldANSI			&& переменная установки среды - сравнивание строк в  SQL запросах
	LOCAL ln_fldindex
	LOCAL ln_i
	LOCAL ll_NotError

	* инициализация
	ln_DBID     = m.i_dbid
	ln_RecID    = m.i_recid
	lc_Act      = m.c_Act
	lt_DateTime = DATETIME()
	ln_State    = 0
	lc_fldstate = GETFLDSTATE(-1) 	&& определяем какие поля изменились
	ln_len 		= LEN(lc_fldstate)	&& определяем длину строки

	ll_NotError = .T.
	
	*=====================================	
	* установим переменные среды
	lc_OldDecimal  = SET("DECIMALS")
	lc_OldANSI      = SET("ANSI")

	SET DECIMALS TO 0
	SET ANSI ON
	*=====================================	

	*=====================================	
	LOCAL lc_Error
	LOCAL ll_NotError
	ll_NotError = .T.
	lc_Error=ON("ERROR")
	ON ERROR ll_NotError = .F.
	*=====================================	


	*============================================================================
	* узнаем идентификатор БД, создавшей запись
	LOCAL ln_arrCurrentDBID[1]
	ln_arrCurrentDBID(1) = 0

	SELECT centerid FROM tcenters  	;
		WHERE tcenters.visible=.T. 	;
		INTO ARRAY ln_arrCurrentDBID

		
	*============================================================================
	* узнаем идентификатор таблицы, в которой были произведены изменения
	LOCAL ln_arrCurrentTBLID[1]
	ln_arrCurrentTBLID(1) = 0

	SELECT tableid FROM ttables ;
		WHERE ALLTRIM(UPPER(tablename))=ALLTRIM(UPPER(m.c_TableName)) 	;
		INTO ARRAY ln_arrCurrentTBLID


	*============================================================================
	* проверка, является ди данная БД центральной
	LOCAL ll_arrIsMainCenter[1]
	ll_arrIsMainCenter(1) = .F.
	
	SELECT maincenter FROM tcenters 	;
		WHERE tcenters.visible=.T. 		;
		INTO ARRAY ll_arrIsMainCenter


	*============================================================================
	* массив с идентификаторами баз данных, с кот. произв. синхронизация
	LOCAL ln_arrDBS[1]
	ln_arrDBS(1) = 0

	IF(ll_arrIsMainCenter(1)) THEN
		* является главным центром
		SELECT centerid FROM tcenters 		 ;
			WHERE tcenters.maincenter = .F.  ;
			INTO ARRAY ln_arrDBS
	ELSE
		* является филиалом
		SELECT centerid FROM tcenters 		 ;
			WHERE tcenters.maincenter = .T.  ;
			INTO ARRAY ln_arrDBS
	ENDIF
	*============================================================================



	IF(lc_Act == "M") THEN
		
		* цикл - определение измененных полей в записи
		FOR ln_fldindex = 1 TO ln_len

			lc_fldstate	= RIGHT(lc_fldstate,ln_len - ln_fldindex)	&& удалили  крайний левый символ
			lc_symbol 	= LEFT(lc_fldstate,1)						&& выделили крайний левый символ
			lc_fldname	= UPPER(FIELD(ln_fldindex))					&& получили название поля в верхнем регистре
		
			* возможные варианты значения lc_symbol
			* lc_symbol == '1' 	- поле не изменилось
			* lc_symbol == '2' 	- поле модифицировано
			* lc_symbol == '3' 	- поле добавлено (запись только-что создана)
			* lc_symbol == '4' 	- поле добавлено и модифицировано (запись только-что создана, а поле изменило свое значение)
		
		
			IF(lc_symbol == '2') THEN	&& поле модифицировано
			
				*=====================================	
				* проверка на присутствие дублирующих записей
				UPDATE tjournal ;
					SET act = "P",state = -1 ;
					WHERE tableid = ln_arrCurrentTBLID(1) .AND. dbid = ln_DBID .AND. recid = ln_RecID .AND. fldname = lc_fldname
				*=====================================			

				*=====================================
				* вставка записи в журнал - таблица tjournal
				FOR ln_i = 1 TO ALEN(ln_arrDBS)
					INSERT INTO tjournal (tableid,dbid,recid,fldname,act,date,owncenterid,state,centerid)	; 
						VALUES (ln_arrCurrentTBLID(1),ln_DBID,ln_RecID,lc_fldname,lc_Act,lt_DateTime,ln_arrCurrentDBID(1),ln_State,ln_arrDBS(ln_i))
				NEXT
				*=====================================	
		
			ENDIF

		NEXT
		*=====================================	

	ELSE	&& запись удалена или добавлена
	
		lc_fldname = "*"	&& изменению подверглись все поля
	
		*=====================================	
		* проверка на присутствие дублирующих записей
		UPDATE tjournal ;
			SET act = "P",state = -1 ;
			WHERE tableid = ln_arrCurrentTBLID(1) .AND. dbid = ln_DBID .AND. recid = ln_RecID
		*=====================================			

		*=====================================
		* вставка записи в журнал - таблица tjournal
		FOR ln_i = 1 TO ALEN(ln_arrDBS)
			INSERT INTO tjournal (tableid,dbid,recid,fldname,act,date,owncenterid,state,centerid)	; 
				VALUES (ln_arrCurrentTBLID(1),ln_DBID,ln_RecID,lc_fldname,lc_Act,lt_DateTime,ln_arrCurrentDBID(1),ln_State,ln_arrDBS(ln_i))
		NEXT
		*=====================================	
		
	ENDIF


	IF(CURSORGETPROP('BUFFERING','tjournal')>1) THEN
	=TABLEUPDATE(.T.,.T.,"tjournal")   
	ENDIF


	*=====================================	
	* востановим переменные среды

	ON ERROR &lc_Error
	
	IF(lc_OldANSI == "OFF") THEN
		SET ANSI OFF
	ENDIF
	
	SET DECIMALS TO (lc_OldDecimal)
	*=====================================	
	

	

	RETURN ll_NotError
ENDFUNC


19 июн 06, 14:55    [2787425]     Ответить | Цитировать Сообщить модератору
 Re: Журнал изменений  [new]
no.exit | tex
Guest
В догонку. Хочу обощить все вышеизложенное. Записи добавляются в таблицы, но в момент добавления триггеры неправильно срабатывают, т.е. в журнал ничего не записывается 8( Либо выборки дают 0, хотя они все идут из таблицы tcenters, которая заполняется отдельно при настройке БД и в программе в ней изменяется только одно поле - уникальный ключ заказа. Либо вставка неудачная производиться в журнал, не пойму в чем дело, т.к. происходит это где-то на 1000 вставок.
19 июн 06, 16:32    [2788225]     Ответить | Цитировать Сообщить модератору
Все форумы / FoxPro, Visual FoxPro Ответить