谢谢回复,不过还是没有解决我的问题,我现在用的就是动态SQL,我的需求是要在任意两SCHEMA之间拷贝全部表的数据,其中主键重复的记录要写入自己的LOG,主键不重复的要一次性拷贝并插入目标表.我的代码是
PROCEDURE COPY_DATA IS
pk_column_name
dba_cons_columns.column_name%TYPE;
TYPE cur_t_pk_columns
IS REF CURSOR;
cur_pk_columns
cur_t_pk_columns;
v_str_get_pk_column
VARCHAR2(2000);
v_str_log
VARCHAR2(3000);
--コピー元テーブルからのキー項目が重複しているレコードを取得するSQL文
v_str_insert
VARCHAR2(3000);
--コピー元テーブルからのキー項目が重複していないレコードを取得するSQL文
v_where_condition
VARCHAR2(2000); --キー項目が重複しているレコードに対する検索条件
keyExists
BOOLEAN := FALSE;
i
NUMBER := 0;
BEGIN
v_str_get_pk_column := 'SELECT col.column_name FROM dba_constraints c, dba_cons_columns col ' ||
' WHERE c.owner = ''' || UPPER(P_FROM_SCHEMA)
|| ''' AND c.table_name = ''' || tableName ||
''' AND constraint_type = ''P'' AND c.owner = col.owner '||' AND c.constraint_name = col.constraint_name ORDER BY col.position';
OPEN cur_pk_columns FORv_str_get_pk_column;
LOOP FETCHcur_pk_columnsINTO
pk_column_name;
EXIT WHEN
cur_pk_columns%NOTFOUND;
keyExists := TRUE;
i := i + 1;
--取得したキー項目によって、動的にキー項目に対する検索条件を生成する
IF i > 1 THEN
v_where_condition := v_where_condition || ' AND f.' || pk_column_name ||' = t.'|| pk_column_name;
ELSE
v_where_condition := ' f.' || pk_column_name || ' = t.'|| pk_column_name;
END IF;
END LOOP;
CLOSE cur_pk_columns;
IF keyExists = FALSE
THEN
--キー項目がない、コピー元テーブルの全部レコードコピー
v_str_insert:='INSERT INTO ' || P_TO_SCHEMA ||'.' || tableName || ' SELECT * FROM ' ||P_FROM_SCHEMA || '.' || tableName ;
ELSE
--コピー元テーブルからのキー項目が重複レコードを取得
v_str_log := 'SELECTf.* FROM ' ||P_FROM_SCHEMA || '.' || tableName || ' f ' || ' WHERE EXISTS(SELECT 1 FROM ' || P_TO_SCHEMA || '.' || tableName ||' t ' ||'WHERE ' || v_where_condition || ')';
--コピー元テーブルからのキー項目が重複ないレコードを取得
v_str_insert := 'INSERT INTO ' || P_TO_SCHEMA ||'.' || tableName || ' SELECT f.* FROM ' ||P_FROM_SCHEMA || '.' || tableName || ' f ' || ' WHERE NOTEXISTS(SELECT 1 FROM ' ||
P_TO_SCHEMA || '.' || tableName ||' t ' || 'WHERE ' || v_where_condition || ')';
END IF;
--コピー元スキーマからコピー先スキーマにテーブルのデータをコピーする
EXECUTE IMMEDIATE v_str_insert;
COMMIT;
IF keyExists = TRUE
THEN
EXECUTE IMMEDIATE v_str_log;
--UTL_FILE.PUT_LINE(log_file, ???????????);
END IF;
ENDCOPY_DATA;
现在拷贝没有问题,但带来的问题是无法将重复的记录取出并记入LOG.原因还是表名无法事先确定,因此如果%ROWTYPE前的基表名不能用变量的话,没法将重复记录取出记入LOG.
|