2015-01-21 2 views
1

Я работаю над кодом PL/SQL, где мне нужно выполнить запрос выбора, используя переменную в качестве имени столбца в where where. Имена столбцов хранятся в таблице как varchar, и я использую цикл для передачи этих имен столбцов в мой оператор select.переменная как имя столбца в where where в Oracle PL/SQL

Вы можете найти сегмент образца кода я пытаюсь запустить:

set serveroutput on; 

declare 
var varchar2(100); 
counter number; 
begin 

var:='description'; 
select count(*) 
into counter 
      from nodetable 
      where var like '%Ship%'; 

dbms_output.put_line(counter); 
end; 

Выход:

anonymous block completed 
0 

Однако результат должен быть 86. Oracle является сравнением последнего условия, как две строки, а не колонки = строка.

Пожалуйста, дайте мне знать, если это возможно в oracle, или если есть обходной путь для него.

С уважением Анкит

+0

_ «Имена столбцов хранятся в таблице как varchar» _ это довольно запутанно. Вы говорите, что у вас есть таблица, строки которой содержат имена столбцов другой таблицы? Также как и стандартный ['USER_TAB_COLUMNS'] (http://docs.oracle.com/cd/B19306_01/server.102/b14237/statviews_4462.htm#REFRN26277). Или что-то еще ? –

+0

Да, имена столбцов хранятся в другой таблице в виде строк, аналогичных стандартным user_tab_columns. – ankit

+0

Предложение WHERE в вашем примере не имеет ничего общего с информацией в упомянутой таблице, поэтому вы получаете неправильный результат. Каждое предложение WHERE/AND должно в какой-то момент ссылаться на имя столбца от объектов, перечисленных в предложении FROM. Ну, в базовом SQL это правда. Существуют более сложные утверждения, но это верно для вашего случая. – tvCa

ответ

4

Вы должны использовать динамический SQL, предпочтительно с связываемым-переменными:

EXECUTE IMMEDIATE 
    'select count(*) from nodetable where '||var||' like :p1' 
    INTO counter 
    USING '%Ship%'; 
0

Я согласился с предыдущим ответом в реализации, но я строго рекомендую вам изменить ваши технические требования, потому что вы не можете использовать переменные связывания для этого, и это потенциальное место для инъекций. Например, если кто-то отредактирует значение в вашей таблице, в котором хранятся имена столбцов, что-то вроде этого: «description = injection_function или description». Тогда ваш динамический SQL блок будет выполнять это заявление:

select count(*) from nodetable where description = inject_function or description like '%Ship% 

и пример реализации функции

create function inject_function 
return varchar2 
is pragma autonomous_transaction; 
begin 
    delete * from most_important_table; 
    commit; 
    return to_char(null); 
exception when others then 
    rollback; 
    return to_char(null); 
end; 
1

Попробуйте

declare 
var varchar2(100); 
counter number; 
begin 

var:='description'; 
EXECUTE IMMEDIATE 
'select count(*) 
into counter 
      from nodetable 
      where '||var||' like ''%Ship%'' '; 

dbms_output.put_line(counter); 
end; 

Вы должны быть осторожны с двоеточие (в ').

Смежные вопросы