本文介紹了Visual Foxpro中數(shù)據(jù)庫(kù)觸發(fā)技術(shù)的應(yīng)用實(shí)例,為VFP表建立跟蹤日志,提供解決網(wǎng)絡(luò)多用戶環(huán)境中數(shù)據(jù)文件安全的一種方法。
關(guān)鍵詞 觸發(fā)技術(shù),表跟蹤,自定義函數(shù)
表跟蹤問題的提出:
在管理信息系統(tǒng)的正常運(yùn)行中,信息的安全性問題日益突出。雖然網(wǎng)絡(luò)為我們提供了一定的數(shù)據(jù)安全性,只有授權(quán)的用戶才能對(duì)數(shù)據(jù)進(jìn)行日常的維護(hù),但有時(shí)用戶的誤操作可能導(dǎo)致數(shù)據(jù)的丟失或混亂;另外,有時(shí)我們需要對(duì)數(shù)據(jù)的改動(dòng)留下記載等。對(duì)重要的數(shù)據(jù)文件,記錄每一個(gè)數(shù)據(jù)變化的審核日志,對(duì)其建立其相應(yīng)的日志表來(lái)跟蹤對(duì)它的增、刪和修改操作是十分必要的。日志表中記載了何時(shí)、何用戶進(jìn)行了何種操作,記載了被用戶增加或刪除的記錄信息,以及被修改記錄的原來(lái)信息和修改后的信息,將被操縱過的記錄進(jìn)行備份。
VFP觸發(fā)技術(shù):
Visual Foxpro與它的前期版本重大差別之一是使用了數(shù)據(jù)庫(kù)(Database)這一強(qiáng)大功能,使之成為一個(gè)真正的DataBase。VFP的Database Container包含了表(Table)及表的各種屬性定義,也包含了屬于后端的SQL中的觸發(fā)技術(shù)(Trigger)。
Trigger的使用為Database中的Table提供了一個(gè)記錄級(jí)規(guī)則(即檢測(cè)程序)。Trigger分為Insert Trigger、Update Trigger和Delete Trigger三種操作。Insert Trigger用于Table新增記錄時(shí)所觸發(fā)的檢測(cè)程序,Update Trigger用于Table修改記錄回存時(shí)所觸發(fā)的檢測(cè)程序,Delete Trigger用于Table中記錄被刪時(shí)所觸發(fā)的檢測(cè)程序。VFP允許對(duì)任一種操作設(shè)定不同的規(guī)則,該規(guī)則可以是表達(dá)式或用戶自定義函數(shù)(UFD),若響應(yīng)為真值時(shí),表示觸發(fā)成功,若響應(yīng)為假值時(shí),表示觸發(fā)失敗。用戶自定義函數(shù)(UFD)存儲(chǔ)在Database Container中。
創(chuàng)建觸發(fā)器有兩種方式:
1) 打開表屬性”對(duì)話框,在 INSERT、UPDATE 或 DELETE 觸發(fā)器框中,輸入觸發(fā)器表達(dá)式或用戶自定義函數(shù)(UFD);
2) 使用 CREATE TRIGGER 命令。
創(chuàng)建、修改或移去存儲(chǔ)過程有三種方式:
1) 在項(xiàng)目管理器中,選擇并展開一個(gè)數(shù)據(jù)庫(kù),選定“存儲(chǔ)過程”,然后選擇“新建”、“修改”或“移去”按鈕;
2) 在數(shù)據(jù)庫(kù)設(shè)計(jì)器中,從“數(shù)據(jù)庫(kù)”菜單中選擇“編輯存儲(chǔ)過程”按鈕;
3) 在COMMAND命令窗口中,使用 MODIFY PROCEDURE 命令。
表跟蹤設(shè)計(jì):
利用Insert Trigger、Update Trigger和Delete Trigger三種操作原理,我們可以構(gòu)造備,以實(shí)現(xiàn)表跟蹤。這樣,不論用戶使用程序進(jìn)行對(duì)此表的操縱或直接打開此表進(jìn)行增刪和修改記錄,都能激發(fā)Trigger將被操縱記錄進(jìn)行日志記載。
本人構(gòu)造了四個(gè)通用的自定義函數(shù),Inslog()、Dellog()、Modlog()和addlog(),存放于Database Container的存儲(chǔ)過程中。在需要進(jìn)行表跟蹤的數(shù)據(jù)文件的Insert Trigger、Delete Trigger和Update Trigger中分別加入Inslog()函數(shù)、Dellog()函數(shù)和Modlog()函數(shù),以使對(duì)數(shù)據(jù)文件中記錄的增、刪和修改均激發(fā)Trigger進(jìn)行日志記載。addlog()用于建立被跟蹤表的日志表結(jié)構(gòu),日志表的結(jié)構(gòu)設(shè)計(jì)包含了被跟蹤表的所有字段信息,并且增加了用戶標(biāo)志opid、操作日期時(shí)間optime和操作標(biāo)志opmak字段。日志表的命名規(guī)則為被跟蹤表的表名前加‘L,以示區(qū)分,另外本人在存放數(shù)據(jù)文件目錄下另設(shè)子目錄LOGDBFS,專用于存放日志表以便管理。這四個(gè)函數(shù)程序設(shè)計(jì)如下:
*Insert Trigger:
FUNCTION inslog()
m.path=substr(dbf(),1,rat(\,dbf()))
m. logname=m.path+LOGDBFS\L+SUBSTR(DBF(),LEN(m.path)+1)
IF NOT FILE(m.logname)
=addlog() &&建立日志表結(jié)構(gòu)
ENDI
SCATTER MEMVAR
m.opmak=增 &&增加記錄標(biāo)志
m.opid=SYS(0) &&取網(wǎng)絡(luò)用戶標(biāo)志
m.optime=datetime() &&增加記錄時(shí)間
INSERT INTO (m.logname) ;
FROM MEMVAR &&記載所增記錄
RETURN .T.
*Delete Trigger:
FUNCTION dellog()
m.path=substr(dbf(),1,rat(\,dbf()))
m. logname=m.path+LOGDBFS\L+SUBSTR(DBF(),LEN(m.path)+1)
IF NOT FILE(m.logname)
=addlog()
ENDI
SCATTER MEMVAR
m.opmak=刪 &&刪除記錄標(biāo)志
m.opid=SYS(0)
m.optime=datetime()
INSERT INTO (m.logname) ;
FROM MEMVAR &&記載所刪記錄
RETURN .T.
*Update Trigger:
FUNCTION modlog()
m.path=substr(dbf(),1,rat(\,dbf()))
m. logname=m.path+LOGDBFS\L+SUBSTR(DBF(),LEN(m.path)+1)
IF NOT FILE(m.logname)
=addlog()
ENDI
DIME alog[FCOUNT()+3]
alog[FCOUNT()+2]=SYS(0)
alog[FCOUNT()+3]=datetime()
alog[FCOUNT()+1]=修(原)
FOR i=1 TO FCOUNT()
alog[I]=oldval(field[I])
ENDFOR
INSERT INTO (m.logname) ;
FROM ARRAY alog &&記載更改前信息
alog[FCOUNT()+1]=修(現(xiàn))
FOR i=1 TO FCOUNT()
alog[I]=EVALUATE(field[I])
ENDFOR
INSERT INTO (m.logname) ;
FROM ARRAY alog &&記載更改后信息
RETURN .T.
*建立日志表結(jié)構(gòu):
FUNCTION addlog()
*取被跟蹤表字段
COPY STRU TO tmp EXTEND
*建立用戶標(biāo)志、操作時(shí)間和操作標(biāo)志字段信息
INSERT INTO tmp.dbf ;
(field_name,field_type,field_len);
VALUES (OPMAK,C,6)
INSERT INTO tmp.dbf ;
(field_name,field_type,field_len);
VALUES (OPID,C,10)
INSERT INTO tmp.dbf ;
(field_name,field_type,field_len);
VALUES (OPTIME,T,8)
USE IN tmp
oldselect=SELECT() &&生成日志表結(jié)構(gòu)
SELE 0
CREATE (m.logname) FROM tmp
DELETE FILE tmp.dbf
SELECT (oldselect)
關(guān)鍵詞 觸發(fā)技術(shù),表跟蹤,自定義函數(shù)
表跟蹤問題的提出:
在管理信息系統(tǒng)的正常運(yùn)行中,信息的安全性問題日益突出。雖然網(wǎng)絡(luò)為我們提供了一定的數(shù)據(jù)安全性,只有授權(quán)的用戶才能對(duì)數(shù)據(jù)進(jìn)行日常的維護(hù),但有時(shí)用戶的誤操作可能導(dǎo)致數(shù)據(jù)的丟失或混亂;另外,有時(shí)我們需要對(duì)數(shù)據(jù)的改動(dòng)留下記載等。對(duì)重要的數(shù)據(jù)文件,記錄每一個(gè)數(shù)據(jù)變化的審核日志,對(duì)其建立其相應(yīng)的日志表來(lái)跟蹤對(duì)它的增、刪和修改操作是十分必要的。日志表中記載了何時(shí)、何用戶進(jìn)行了何種操作,記載了被用戶增加或刪除的記錄信息,以及被修改記錄的原來(lái)信息和修改后的信息,將被操縱過的記錄進(jìn)行備份。
VFP觸發(fā)技術(shù):
Visual Foxpro與它的前期版本重大差別之一是使用了數(shù)據(jù)庫(kù)(Database)這一強(qiáng)大功能,使之成為一個(gè)真正的DataBase。VFP的Database Container包含了表(Table)及表的各種屬性定義,也包含了屬于后端的SQL中的觸發(fā)技術(shù)(Trigger)。
Trigger的使用為Database中的Table提供了一個(gè)記錄級(jí)規(guī)則(即檢測(cè)程序)。Trigger分為Insert Trigger、Update Trigger和Delete Trigger三種操作。Insert Trigger用于Table新增記錄時(shí)所觸發(fā)的檢測(cè)程序,Update Trigger用于Table修改記錄回存時(shí)所觸發(fā)的檢測(cè)程序,Delete Trigger用于Table中記錄被刪時(shí)所觸發(fā)的檢測(cè)程序。VFP允許對(duì)任一種操作設(shè)定不同的規(guī)則,該規(guī)則可以是表達(dá)式或用戶自定義函數(shù)(UFD),若響應(yīng)為真值時(shí),表示觸發(fā)成功,若響應(yīng)為假值時(shí),表示觸發(fā)失敗。用戶自定義函數(shù)(UFD)存儲(chǔ)在Database Container中。
創(chuàng)建觸發(fā)器有兩種方式:
1) 打開表屬性”對(duì)話框,在 INSERT、UPDATE 或 DELETE 觸發(fā)器框中,輸入觸發(fā)器表達(dá)式或用戶自定義函數(shù)(UFD);
2) 使用 CREATE TRIGGER 命令。
創(chuàng)建、修改或移去存儲(chǔ)過程有三種方式:
1) 在項(xiàng)目管理器中,選擇并展開一個(gè)數(shù)據(jù)庫(kù),選定“存儲(chǔ)過程”,然后選擇“新建”、“修改”或“移去”按鈕;
2) 在數(shù)據(jù)庫(kù)設(shè)計(jì)器中,從“數(shù)據(jù)庫(kù)”菜單中選擇“編輯存儲(chǔ)過程”按鈕;
3) 在COMMAND命令窗口中,使用 MODIFY PROCEDURE 命令。
表跟蹤設(shè)計(jì):
利用Insert Trigger、Update Trigger和Delete Trigger三種操作原理,我們可以構(gòu)造備,以實(shí)現(xiàn)表跟蹤。這樣,不論用戶使用程序進(jìn)行對(duì)此表的操縱或直接打開此表進(jìn)行增刪和修改記錄,都能激發(fā)Trigger將被操縱記錄進(jìn)行日志記載。
本人構(gòu)造了四個(gè)通用的自定義函數(shù),Inslog()、Dellog()、Modlog()和addlog(),存放于Database Container的存儲(chǔ)過程中。在需要進(jìn)行表跟蹤的數(shù)據(jù)文件的Insert Trigger、Delete Trigger和Update Trigger中分別加入Inslog()函數(shù)、Dellog()函數(shù)和Modlog()函數(shù),以使對(duì)數(shù)據(jù)文件中記錄的增、刪和修改均激發(fā)Trigger進(jìn)行日志記載。addlog()用于建立被跟蹤表的日志表結(jié)構(gòu),日志表的結(jié)構(gòu)設(shè)計(jì)包含了被跟蹤表的所有字段信息,并且增加了用戶標(biāo)志opid、操作日期時(shí)間optime和操作標(biāo)志opmak字段。日志表的命名規(guī)則為被跟蹤表的表名前加‘L,以示區(qū)分,另外本人在存放數(shù)據(jù)文件目錄下另設(shè)子目錄LOGDBFS,專用于存放日志表以便管理。這四個(gè)函數(shù)程序設(shè)計(jì)如下:
*Insert Trigger:
FUNCTION inslog()
m.path=substr(dbf(),1,rat(\,dbf()))
m. logname=m.path+LOGDBFS\L+SUBSTR(DBF(),LEN(m.path)+1)
IF NOT FILE(m.logname)
=addlog() &&建立日志表結(jié)構(gòu)
ENDI
SCATTER MEMVAR
m.opmak=增 &&增加記錄標(biāo)志
m.opid=SYS(0) &&取網(wǎng)絡(luò)用戶標(biāo)志
m.optime=datetime() &&增加記錄時(shí)間
INSERT INTO (m.logname) ;
FROM MEMVAR &&記載所增記錄
RETURN .T.
*Delete Trigger:
FUNCTION dellog()
m.path=substr(dbf(),1,rat(\,dbf()))
m. logname=m.path+LOGDBFS\L+SUBSTR(DBF(),LEN(m.path)+1)
IF NOT FILE(m.logname)
=addlog()
ENDI
SCATTER MEMVAR
m.opmak=刪 &&刪除記錄標(biāo)志
m.opid=SYS(0)
m.optime=datetime()
INSERT INTO (m.logname) ;
FROM MEMVAR &&記載所刪記錄
RETURN .T.
*Update Trigger:
FUNCTION modlog()
m.path=substr(dbf(),1,rat(\,dbf()))
m. logname=m.path+LOGDBFS\L+SUBSTR(DBF(),LEN(m.path)+1)
IF NOT FILE(m.logname)
=addlog()
ENDI
DIME alog[FCOUNT()+3]
alog[FCOUNT()+2]=SYS(0)
alog[FCOUNT()+3]=datetime()
alog[FCOUNT()+1]=修(原)
FOR i=1 TO FCOUNT()
alog[I]=oldval(field[I])
ENDFOR
INSERT INTO (m.logname) ;
FROM ARRAY alog &&記載更改前信息
alog[FCOUNT()+1]=修(現(xiàn))
FOR i=1 TO FCOUNT()
alog[I]=EVALUATE(field[I])
ENDFOR
INSERT INTO (m.logname) ;
FROM ARRAY alog &&記載更改后信息
RETURN .T.
*建立日志表結(jié)構(gòu):
FUNCTION addlog()
*取被跟蹤表字段
COPY STRU TO tmp EXTEND
*建立用戶標(biāo)志、操作時(shí)間和操作標(biāo)志字段信息
INSERT INTO tmp.dbf ;
(field_name,field_type,field_len);
VALUES (OPMAK,C,6)
INSERT INTO tmp.dbf ;
(field_name,field_type,field_len);
VALUES (OPID,C,10)
INSERT INTO tmp.dbf ;
(field_name,field_type,field_len);
VALUES (OPTIME,T,8)
USE IN tmp
oldselect=SELECT() &&生成日志表結(jié)構(gòu)
SELE 0
CREATE (m.logname) FROM tmp
DELETE FILE tmp.dbf
SELECT (oldselect)