сложный выбор из курсора - PullRequest
0 голосов
/ 01 марта 2012

Предположим, у меня есть таблица conf с первичным ключом PK:

Conf
------------------
PK  A    B     C
------------------
1   Y    Y     Y
2   Y          Y
3   Y    
------------------

У меня есть другая таблица temp:

Temp
------------------
PK  A    B     C
------------------
1   ab   cd    ef
1   null cd    ef
2   cd         pq
3   dn    
------------------

Мне нужно извлечь все имена столбцов и PK из таблицы conf, имеющие значение Y, например:

1  A  B  C
2  A  C
3  A

Эти значения необходимо сравнить со temp строками таблицы и проверить, является ли значение извлеченного столбца пустым внутри этого столбца, и если это так, выдать ошибку.

Например, для 2 A C нам нужно сравнить столбцы A и C временной таблицы, имеющие 2 как PK.

У меня вопрос, как мне получить указанную ниже запись в курсоре:

1  A  B  C
2  A  C
3  A

Я не получаю оптимизированное решение для этого. Это можно сделать, сравнив все столбцы таблицы conf с таблицей temp, но их может быть больше 15.

Схема алгоритма:

fetch all column name from conf table having value 'Y'
loop
    fetch all the columns from temp table with primary key from outer cursor
    loop
        On the basis of column name from outer cursor check the value of column
        of temp table for its nullability 
    end loop;
end loop;

1 Ответ

2 голосов
/ 01 марта 2012

Я думаю, что лучше использовать запрос вроде:

select c.*, t.*
  from conf c, temp t
 where c.pk = t.pk
   and ((c.a = 'Y' and t.a is null) or (c.b = 'Y' and t.b is null) or
       (c.c = 'Y' and t.c is null))

если вы не знаете столбцы, вы можете создать запрос динамически, выполнив цикл user_tab_cols / all_tab_cols:

declare

  sql_str varchar2(32767);

  cursor c_col is
    select tc.column_name
      from user_tab_cols tc
     where tc.table_name = 'CONF' and tc.column_name <> 'PK';

  type rc_bad_rows is ref cursor;
  c_bad_rows rc_bad_rows;

  val number;

  is_first boolean := true;

begin

  sql_str := 'select t.pk from conf c, temp t ' ||
             'where c.pk = t.pk and (';

  for r in c_col loop

    if not is_first then
      sql_str := sql_str || ' or ';
    end if;

    is_first := false;

    sql_str := sql_str || '(c.' || r.column_name || ' = ''Y'' and t.' ||
               r.column_name || ' is null)';

  end loop;

  sql_str := sql_str || ')';

  dbms_output.put_line(sql_str);

  open c_bad_rows for sql_str;

  loop
    fetch c_bad_rows
      into val;
    exit when c_bad_rows%notfound;
    dbms_output.put_line(val);
  end loop;

  close c_bad_rows;
end;

Этот код может быть не лучшим, но это пример ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...