Kar*_*tel 4 sql database testing oracle export
我想为我的Oracle数据库中的一行生成插入字符串,包括其他表中的所有依赖行(及其相关行).
例:
CREATE TABLE a (
a_id number PRIMARY KEY,
name varchar2(100)
);
CREATE TABLE b (
b_id number PRIMARY KEY,
a_id number REFERENCES a(a_id)
);
Run Code Online (Sandbox Code Playgroud)
当我从a_id = 1中提取行时,结果应该是该行和依赖行的插入字符串:
INSERT INTO a(a_id, name) VALUES (1, 'foo');
INSERT INTO b(b_id, a_id) VALUES (1, 1);
INSERT INTO b(b_id, a_id) VALUES (2, 1);
INSERT INTO b(b_id, a_id) VALUES (3, 1);
Run Code Online (Sandbox Code Playgroud)
我想要这样做的原因是,我有大型数据库,在那之间有许多不同的表和约束,我想提取一小部分数据作为测试数据.
Ste*_*erg 12
可能有一些工具已经完成,但是从起始表中任意提取所有行表本身就是一个小的开发任务.我不能为你写完整件事,但我可以让你开始 - 我开始写它,但大约20分钟后,我意识到这是一个更多的工作,我想承诺一个无偿的答案.
我可以通过递归的PL/SQL过程看到它做得最好,该过程将使用dbms_ouput和user_cons_columns&user_constraints为源表创建insert语句.您可以通过编写所有插入来作弊,就像列是char值一样,因为Oracle将隐式地将任何char值转换为正确的数据类型,假设您的NLS参数在源和目标系统上是相同的.
请注意,如果您的表中存在循环关系,则下面的包会出现问题; 此外,在早期版本的Oracle上,使用dbms_output可能会耗尽缓冲区空间.这两个问题都可以通过将生成的sql插入到sql上具有唯一索引的登台表中来解决,如果遇到唯一的密钥冲突则中止递归.下面的大节省时间是MakeParamList函数,它将返回列列表的游标转换为以逗号分隔的列表,或者将单个表达式转换为以逗号分隔的形式显示这些列的值(当作为针对表的查询中的select子句.
另请注意,在您进一步修改之后,以下包将无法正常工作(我停止编写它的原因之一):生成的初始insert语句基于以下假设:传入的constraint_vals参数将导致单行为生成 - 当然,一旦开始递归,这几乎肯定不是这种情况(因为父级会有很多子行).您需要将第一个语句(以及后续递归调用)的生成更改为循环内部,以处理对第一个EXECUTE IMMEDIATE调用的调用生成多行而不是单个行的情况.让它工作的基础是在这里,你只需要研究细节并使外部光标工作.
最后要注意的是:您不可能运行此过程来生成一组行,这些行在插入目标系统时会产生"干净"的数据集,因为尽管您将获得所有相关数据,数据可能取决于您未导入的其他表(例如,您遇到的第一个子表可能有其他外键指向与您的初始表无关的表).在这种情况下,您可能希望从详细信息表开始,而不是向下工作; 这样做,你也想要反转你生成的语句的顺序,或者使用脚本实用程序,或者像上面提到的那样将sql插入到临时表中,使用序列,然后用降序排序选择它.
至于调用它,您传递以逗号分隔的列列表以约束为constraint_cols,并将相应的逗号分隔值列表作为constraint_vals,例如:
exec Data_extractor.MakeInserts ('MYTABLE', 'COL1, COL2', '99, 105')
Run Code Online (Sandbox Code Playgroud)
这里是:
CREATE OR REPLACE PACKAGE data_extractor
IS
TYPE column_info IS RECORD(
column_name user_tab_columns.column_name%TYPE
);
TYPE column_info_cursor IS REF CURSOR
RETURN column_info;
FUNCTION makeparamlist(
column_info column_info_cursor
, get_values NUMBER
)
RETURN VARCHAR2;
PROCEDURE makeinserts(
source_table VARCHAR2
, constraint_cols VARCHAR2
, constraint_vals VARCHAR2
);
END data_extractor;
CREATE OR REPLACE PACKAGE BODY data_extractor
AS
FUNCTION makeparamlist(
column_info column_info_cursor
, get_values NUMBER
)
RETURN VARCHAR2
AS
BEGIN
DECLARE
column_name user_tab_columns.column_name%TYPE;
tempsql VARCHAR2(4000);
separator VARCHAR2(20);
BEGIN
IF get_values = 1
THEN
separator := ''''''''' || ';
ELSE
separator := '';
END IF;
LOOP
FETCH column_info
INTO column_name;
EXIT WHEN column_info%NOTFOUND;
tempsql := tempsql || separator || column_name;
IF get_values = 1
THEN
separator := ' || '''''', '''''' || ';
ELSE
separator := ', ';
END IF;
END LOOP;
IF get_values = 1
THEN
tempsql := tempsql || ' || ''''''''';
END IF;
RETURN tempsql;
END;
END;
PROCEDURE makeinserts(
source_table VARCHAR2
, constraint_cols VARCHAR2
, constraint_vals VARCHAR2
)
AS
BEGIN
DECLARE
basesql VARCHAR2(4000);
extractsql VARCHAR2(4000);
tempsql VARCHAR2(4000);
valuelist VARCHAR2(4000);
childconstraint_vals VARCHAR2(4000);
BEGIN
SELECT makeparamlist(CURSOR(SELECT column_name
FROM user_tab_columns
WHERE table_name = source_table), 0)
INTO tempsql
FROM DUAL;
basesql := 'INSERT INTO ' || source_table || '(' || tempsql || ') VALUES (';
SELECT makeparamlist(CURSOR(SELECT column_name
FROM user_tab_columns
WHERE table_name = source_table), 1)
INTO tempsql
FROM DUAL;
extractsql := 'SELECT ' || tempsql || ' FROM ' || source_table
|| ' WHERE (' || constraint_cols || ') = (SELECT '
|| constraint_vals || ' FROM DUAL)';
EXECUTE IMMEDIATE extractsql
INTO valuelist;
-- This prints out the insert statement for the root row
DBMS_OUTPUT.put_line(basesql || valuelist || ');');
-- Now we construct the constraint_vals parameter for subsequent calls:
SELECT makeparamlist(CURSOR( SELECT column_name
FROM user_cons_columns ucc
, user_constraints uc
WHERE uc.table_name = source_table
AND ucc.constraint_name = uc.constraint_name
ORDER BY position)
, 1)
INTO tempsql
FROM DUAL;
extractsql := 'SELECT ' || tempsql || ' FROM ' || source_table
|| ' WHERE ' || constraint_cols || ' = ' || constraint_vals;
EXECUTE IMMEDIATE extractsql
INTO childconstraint_vals;
childconstraint_vals := childconstraint_vals;
-- Now iterate over the dependent tables for this table
-- Cursor on this statement:
-- SELECT uc.table_name child_table, uc.constraint_name fk_name
-- FROM user_constraints uc
-- , user_constraints ucp
-- WHERE ucp.table_name = source_table
-- AND uc.r_constraint_name = ucp.constraint_name;
-- For each table in that statement, find the foreign key
-- columns that correspond to the rows
-- in the parent table
-- SELECT column_name
-- FROM user_cons_columns
-- WHERE constraint_name = fk_name
--ORDER BY POSITION;
-- Pass that columns into makeparamlist above to create
-- the constraint_cols argument of the call below:
-- makeinserts(child_table, ChildConstraint_cols, childconstrain_vals);
END;
END;
END data_extractor;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6944 次 |
| 最近记录: |