用户层面
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;