Нужна помощь в выполнении запроса немедленного обновления - PullRequest
2 голосов
/ 17 февраля 2011

У меня есть этот запрос, и он не обновляется в базе данных. Данное предложение «где» действительно. Когда я запускаю запрос независимо, он работает нормально, но в этой процедуре он не работает. Нет исключений или ошибок. Не могли бы вы, ребята, помочь мне выяснить, где проблема?

EXECUTE IMMEDIATE 'UPDATE  ' || dest || ' SET COUNTRY_CODE = :v1 WHERE col_id = :v2'
          USING l_vc_CountryCode, l_vc_ColId;

if SQL%ROWCOUNT > 1 THEN
          inserts := inserts + 1;
          counter := counter + 1;
          IF counter > 500 THEN
            counter := 0;
            COMMIT;
          END IF;
        END IF;

Я не писал код коммита раньше. Просто для ясности.

Ответы [ 4 ]

2 голосов
/ 17 февраля 2011

Я полагаю, что col_id является первичным ключом. Так что в обновлении заявления

EXECUTE IMMEDIATE 'UPDATE  ' || dest || ' SET COUNTRY_CODE = :v1 WHERE col_id = :v2'
          USING l_vc_CountryCode, l_vc_ColId;

вы всегда обновляете не более одной строки и, следовательно, условие

SQL%ROWCOUNT > 1

никогда не соответствует действительности (1 не> 1)

Так что, если в вашей процедуре нет другого оператора фиксации, вы никогда не будете фиксировать эти обновления.

Кстати: какова цель этого

if SQL%ROWCOUNT > 1 THEN
          inserts := inserts + 1;
          counter := counter + 1;
          IF counter > 500 THEN
            counter := 0;
            COMMIT;
          END IF;
        END IF;

почему бы вам просто не сделать коммит в конце своей работы?

1 голос
/ 17 февраля 2011

вы можете пересмотреть свой дизайн, если вы используете динамический sql для изменения таблицы "dest" в тысячах обновлений.

Намного лучше узнать свое назначение и использовать переменные связывания для условий where.тогда вы можете фиксировать каждые x строк, используя мод или аналогичные:

if (mod(v_ctr, 1000) = 0) then
  commit;
end if;

Но для вашего примера Марцин прав, если вы обновляете только 1 строку за раз, тогда

if SQL%ROWCOUNT > 1

никогда не будет истинным;

РЕДАКТИРОВАТЬ: простой пример, зная вашу таблицу "dest":

declare

  cursor sel_cur is
  select col1, col2, from sourceTable where col3 = 'X';

  v_ctr pls_integer := 0;

begin
  for rec in sel_cur
  loop
    v_ctr := v_ctr + 1;

    -- implicit bind variables used
    update destTable
    set col1 = rec.col1,
        col2 = rec.col2
    where col3 = 'Z';

    if (mod(v_ctr, 1000) = 0) then
      commit;
    end if;

  end loop;

exception
  when others then rollback;
  raise;
end;

Если используется динамический SQL, простой пример с использованием явных переменных связывания (предложение USING)Документы Oracle:

CREATE OR REPLACE PROCEDURE raise_emp_salary (column_value NUMBER, 
                             emp_column VARCHAR2, amount NUMBER) IS
   v_column VARCHAR2(30);
   sql_stmt  VARCHAR2(200);
BEGIN
-- determine if a valid column name has been given as input
  SELECT COLUMN_NAME INTO v_column FROM USER_TAB_COLS 
    WHERE TABLE_NAME = 'EMPLOYEES' AND COLUMN_NAME = emp_column;
  sql_stmt := 'UPDATE employees SET salary = salary + :1 WHERE ' 
               || v_column || ' = :2';
  EXECUTE IMMEDIATE sql_stmt USING amount, column_value;
  IF SQL%ROWCOUNT > 0 THEN
    DBMS_OUTPUT.PUT_LINE('Salaries have been updated for: ' || emp_column 
                        || ' = ' || column_value);
  END IF;
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
    DBMS_OUTPUT.PUT_LINE ('Invalid Column: ' || emp_column);
END raise_emp_salary;
/

Для получения дополнительной информации см. здесь .

Надеюсь, это поможет, счастливое кодирование

1 голос
/ 17 февраля 2011

Следующий код работает нормально (т.е. обновляет строку).Я подозреваю, что ваша ошибка в другом месте.

Например, если вы не инициализируете COUNTER, приращение все равно останется нулевым и никогда не будет зафиксировано.

Или l_vc_ColId может быть неправильным типом данных и страдать от недопустимогоконвертация.

declare
  v_emp_id number := 7839;
  v_name varchar2(4) := 'DING';
  v_tab varchar2(3) := 'EMP';
begin
  execute immediate 'update '||v_tab||
                    ' set ename = :v_name Where empno = :v_emp_id'
     using v_name, v_emp_id;
  dbms_output.put_line('C:'||sql%rowcount);
end;
0 голосов
/ 17 февраля 2011

Выполнение немедленной необходимости явной фиксации.Я полагаю, вы это проверили?

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