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

发布于 2024-10-18 04:15:56 字数 492 浏览 0 评论 0原文

我有这个查询,但它没有更新到数据库中。给定的“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;

我之前没有写提交代码。只是为了清楚起见。

I have this query and it's not updating into the database. The given "where" clause is valid. When I run the query independently, it works fine but in this Procedure it's not working. There is no exception or no error. Could you guys help me in figuring out where the problem is?

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;

I didn't write the commit code before. Just to clarity.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

扭转时空 2024-10-25 04:15:56

我认为 col_id 是主键。因此,在 update 语句中

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;

为什么你不在工作结束时做出承诺呢?

I suppose that col_id is the primary key. So in the update statement

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

you are always updating at most one row and thus the condition

SQL%ROWCOUNT > 1

is never true ( 1 is not > 1 )

So if you don't have any other commit statement in your procedure, you will never commit those updates.

By the way: what is the purpose of this

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

why don't you just commit at the end of your work?

神仙妹妹 2024-10-25 04:15:56

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

例如,如果您不初始化 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;

The following code works okay (ie updates the row).
I suspect your error is elsewhere.

For example, if you don't initialise COUNTER, the increment will still leave it as null and it will never commit.

Or, l_vc_ColId may be the wrong datatype and suffering from an invalid conversion.

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;
李白 2024-10-25 04:15:56

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

更好地了解您的目标并使用绑定变量作为 where 条件。那么你可以使用 mod 或类似的方法提交每 x 行:

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

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

if SQL%ROWCOUNT > 1

永远不会是真的;

编辑:
一个了解“目标”表的简单示例:

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 文档中的显式绑定变量(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;
/

有关更多阅读,请参阅 此处

希望这有帮助,编码愉快

you may want to reconsider your design if your using dynamic sql to change the "dest" table in thousands of updates.

Much better to know your dest and use bind variables for the where conditions. then you can commit every x rows using mod or similar:

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

But for your example, Marcin is correct, if you are updating only 1 row at a time, then

if SQL%ROWCOUNT > 1

will never be true;

EDIT:
A simple example knowing your "dest" table:

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;

If using dynamic SQL, a simple example using explicit bind variables (USING clause) from Oracle docs:

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

For more reading, see here.

Hope this helps, happy coding

娇纵 2024-10-25 04:15:56

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

Execute immediate needs explicit commit. I guess you checked that ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文