Как я могу запустить скрипт, сгенерированный из другого скрипта в Oracle DB?
Кто-нибудь знает, как самостоятельно выполнять все строки, сгенерированные из следующего запроса, как сценарии?
select 'DROP TABLE '||table_name||' CASCADE CONSTRAINTS;' from user_tables;
Что я в основном пытаюсь сделать, это удалить все пользовательские таблицы и ограничения в моей БД (это оракул). Вывод, который я получаю, правильный, но я хочу знать, как бы я выполнял все строки без копирования / вставки.
Кроме того, есть ли более эффективный способ отбросить все таблицы (включая ограничения)?
4 ответа
begin
for i in (select table_name from user_tables)
loop
execute immediate ('drop table ' || i.table_name || ' cascade constraints');
end loop;
end;
/
Джастин Кейв поднял замечательную мысль: ниже будут отброшены таблицы в схеме пользователя, начиная с самых внешних ветвей иерархии зависимостей, предполагая, что все внешние ключи ссылаются на первичный ключ, а не на уникальное ограничение. Таблицы без первичных ключей будут удалены последними.
begin
for i in (select parent_table, max(tree_depth) as tree_depth
from (select parent.table_name as parent_table,
child.constraint_name as foreign_key,
child.table_name as child_table,
LEVEL AS TREE_DEPTH
from (select table_name, constraint_name
from USER_constraints
where constraint_type = 'P'
) parent
LEFT JOIN
(SELECT TABLE_NAME, CONSTRAINT_NAME,
r_constraint_name
FROM USER_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'R') child
on parent.constraint_name =
child.r_constraint_name
CONNECT BY NOCYCLE
(PRIOR CHILD.TABLE_NAME = PARENT.TABLE_NAME)
UNION
select DT.table_name as parent_table,
NULL AS FOREIGN_KEY, NULL AS CHILD_TABLE,
0 AS TREE_DEPTH
FROM USER_TABLES DT
WHERE TABLE_NAME NOT IN
(SELECT TABLE_NAME
FROM USER_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'P')
)
group by parent_table
order by 2 desc
)
loop
execute immediate ('drop table ' || i.parent_table ||
' cascade constraints');
end loop;
end;
/
Быстрое и грязное решение было бы сделать что-то вроде
FOR x IN (SELECT * FROM user_tables)
LOOP
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ' || x.table_name ||
' CASCADE CONSTRAINTS';
EXCEPTION
WHEN others THEN
dbms_output.put_line( 'Failed to drop ' || x.table_name );
END;
END LOOP;
и запустить это несколько раз, пока все таблицы не будут удалены. Это займет несколько проходов, потому что вы не можете удалить родительскую таблицу, пока есть дочерние таблицы с внешними ключами, которые ссылаются на родительскую таблицу.
Более чистым вариантом было бы написать иерархический запрос к словарю данных, чтобы получить дочерние таблицы, родителей этих детей, бабушек и дедушек и т. Д. И пройтись по дереву, чтобы отбросить соответствующие объекты. Это должно избежать ошибок, но потребует немного больше работы для написания кода.
Как правило, при удалении таблиц более эффективно использовать оператор усечения.
Вы можете выполнять динамические сценарии, используя команду execute немедленный