我和this one有完全相同的问题,除了我在Oracle上运行而不是SQL-Server。
我有这样的结构:
[多边形
IdPolygon (Primary Key)
VertexA
VertexB
VertexC
[ FrontFaces
IdFace (Primary Key)
IdPolygon (Foreign Key)
FaceValue
[ LinesGroups
IdLinesGroup (Primary Key)
IdFace (Foreign Key)
LinesGroupValue
[行
IdLine (Primary Key)
IdLinesGroup (Foreign Key)
LineValue
[点
IdPoint (Primary Key)
IdLine (Foreign Key)
PointValue
这是一个想法:
有没有办法在不列出所有表/行的情况下执行此操作(基于外键搜索?)
答案 0 :(得分:1)
考虑这个问题:
with ri_tables as
(select parent, parent_key, child, foreign_key, min(ri_depth) as ri_depth
from (select parent, parent_key, child, foreign_key, level as ri_depth
from (select parent_table.table_name parent,
parent_constraint.constraint_name as parent_key,
child_table.table_name child,
child_constraint.constraint_name as foreign_key
from all_tables parent_table
inner join all_constraints parent_constraint
on parent_table.table_name = parent_constraint.table_name
inner join all_constraints child_constraint
on child_constraint.r_constraint_name = parent_constraint.constraint_name
inner join all_tables child_table
on child_table.table_name = child_constraint.table_name
where parent_constraint.constraint_type IN( 'P', 'U' )
and child_constraint.constraint_type = 'R'
and child_table.table_name != parent_table.table_name
)
start with parent = 'POLYGON'
connect by nocycle prior child = parent
)
group by parent, child, parent_key, foreign_key
)
select ri_tables.parent as source_table,
pc.column_name as source_key_column,
ri_tables.child as target_table,
cc.column_name as target_key_column,
pc.position as position
from ri_tables
inner join all_cons_columns pc
on ri_tables.parent = pc.table_name
and ri_tables.parent_key = pc.constraint_name
inner join all_cons_columns cc
on ri_tables.child = cc.table_name
and ri_tables.foreign_key = cc.constraint_name
and pc.position = cc.position
order by ri_tables.ri_depth, ri_tables.parent, ri_tables.child,
pc.position;
这将遍历外键层次结构,按顺序列出所有表依赖项,显示外键列如何链接到父项。
没有一种简单的方法可以构建所需的插入语句,而无需为正在复制数据的每个表拖拽user_tab_columns
。上面的SQL至少显示了您不需要复制哪些列,而是需要使用序列值。
当然,如果你有任何多列主键或外键,任何依赖于上述SQL的代码都会完全破坏。
我认为现在是时候考虑是否需要复制所有这些数据而不是要复制所有这些数据。在关系数据库中存在重复数据通常被认为是一个坏主意。
答案 1 :(得分:0)
给出一个表的名称我终于能够检索子表和将它们连接在一起的Primarary / Foreign Key
SELECT pk.table_name AS "Base Table", fk.table_name AS "Found Table", pc.column_name AS "Linking Key"
FROM all_constraints pk, all_constraints fk, all_cons_columns pc, all_cons_columns fc
WHERE pk.owner = pc.owner AND fk.owner = fc.owner
AND pk.constraint_name = pc.constraint_name AND fk.constraint_name = fc.constraint_name
AND fk.r_owner = pk.owner
AND fk.r_constraint_name = pk.constraint_name
AND pc.position = fc.position
AND pk.constraint_type IN ('P', 'U')
AND fk.constraint_type = 'R'
AND pk.owner = 'USER'
AND pk.table_name = 'FRONTFACES';
我的测试基础的结果是:
FRONTFACES
LINESGROUPS
IDFACE
但执行时间非常慢(大约8秒左右),如果有人可以帮助加快速度......
答案 2 :(得分:0)
好吧,我真的尝试自动获取外键,但是它确实在all_constraints
中搜索对于生产基地来说效率不高(在我的服务器上查询8到10秒)。
所以我写下了一个程序,列出了要用游标复制的所有表/字段,以获得多行及其子项:
CREATE OR REPLACE PROCEDURE DUPLICATEFACE_PRO
(
POLYGONID IN NUMBER DEFAULT 1
) AS
-- Declare variables to hold values from table columns
-- Table FrontFaces
FrontFaces_Old_idFace FrontFaces.idFace%TYPE;
FrontFaces_New_idFace FrontFaces.idFace%TYPE;
FrontFaces_FaceValue FrontFaces.FaceValue%TYPE;
-- Table LinesGroups
LinesGroups_Old_idLinesGroup LinesGroups.idLinesGroup%TYPE;
LinesGroups_New_idLinesGroup LinesGroups.idLinesGroup%TYPE;
LinesGroups_LinesGroupValue LinesGroups.LinesGroupValue%TYPE;
-- Table Lines
Lines_Old_idLine Lines.idLine%TYPE;
Lines_New_idLine Lines.idLine%TYPE;
Lines_LineValue Lines.LineValue%TYPE;
-- Table Points
Points_Old_idPoint Points.idPoint%TYPE;
Points_New_idPoint Points.idPoint%TYPE;
Points_PointValue Points.PointValue%TYPE;
-- Cursor to fill FrontFaces
-- Select each Face and Value Referencing POLYGONID from FrontFaces
CURSOR C1 IS select a.facevalue, a.idface
from frontfaces a
where a.idpolygon = POLYGONID
AND ROWNUM = 1;
-- Cursor to fill LinesGroups
-- Select each LinesGroup and Value Referencing Old_idFace from LinesGroups
CURSOR C2 IS select a.LinesGroupValue, a.idLinesGroup
from LinesGroups a
where a.idFace = frontfaces_old_idface;
-- Cursor to fill Lines
-- Select each Line and Value Referencing Old_idLinesGroup from Lines
CURSOR C3 IS select a.LineValue, a.idLine
from Lines a
where a.idLinesGroup = linesgroups_old_idlinesgroup;
-- Cursor to fill Points
-- Select each Point and Value Referencing Old_idLine from Points
CURSOR C4 IS select a.PointValue, a.idPoint
from Points a
where a.idLine = lines_old_idline;
BEGIN
OPEN C1;
LOOP
-- Put Select results in variables
FETCH C1 INTO FrontFaces_FaceValue, FrontFaces_Old_idFace;
EXIT WHEN C1%NOTFOUND;
-- Put the next free id in a variable
FrontFaces_New_idFace := frontfaces_seq.nextval;
-- Create a new row with same FaceValue and Reference to POLYGONID
INSERT INTO FrontFaces(idFace, idPolygon, FaceValue)
VALUES(FrontFaces_New_idFace, POLYGONID, FrontFaces_FaceValue);
dbms_output.put_line('New row with FaceValue = ' || FrontFaces_FaceValue || ' & New_Id ' || FrontFaces_New_idFace || ' & POLYGONID ' || POLYGONID);
-- Start another Cursor to fill LinesGroups
OPEN C2;
LOOP
-- Put Select results in variables
FETCH C2 INTO LinesGroups_LinesGroupValue, LinesGroups_Old_idLinesGroup;
EXIT WHEN C2%NOTFOUND;
-- Put the next free id in a variable
LinesGroups_New_idLinesGroup := linesgroups_seq.nextval;
-- Create a new row with same LinesGroupValue and Reference to New_idFace
INSERT INTO LinesGroups(idLinesGroup, idFace, LinesGroupValue)
VALUES(LinesGroups_New_idLinesGroup, FrontFaces_New_idFace, LinesGroups_LinesGroupValue);
dbms_output.put_line('New row with LinesGroupValue = ' || LinesGroups_LinesGroupValue || ' & New_Id ' || LinesGroups_New_idLinesGroup || ' & New_idFace ' || FrontFaces_New_idFace);
-- Start another Cursor to fill Lines
OPEN C3;
LOOP
-- Put Select results in variables
FETCH C3 INTO Lines_LineValue, Lines_Old_idLine;
EXIT WHEN C3%NOTFOUND;
-- Put the next free id in a variable
Lines_New_idLine := lines_seq.nextval;
-- Create a new row with same LineValue and Reference to New_idLinesGroup
INSERT INTO Lines(idLine, idLinesGroup, LineValue)
VALUES(Lines_New_idLine, LinesGroups_New_idLinesGroup, Lines_LineValue);
dbms_output.put_line('New row with LineValue = ' || Lines_LineValue || ' & New_Id ' || Lines_New_idLine || ' & New_idLinesGroup ' || LinesGroups_New_idLinesGroup);
-- Start another Cursor to fill Lines
OPEN C4;
LOOP
-- Put Select results in variables
FETCH C4 INTO Points_PointValue, Points_Old_idPoint;
EXIT WHEN C4%NOTFOUND;
-- Put the next free id in a variable
Points_New_idPoint := points_seq.nextval;
-- Create a new row with same LineValue and Reference to New_idLinesGroup
INSERT INTO Points(idPoint, idLine, PointValue)
VALUES(Points_New_idPoint, Lines_New_idLine, Points_PointValue);
dbms_output.put_line('New row with PointValue = ' || points_pointvalue || ' & New_Id ' || Points_New_idPoint || ' & New_idLine ' || Lines_New_idLine);
END LOOP;
CLOSE C4;
END LOOP;
CLOSE C3;
END LOOP;
CLOSE C2;
END LOOP;
CLOSE C1;
END DUPLICATEFACE_PRO;