Вы можете создать свой скрипт SQL, используя *_TAB_COLUMNS
view и LISTAGG
.
Например:
select
'select '||listagg(column_name, ',') within group (order by column_name)||
' from '||table_name||'
group by '||listagg(column_name, ',') within group (order by column_name)||'
having count(*) >1 ' str
from user_tab_columns where table_name = 'EMPLOYEES'
group by table_name;
Вывод вышеуказанного запроса для таблицы EMPLOYEES
в HR
схеме ( конечно отформатировал SQL) :
SELECT
commission_pct,
department_id,
email,
employee_id,
first_name,
hire_date,
job_id,
last_name,
manager_id,
phone_number,
salary
FROM
employees
GROUP BY
commission_pct,
department_id,
email,
employee_id,
first_name,
hire_date,
job_id,
last_name,
manager_id,
phone_number,
salary
HAVING
COUNT(*) > 1;
Чтобы l oop через все таблицы в схеме и сгенерировать ее для всех таблиц, вы может сделать что-то вроде:
DECLARE
TABLE_COLUMNS VARCHAR2(10000);
DELETE_STATEMENT VARCHAR2(10000);
CURSOR ALL_MY_TABLES IS (SELECT TABLE_NAME FROM USER_TABLES);
BEGIN
FOR MY_TABLE IN ALL_MY_TABLES
LOOP
-- prepare the list of columns
SELECT LISTAGG(COLUMN_NAME, ',') WITHIN GROUP (ORDER BY 1) INTO TABLE_COLUMNS FROM
USER_TAB_COLUMNS WHERE TABLE_NAME = 'YOUR_TABLE_NAME';
-- prepare the delete statements
DELETE_STATEMENT := 'DELETE FROM ' || YOUR_TABLE_NAME || ' WHERE ROWID NOT IN
(SELECT MIN(ROWID) FROM ' || YOUR_TABLE_NAME
|| ' GROUP BY ' || TABLE_COLUMNS ||');';
EXECUTE IMMEDIATE DELETE_STATEMENT;
-- output of all delete statements in loop
DBMS_OUTPUT.PUT_LINE(DELETE_STATEMENT);
END LOOP;
END;
/