powered by simpleCommunicator - 2.0.30     © 2024 Programmizd 02
Map
Форумы / Informix [игнор отключен] [закрыт для гостей] / Простой способ определения наличия ссылок?
8 сообщений из 8, страница 1 из 1
Простой способ определения наличия ссылок?
    #38710693
NetSpider
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, форумчане!
Возникла задачка сделать выборку записей, на которые ни кто (ни какая другая таблица) не ссылается...
сначала, хотел сделать как обычно:
Код: sql
1.
2.
3.
select * from main_tab where key_id not in (select key_id from ref_tab1);
-- или
select * from main_tab m where not exists (select r.key_id from ref_tab1 r where r.key_id = m.key_id);



проблема только в том, что таблиц, подобных ref_tab1 несколько десятков.

Вопрос: есть-ли какой-то более хитрый (оптимальный) способ, сделать подобную выборку, способ доступный для использования в простом запросе.

БД: IBM Informix Dynamic Server Version 11.50.FC9
...
Рейтинг: 0 / 0
Простой способ определения наличия ссылок?
    #38711380
victor16
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
NetSpiderсделать выборку записей, на которые ни кто (ни какая другая таблица) не ссылается... таблиц, подобных ref_tab1 несколько десятков...
другого способа нет, кроме как обойти все эти detail-таблицы
Код: sql
1.
2.
3.
4.
5.
select * from main_tab 
where key_id not in (select key_id from ref_tab1)
   and key_id not in (select key_id from ref_tab2)
   and key_id not in (select key_id from ref_tab3)
... /* повторяем для всех detail-таблиц */ ...


или
Код: sql
1.
2.
3.
4.
5.
select * from main_tab m 
where not exists (select r.key_id from ref_tab1 r where r.key_id = m.key_id)
  and not exists (select r.key_id from ref_tab2 r where r.key_id = m.key_id)
  and not exists (select r.key_id from ref_tab3 r where r.key_id = m.key_id)
... /* повторяем для всех detail-таблиц */ ...



Если никакой другой задачи не стоит, кроме как выбрать - этого селекта будет достаточно.
Другой вопрос - как определить эти несколько десятков detail-таблиц, которые ссылаются на эту таблицу. Можно начать примерно с такого запроса:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
SELECT master.tabname mastertable,
       "->",
       slave.tabname slavetable,
" and not exists (select 1 from " || trim(master.tabname) || 
" where " || trim(get_join_str(sysreferences.constrid)) || ");"
FROM sysreferences,
       systables master,
       sysconstraints masterconstr,
       systables slave,
       sysconstraints slaveconstr,
       outer sysconstraints slaveprim
 WHERE slaveconstr.constrid = sysreferences.constrid
and lower(master.tabname) = lower("<tabname>")  
   AND master.tabid = sysreferences.ptabid
   AND masterconstr.constrid = sysreferences.primary
   AND slave.tabid = slaveconstr.tabid
   AND masterconstr.tabid = master.tabid
   AND slaveprim.tabid = slave.tabid
   AND slaveprim.constrtype = "P"
ORDER BY 1,2;


get_join_str - это функция, возвращающая строку соединения
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
EXECUTE PROCEDURE ifx_allow_newline('t');
create procedure get_join_str(p_constrid INT)
 returning lvarchar;
 define p_join_str lvarchar;
 define p_master_idxname lvarchar;
 define p_master_tabname lvarchar;
 define p_master_tabid integer;
 define p_slave_idxname lvarchar;
 define p_slave_tabname lvarchar;
 define p_slave_tabid integer;
 define p_idxcolno integer;
 define p_master_colname lvarchar;
 define p_master_colno lvarchar;
 define p_slave_colname lvarchar;
 define p_slave_colno lvarchar;

 SELECT masterconstr.idxname, master.tabname, master.tabid, slaveconstr.idxname, slave.tabname, slave.tabid
   INTO p_master_idxname, p_master_tabname, p_master_tabid, p_slave_idxname, p_slave_tabname, p_slave_tabid
   FROM sysreferences,
        systables master,
        sysconstraints masterconstr,
        systables slave,
        sysconstraints slaveconstr
  WHERE slaveconstr.constrid = sysreferences.constrid
    AND sysreferences.constrid = p_constrid
    AND master.tabid = sysreferences.ptabid
    AND masterconstr.constrid = sysreferences.primary
    AND slave.tabid = slaveconstr.tabid
    AND masterconstr.tabid = master.tabid;

 LET p_join_str = "";
 LET p_idxcolno = 0;
 LOOP
     SELECT ikeyextractcolno(indexkeys, p_idxcolno) INTO p_master_colno FROM sysindices WHERE sysindices.idxname == p_master_idxname;
     SELECT ikeyextractcolno(indexkeys, p_idxcolno) INTO p_slave_colno FROM sysindices WHERE sysindices.idxname == p_slave_idxname;
     IF p_master_colno == 0 OR p_slave_colno == 0 THEN
        EXIT LOOP;
     END IF;
     LET p_idxcolno = p_idxcolno + 1;
     SELECT colname INTO p_master_colname FROM syscolumns
      WHERE tabid = p_master_tabid AND colno = p_master_colno;
     SELECT colname INTO p_slave_colname FROM syscolumns
      WHERE tabid = p_slave_tabid AND colno = p_slave_colno;
     IF LENGTH(p_join_str) > 0 THEN
        LET p_join_str = trim(p_join_str) || "
