在执行立即更新查询时需要帮助

时间:2011-02-16 23:54:15

标签: oracle plsql

我有这个查询,它没有更新到数据库中。给定的“where”子句有效。当我独立运行查询时,它工作正常但在此过程中它不起作用。没有异常或没有错误。你能帮我解决问题所在吗?

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 个答案:

答案 0 :(得分:2)

我认为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 :(得分:1)

以下代码可以正常工作(即更新行)。 我怀疑你的错误在其他地方。

例如,如果你没有初始化COUNTER,增量仍会保留为null,它永远不会提交。

或者,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;

答案 2 :(得分:1)

如果您使用动态SQL在数千个更新中更改“dest”表,则可能需要重新考虑您的设计。

更好地了解你的dest并在where条件中使用绑定变量。那么你可以使用mod或类似的方式提交每个x行:

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

但是对于你的例子,Marcin是正确的,如果你一次只更新一行,那么

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,则使用Oracle docs中的显式绑定变量(USING子句)的简单示例:

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;
/

如需更多阅读,请参阅here

希望这有帮助,快乐编码

答案 3 :(得分:0)

执行立即需要显式提交。我想你检查过了吗?