请教高人:如何在%ROWTYPE声明时使用变量基表名

[复制链接]
查看11 | 回复7 | 2008-9-15 01:28:12 | 显示全部楼层 |阅读模式
我现在做一个数据库管理工具项目,其中需要将任意schema1下的任意table的数据拷贝到任意schema2下的同名同结构的table中,并且不能一条一条的拷贝,因此,我使用了BULK COLLECT,但在用%ROWTYPE声明中间TABLE时,由于基表名是变量,编译通不过。下面是我的代码:
CREATE OR REPLACE PROCEDURE DYNBULK
(P_FROM_SCHEMA
IN
VARCHAR2,

P_TO_SCHEMA
IN
VARCHAR2,
P_TABLE_NAME
IN
VARCHAR2
)
IS
TYPE t_tIS TABLE OF P_FROM_SCHEMA.P_TABLE_NAME%ROWTYPE;
t t_t;
BEGIN
SELECT *BULK COLLECT INTO tFROM P_FROM_SCHEMA.P_TABLE_NAME;
FORALLi in t.First..t.Last SAVE EXCEPTIONS
insert into P_TO_SCHEMA.P_TABLE_NAME values t(i);
END;
如果将参数P_FROM_SCHEMA,P_TO_SCHEMA,P_TABLE_NAME替换成实际的schema名称和表名则编译和运行都没有问题,但这不能达到目的,请教高人,怎样写才能编译通过并达到目的呢?
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
用动态SQL写COPY FROM很快!
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
好像只能用动态SQL写。copy form 只能在oracle PL/SQL执行
刚刚没事写了一下
DECLARE
p_table VARCHAR2(60);
p_des_table VARCHAR2(60);
n_ret NUMBER;
n_cursiridNUMBER;
v_selectVARCHAR2(2000);
BEGIN
p_table := 'xxx';
p_des_table := 'yyy';
n_cursirid:= dbms_sql.open_cursor;
v_select := 'create table ' || p_des_table || ' as select * from ' || p_table;
dbms_output.put_line(v_select);
dbms_sql.parse(n_cursirid, v_select, dbms_sql.v7);
n_ret := dbms_sql.EXECUTE(n_cursirid);
dbms_sql.close_cursor(n_cursirid);
END;
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
谢谢回复,不过还是没有解决我的问题,我现在用的就是动态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.
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
dwbdwb 发表于 2006-11-14 10:21
谢谢回复,不过还是没有解决我的问题,我现在用的就是动态SQL,我的需求是要在任意两SCHEMA之间拷贝全部表的数 ...

请教 如何解决P_FROM_SCHEMA.P_TABLE_NAME%ROWTYPE;
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
grandhappy 发表于 2013-4-19 21:02
请教 如何解决P_FROM_SCHEMA.P_TABLE_NAME%ROWTYPE;

必须构造一个动态PL/SQL块。
改用动态SQL: INSERT ... SELECT 就方便得多。
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
newkid 发表于 2013-4-19 23:00
必须构造一个动态PL/SQL块。
改用动态SQL: INSERT ... SELECT 就方便得多。

不是很明白 解释细致点
我用游标查出记录放在记录类型变量中
如果不定义记录类型变量 那我用什么接收游标查出来的记录呢???

回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
grandhappy 发表于 2013-4-23 11:21
不是很明白 解释细致点
我用游标查出记录放在记录类型变量中
如果不定义记录类型变量 那我用什么接收游 ...

版主的意思是用:insert into from....直接copy数据。
你的意思是,要记录重复id的log,没约束吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行