首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > oracle >

Oracle :new 与:old 和变量的有关问题

2011-12-27 
Oracle :new 与:old 和变量的问题我在表MEM_MEMBER中建立一个触发器,因为表MEM_MEMBER 中字段太多,我要循

Oracle :new 与:old 和变量的问题
我在表MEM_MEMBER中建立一个触发器,因为表MEM_MEMBER 中字段太多,我要循环表MEM_MEMBER中的字段来比较new 和old值 我要循环表MEM_MEMBER中的字段,如:new.mem_member_id或者:old.mem_member_id我想把表MEM_MEMBER中的所有的字段用一个变量表示出来,如:new.v_column_name 我已经通过游标把字段名都取出来了,我要比较每个字段是否有变化,然后我再插入另一个表中,可是有问题,怎么办?
create or replace trigger TR_MEM_MEMBER_LOG
after INSERT OR UPDATE OR DELETE ON MEM_MEMBER FOR EACH ROW
declare
cursor CUR_MEM_MEMBER_LOG_DATA is
  select column_name,column_id from user_tab_cols where table_name='MEM_MEMBER' order by column_id; 
  v_column_name user_tab_cols.column_name%type;
  v_column_id user_tab_cols.column_id%type;  
BEGIN 
--更新时写日志
IF UPDATING THEN
  OPEN CUR_MEM_MEMBER_LOG_DATA;
  LOOP
  FETCH CUR_MEM_MEMBER_LOG_DATA INTO v_column_name,v_column_id;  
  EXIT WHEN CUR_MEM_MEMBER_LOG_DATA%NOTFOUND;
  --有问题
  IF ':NEW.'||v_column_name <> ':OLD.'||v_column_name THEN
  INSERT INTO MEM_MEMBER_LOG(MEMBER_LOG_ID,MEMBER_ID,MENMBER_FIELDS,MENMBER_COUNT,MEMBER_LOG_FLAG,OPERATION_DATE) 
  Values(SEQ_MEM_MEMBER_LOG.NEXTVAL,:OLD.MEMBER_ID, v_column_name,':OLD.'||v_column_name,'2',SYSDATE);
  End IF ; 
  End loop; 
  close CUR_MEM_MEMBER_LOG_DATA;
End IF;
End TR_MEM_MEMBER_LOG;

[解决办法]
还是字段一一列出来吧,你上面的方法肯定不行。

[解决办法]

SQL code
CREATE OR REPLACE TRIGGER TR_MEM_MEMBER_LOG  AFTER INSERT OR UPDATE OR DELETE ON MEM_MEMBER  FOR EACH ROWDECLARE  CURSOR CUR_MEM_MEMBER_LOG_DATA IS    SELECT COLUMN_NAME, COLUMN_ID      FROM USER_TAB_COLS     WHERE TABLE_NAME = 'MEM_MEMBER'     ORDER BY COLUMN_ID;  V_COLUMN_NAME USER_TAB_COLS.COLUMN_NAME%TYPE;  V_COLUMN_ID   USER_TAB_COLS.COLUMN_ID%TYPE;    V_N_COLUMN_NAME_VALUE VARCHAR2(200);  V_O_COLUMN_NAME_VALUE VARCHAR2(200);BEGIN  --更新时写日志  IF UPDATING THEN    OPEN CUR_MEM_MEMBER_LOG_DATA;    LOOP      FETCH CUR_MEM_MEMBER_LOG_DATA        INTO V_COLUMN_NAME, V_COLUMN_ID;      EXIT WHEN CUR_MEM_MEMBER_LOG_DATA%NOTFOUND;      --有问题      --改成下面这样,但是需要注意表中的数据类型,最好在这个位置增加一个数据类型的判断      --如果是普通类型的没问题,varchar(200)可以,但是如果是日期类型的需要一个to_char函数转换      EXECUTE IMMEDIATE 'SELECT :NEW.'|| V_COLUMN_NAME||',:OLD.'||V_COLUMN_NAME||' FROM DUAL'                   INTO V_N_COLUMN_NAME_VALUE,V_O_COLUMN_NAME_VALUE;            IF V_N_COLUMN_NAME_VALUE <> V_O_COLUMN_NAME_VALUE THEN        INSERT INTO MEM_MEMBER_LOG          (MEMBER_LOG_ID,           MEMBER_ID,           MENMBER_FIELDS,           MENMBER_COUNT,           MEMBER_LOG_FLAG,           OPERATION_DATE)        VALUES          (SEQ_MEM_MEMBER_LOG.NEXTVAL,           :OLD.MEMBER_ID,           V_COLUMN_NAME,           ':OLD.' || V_COLUMN_NAME,           '2',           SYSDATE);      END IF;    END LOOP;    CLOSE CUR_MEM_MEMBER_LOG_DATA;  END IF;END TR_MEM_MEMBER_LOG;
[解决办法]
自己说明下,这里这么写有问题,犯了经验主义错误。
SQL code
--写了个脚本生成主要部分的代码,楼主还是一个一个写吧。DECLARE  CURSOR CUR_MEM_MEMBER_LOG_DATA IS    SELECT COLUMN_NAME, COLUMN_ID      FROM USER_TAB_COLS     WHERE TABLE_NAME = 'MEM_MEMBER'     ORDER BY COLUMN_ID;  V_COLUMN_NAME USER_TAB_COLS.COLUMN_NAME%TYPE;  V_COLUMN_ID   USER_TAB_COLS.COLUMN_ID%TYPE;  V_STRSQL LONG;BEGIN  OPEN CUR_MEM_MEMBER_LOG_DATA;  LOOP    FETCH CUR_MEM_MEMBER_LOG_DATA      INTO V_COLUMN_NAME, V_COLUMN_ID;    EXIT WHEN CUR_MEM_MEMBER_LOG_DATA%NOTFOUND;      V_STRSQL :=V_STRSQL||'      IF UPDATING('''||V_COLUMN_NAME||''') THEN '||        'INSERT INTO MEM_MEMBER_LOG '||          '(MEMBER_LOG_ID, '||          ' MEMBER_ID, '||          ' MENMBER_FIELDS, '||          ' MENMBER_COUNT, '||          ' MEMBER_LOG_FLAG, '||          ' OPERATION_DATE) '||       ' VALUES '||          ' (SEQ_MEM_MEMBER_LOG.NEXTVAL, '||          ' :OLD.MEMBER_ID, '||          ''''|| V_COLUMN_NAME||''','||          ' :OLD.'|| V_COLUMN_NAME||',' ||          ' ''2'', '||          '  SYSDATE); '||       ' END IF;';            END LOOP;  CLOSE CUR_MEM_MEMBER_LOG_DATA;    --这里动态生成触发器只要部分  EXECUTE IMMEDIATE 'CREATE OR REPLACE TRIGGER MY_TRIGGER '||                    'BEFORE UPDATE ON MEM_MEMBER '||                    'FOR EACH ROW '||                    'BEGIN '||                     V_STRSQL ||                    'END;'; END; 

热点排行