开启补充日志

用户层面

bash 复制代码
CREATE OR REPLACE PROCEDURE enable_supplemental_log_for_user(
    p_username VARCHAR2
) AS
    v_username VARCHAR2(30);
    v_total_count NUMBER := 0;
    v_success_count NUMBER := 0;
    v_error_count NUMBER := 0;
    v_error_log VARCHAR2(4000) := '';
    v_sql VARCHAR2(1000);
    v_start_time TIMESTAMP;
    v_end_time TIMESTAMP;
    
    -- 定义日志类型常量
    TYPE log_type_rec IS RECORD (
        type_name VARCHAR2(30),
        type_clause VARCHAR2(50)
    );
    TYPE log_type_table IS TABLE OF log_type_rec;
    v_log_types log_type_table := log_type_table(
        log_type_rec('PRIMARY KEY', 'PRIMARY KEY'),
        log_type_rec('UNIQUE INDEX', 'UNIQUE INDEX'),
        log_type_rec('FOREIGN KEY', 'FOREIGN KEY'),
        log_type_rec('ALL COLUMNS', 'ALL')
    );
    
    -- 获取用户所有表的游标
    CURSOR c_tables IS
        SELECT table_name 
        FROM all_tables 
        WHERE owner = v_username
        AND table_name NOT LIKE 'BIN$%'      -- 排除回收站表
        AND table_name NOT LIKE 'MLOG$%'     -- 排除物化视图日志
        AND table_name NOT LIKE 'RUPD$%'     -- 排除升级表
        AND table_name NOT LIKE 'AQ$%'       -- 排除高级队列表
        AND table_name NOT LIKE 'DR$%'       -- 排除Oracle Text索引表
        ORDER BY table_name;
    
    -- 定义存储过程记录错误信息
    PROCEDURE log_error(p_table_name VARCHAR2, p_log_type VARCHAR2, p_error_msg VARCHAR2) IS
    BEGIN
        v_error_count := v_error_count + 1;
        v_error_log := v_error_log || 'Table: ' || p_table_name || 
                       ', Type: ' || p_log_type || 
                       ', Error: ' || p_error_msg || CHR(10);
    END;
    
