количество повторяющихся записей, передавая динамическое c имя таблицы и имена столбцов - PullRequest
1 голос
/ 22 апреля 2020

Спасибо за вашу помощь в Advance.

У меня есть требование выяснить, есть ли дубликаты выходов или нет во всех таблицах (более 100).

Я знаю SQL чтобы найти дубликаты по таблице за таблицей, но есть ли в любом случае, мы можем передать colu и таблицу при динамическом запуске sql.

имя таблицы и ключ col необходимо передать динамически

step1 : SQL чтобы получить все имена таблиц и связанный с ними ключ col шаг 2: запустить запрос дубликатов, выберите col1, col2, .... col5 count (1) из группы schema.tablename по col1, col2 ... col 5, имеющему count (1)> 1

Может кто-нибудь, пожалуйста, помогите мне избежать ручного запуска вручную по столбцам и именам таблиц.

Спасибо

1 Ответ

0 голосов
/ 22 апреля 2020

Вы можете создать свой скрипт 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;
/
...