AND ";
     END IF;
     LET p_join_str = trim(p_join_str) || " " || trim(p_master_tabname) || "." || trim(p_master_colname) ||
                                    " = " || trim(p_slave_tabname) || "." || trim(p_slave_colname);
 END LOOP;

 LET p_join_str = trim(p_join_str);
 return p_join_str;
end procedure;
EXECUTE PROCEDURE ifx_allow_newline('f');
...
Рейтинг: 0 / 0
Простой способ определения наличия ссылок?
    #38711958
NetSpider
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Большое спасибо за ответ!
Обошелся exists'ами, благо список ссылающихся таблиц определить трудностей не составило.
Только выполнять пришлось не весь запрос разом (чтобы не ждать его выполнения пол дня), а разделить на неск. частей прогоняя через вр. таблицы.

Отдельное спасибо за процедурку!))
...
Рейтинг: 0 / 0
Простой способ определения наличия ссылок?
    #38712053
Фотография Журавлев Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
select * from main_tab a left outer join second_t b on a.f=b.f left outer join third_t c on a.f=c.f where b.f is null and c.f is null

a b c
1 1 1
2 2 2
3 3
4
...
Рейтинг: 0 / 0
Простой способ определения наличия ссылок?
    #38712959
NetSpider
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Журавлев Денисselect * from main_tab a left outer join second_t b on a.f=b.f left outer join third_t c on a.f=c.f where b.f is null and c.f is null

a b c
1 1 1
2 2 2
3 3
4

хм... тоже интересный вариант, попробовал на неск. таблицах - даже вроде как быстрее)) Спасибо за подсказку!

Перейдя на информикс совсем стал забывать про *join*, хотя не думаю, что тут виноват информикс))
...
Рейтинг: 0 / 0
Простой способ определения наличия ссылок?
    #38713136
Фотография Журавлев Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NetSpiderПерейдя на информикс совсем стал забывать про *join*, хотя не думаю, что тут виноват информикс))
я предлагал один запросом заджойнить все таблицы, чтобы в main_tab зайти один раз.

по идее в идеальном сферическом оптимизаторе это ничем не отличается от варианта

select * from main_tab m where
not exists (select r.key_id from ref_tab1 r where r.key_id = m.key_id) and
not exists (select r.key_id from ref_tab2 r where r.key_id = m.key_id) and
not exists (select r.key_id from ref_tab3 r where r.key_id = m.key_id) and
not exists (select r.key_id from ref_tab4 r where r.key_id = m.key_id) and
...
Рейтинг: 0 / 0
Простой способ определения наличия ссылок?
    #38713139
Фотография Журавлев Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NetSpider
Перейдя на информикс совсем стал забывать про *join*, хотя не думаю, что тут виноват информикс))
кажись "родной" синтаксис информикса не позволяет пометить предикат post-join или pre-join поэтому без анси-ситаксиса не обойтись
...
Рейтинг: 0 / 0
Простой способ определения наличия ссылок?
    #38719197
NetSpider
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Журавлев ДенисNetSpiderПерейдя на информикс совсем стал забывать про *join*, хотя не думаю, что тут виноват информикс))
кажись "родной" синтаксис информикса не позволяет пометить предикат post-join или pre-join поэтому без анси-ситаксиса не обойтись

Используя Informix-Extension Outer Joins, результата, подобного ANSI-join, добиться не удалось, что в принципе, не удивительно...
Так что - да, либо без join'ов либо ansi

Если я Вас правильно понимаю))
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Informix [игнор отключен] [закрыт для гостей] / Простой способ определения наличия ссылок?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]