BEGIN
    -- 转换用户名为大写
    v_username := UPPER(p_username);
    v_start_time := SYSTIMESTAMP;
    
    -- 检查用户是否存在
    BEGIN
        SELECT 1 INTO v_total_count 
        FROM all_users 
        WHERE username = v_username;
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            RAISE_APPLICATION_ERROR(-20001, 'User ' || p_username || ' does not exist');
    END;
    
    DBMS_OUTPUT.PUT_LINE('============================================================');
    DBMS_OUTPUT.PUT_LINE('Starting supplemental log configuration for user: ' || v_username);
    DBMS_OUTPUT.PUT_LINE('============================================================');
    DBMS_OUTPUT.PUT_LINE('Log types to be enabled: PRIMARY KEY, UNIQUE INDEX, FOREIGN KEY, ALL');
    DBMS_OUTPUT.PUT_LINE('------------------------------------------------------------');
    
    -- 遍历用户所有表
    FOR r_table IN c_tables LOOP
        DBMS_OUTPUT.PUT_LINE('Processing table: ' || r_table.table_name);
        
        -- 为每种日志类型启用
        FOR i IN 1..v_log_types.COUNT LOOP
            BEGIN
                -- 构建SQL语句
                IF v_log_types(i).type_name = 'ALL COLUMNS' THEN
                    v_sql := 'ALTER TABLE ' || v_username || '.' || r_table.table_name || 
                             ' ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS';
                ELSE
                    v_sql := 'ALTER TABLE ' || v_username || '.' || r_table.table_name || 
                             ' ADD SUPPLEMENTAL LOG DATA (' || v_log_types(i).type_clause || ') COLUMNS';
                END IF;
                
                -- 执行SQL
                EXECUTE IMMEDIATE v_sql;
                v_success_count := v_success_count + 1;
                
                DBMS_OUTPUT.PUT_LINE('  ✓ ' || RPAD(v_log_types(i).type_name, 15) || ' - Success');
                
            EXCEPTION
                WHEN OTHERS THEN
                    -- 处理已存在的错误(ORA-32588)
                    IF SQLCODE = -32588 THEN
                        DBMS_OUTPUT.PUT_LINE('  - ' || RPAD(v_log_types(i).type_name, 15) || ' - Already exists');
                        v_success_count := v_success_count + 1;  -- 已存在也算成功
                    ELSE
                        log_error(r_table.table_name, v_log_types(i).type_name, SQLERRM);
                        DBMS_OUTPUT.PUT_LINE('  ✗ ' || RPAD(v_log_types(i).type_name, 15) || ' - Error: ' || SQLERRM);
                    END IF;
            END;
        END LOOP;
        DBMS_OUTPUT.PUT_LINE('---');
    END LOOP;
    
    v_end_time := SYSTIMESTAMP;
    
    -- 输出总结报告
    DBMS_OUTPUT.PUT_LINE('============================================================');
    DBMS_OUTPUT.PUT_LINE('Configuration Summary:');
    DBMS_OUTPUT.PUT_LINE('============================================================');
    DBMS_OUTPUT.PUT_LINE('User: ' || v_username);
    DBMS_OUTPUT.PUT_LINE('Total operations: ' || (v_success_count + v_error_count));
    DBMS_OUTPUT.PUT_LINE('Successful: ' || v_success_count);
    DBMS_OUTPUT.PUT_LINE('Failed: ' || v_error_count);
    DBMS_OUTPUT.PUT_LINE('Duration: ' || 
        ROUND(EXTRACT(SECOND FROM (v_end_time - v_start_time)), 2) || ' seconds');
    
    -- 如果有错误,输出详细信息
    IF v_error_count > 0 THEN
        DBMS_OUTPUT.PUT_LINE('------------------------------------------------------------');
        DBMS_OUTPUT.PUT_LINE('Error Details:');
        DBMS_OUTPUT.PUT_LINE(v_error_log);
    END IF;
    
    DBMS_OUTPUT.PUT_LINE('============================================================');
    DBMS_OUTPUT.PUT_LINE('Process completed successfully!');
    
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Fatal error occurred: ' || SQLERRM);
        DBMS_OUTPUT.PUT_LINE('Error code: ' || SQLCODE);
        RAISE;
END;
/



-- 检查存储过程是否存在
SELECT object_name, object_type, status
FROM user_objects
WHERE object_name = 'ENABLE_SUPPLEMENTAL_LOG_FOR_USER'
AND object_type = 'PROCEDURE';

-- 如果存在,会显示一行记录,status应为VALID



-- 设置输出显示
SET SERVEROUTPUT ON SIZE UNLIMITED;

-- 执行存储过程
EXEC enable_supplemental_log_for_user('TEST');

select log_group_type from dba_log_groups where owner='ECIFNOR' AND

table_name=CODE_STRING_GOLDEN;

相关推荐
Flynn Liang9 分钟前
可观测性与成本治理:一次对话的 17 个观测点
java·langchain·可观测性·micrometer·langchain4j·token 成本·llm 监控
金銀銅鐵28 分钟前
带您看懂字节码指令(三):同一行加法,为什么有四种指令
java·jvm
another heaven3 小时前
【C/C++ Ranges 是零开销抽象吗?拆开管道、惰性求值和编译期膨胀】
c语言·开发语言·c++
文丑颜不良啊4 小时前
LeetCode2821~2840题目解析
java·leetcode
SomeOtherTime5 小时前
Rust 闭包语法和原理(AI回答)
开发语言·后端·rust
apcipot_rain5 小时前
C++转Java日记(10)
java·开发语言
总要学点什么6 小时前
第105篇:三维特效-流动图片墙体效果——让箭头沿墙长滚,它俩竟是同一份代码
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
简 洁 冬冬6 小时前
泛型方法写法全面辨析:从「能编译」到「能跑」到「能用」
java·泛型
LGL6030A6 小时前
Java学习历程31——初识Spring Boot
java·spring boot·学习
xiaoye-duck6 小时前
《C++ 项目:手写大模型接入 SDK》会话模块整合:内存 SessionManager 与 DataManager 持久化联动
开发语言·数据库·c++·语言模型