2012-01-22 3 views
0

Я хотел бы спросить вас, как повысить производительность на вставке курсора в этом коде? Мне нужно использовать динамический plsql для извлечения данных, но не знаю, как улучшить INSERT наилучшим образом. например, Bulk Insert? Пожалуйста, дайте мне знать с примером кода, если это возможно.Повысить производительность при вставке курсора?

// Это как я использую cur_handle:

cur_HANDLE integer; 
cur_HANDLE := dbms_sql.open_cursor; 
DBMS_SQL.PARSE(cur_HANDLE, W_STMT, DBMS_SQL.NATIVE); 
DBMS_SQL.DESCRIBE_COLUMNS2(cur_HANDLE, W_NO_OF_COLS, W_DESC_TAB); 

LOOP 
-- Fetch a row 
IF DBMS_SQL.FETCH_ROWS(cur_HANDLE) > 0 THEN 
    DBMS_SQL.column_value(cur_HANDLE, 9, cont_ID); 
    DBMS_SQL.COLUMN_VALUE(cur_HANDLE, 3, proj_NR);  
ELSE 
    EXIT; 
END IF; 

    Insert into w_Contracts values(counter, cont_ID, proj_NR); 
counter := counter + 1; 
END LOOP; 
+0

Почему, по-вашему, вы должны использовать динамический SQL для курсора? Если вы хотите, чтобы мы вам помогли, вам нужно объяснить ваш прецедент. – APC

+0

Becouse select statement собирается с веб-сайта, например, если пользователь хочет включить более подробный поиск, то оператор select будет изменен, а результат будет выглядеть по-разному в конце. Все приложение представляет собой веб-сайт, основанный на динамическом коде PLSQL. – Haris

ответ

1

Вы должны делать действия базы данных в наборах по мере возможности, а не строка за строкой вставки. Вы не говорите нам, что CUR_HANDLE, поэтому я не могу переписать это, но вы должны, вероятно, сделать что-то вроде:

INSERT INTO w_contracts 
SELECT ROWNUM, cont_id, proj_nr 
    FROM (... some table or joined tables or whatever...) 

Хотя, если ваше первое значение есть первичный ключ, вероятно, было бы лучше назначить его из последовательности.

+0

Извините за недостающую информацию.Вот как я использую cur_handle: cur_HANDLE integer; - заявление cur_HANDLE: = dbms_sql.open_cursor; DBMS_SQL.PARSE (cur_HANDLE, W_STMT, DBMS_SQL.NATIVE); DBMS_SQL.DESCRIBE_COLUMNS2 (cur_HANDLE, W_NO_OF_COLS, W_DESC_TAB); – Haris

+0

Но что такое инструкция select для курсора? – eaolson

+0

W_STMT - это имя переменной оператора. – Haris

1

Решение 1) Вы можете заполнить внутри цикла в массив/PL SQL, а затем сразу же после цикла вставить весь массив в один шаг с помощью:

FORALL i in contracts_tab.first .. contracts_tab.last 
    INSERT INTO w_contracts VALUES contracts_tab(i); 

Решение 2) если v_stmt содержит действительный SQL заявление вы можете напрямую вставить данные в таблицу с помощью

EXECUTE IMMEDIATE 'INSERT INTO w_contracts (counter, cont_id, proj_nr) 
    SELECT rownum, 9, 3 FROM ('||v_stmt||')'; 
+0

Внутри существующего Loop? Я боюсь, что это сделает всю операцию медленнее, потому что она вставляет для каждой строки, которую она извлекает! – Haris

+0

Я пробовал решение 2 внутри Loop, но ничего не случилось. – Haris

0

«выберите оператор собирается из веб-сайта, если пользователь экс выбрать включать более точный поиск затем изменил оператор выбора и результат выглядит по-разному в конце. Все приложение является веб- сайт построить на динамичном код PLSQL.»

Это опасное положение, потому что он открывает свою базу данных для инъекции SQL. Это сценарий, в котором плохие люди подрывать ваши параметры, чтобы развернуть данные, которые они могут извлечь или увеличить привилегии. По крайней мере, вам нужно использовать DBMS_ASSERT для проверки ввода пользователя. Find out more.

Конечно, если вы разрешаете пользователям передавать целые строки SQL (вы не предоставили никаких информация о строительстве W_STMT), тогда все ставки отключены. DBMS_ASSERT вам не поможет.

Во всяком случае, как вы не смогли предоставить дополнительную информацию, которую мы на самом деле нужно, пожалуйста, дайте мне объяснить это для вас:

  • будет ЗЕЬЕСТ всегда одни и те же имена столбцов из одного имени таблицы, или может ли пользователь изменить эти два?
  • Вы всегда будете интересоваться третьей и девятой колоннами?
  • Какая строка W_STMT собрана? Сколько у вас контроля над проекцией?
Смежные вопросы