【问题标题】:Oracle SQL%ROWCOUNT statement always return 1Oracle SQL%ROWCOUNT 语句总是返回 1
【发布时间】:2019-09-06 03:48:46
【问题描述】:

我在 Oracle 中有一个简单的表 USERS,有 2 列 IDUSERNAMEID 是主键,使用触发器自动递增。

我正在使用这样的过程插入或更新记录

CREATE OR REPLACE PROCEDURE SaveUser(UID NUMBER, UN VARCHAR2, Row_Count OUT NUMBER) IS
BEGIN
    IF(UID > 0) THEN
        UPDATE USERS SET USERNAME = UN WHERE ID = UID;
    ELSE
        INSERT INTO USERS(USERNAME) VALUES(UN);
    END IF;

    Row_Count := SQL%ROWCOUNT;
END;

我这样调用程序:

VARIABLE Row_Count NUMBER;
EXEC SaveUser(50, 'Username_1', Row_Count);
PRINT Row_Count;

问题是我将 50 作为第一个参数传递,但在表中没有ID 50 的行。但我得到了 1 作为结果。即使该行没有更新,SQL%ROWCOUNT 语句也会返回 1。谁能帮我解决这个问题?

上面的代码是简化的,具体代码在这里

CREATE OR REPLACE PROCEDURE SaveEmployee(ID NUMBER, User_Name VARCHAR2, Emp_Password VARCHAR2, Emp_Full_Name VARCHAR2, Emp_Date_Of_Birth DATE, Emp_Gender_ID NUMBER, Emp_Work_Type_ID NUMBER, Emp_Salary FLOAT, Emp_Email VARCHAR2, Row_Count OUT NUMBER) IS
    Username_Row_Count NUMBER := 0;
    Email_Row_Count NUMBER := 0;
BEGIN
    IF(ID > 0) THEN
        SELECT COUNT(1) INTO Username_Row_Count FROM EMPLOYEES WHERE LOWER(USERNAME) = LOWER(User_Name) AND EMPLOYEE_ID <> ID;
        SELECT COUNT(1) INTO Email_Row_Count FROM EMPLOYEES WHERE LOWER(EMAIL) = LOWER(Emp_Email) AND EMPLOYEE_ID <> ID;

        IF(Username_Row_Count = 0 AND Email_Row_Count = 0) THEN
            UPDATE EMPLOYEES
            SET USERNAME = LOWER(User_Name), PASSWORD = Emp_Password, FULL_NAME = Emp_Full_Name, DATE_OF_BIRTH = Emp_Date_Of_Birth, GENDER_ID = Emp_Gender_ID, WORK_TYPE_ID = Emp_Work_Type_ID, SALARY = Emp_Salary, EMAIL = LOWER(Emp_Email)
            WHERE EMPLOYEE_ID = ID;
        END IF;
    ELSE
        SELECT COUNT(1) INTO Username_Row_Count FROM EMPLOYEES WHERE LOWER(USERNAME) = LOWER(User_Name);
        SELECT COUNT(1) INTO Email_Row_Count FROM EMPLOYEES WHERE LOWER(EMAIL) = LOWER(Emp_Email);

        IF(Username_Row_Count = 0 AND Email_Row_Count = 0) THEN
            INSERT INTO EMPLOYEES(USERNAME, PASSWORD, FULL_NAME, DATE_OF_BIRTH, GENDER_ID, WORK_TYPE_ID, SALARY, EMAIL, LOGIN_ATTEMPTS)
            VALUES(LOWER(User_Name), Emp_Password, Emp_Full_Name, Emp_Date_Of_Birth, Emp_Gender_ID, Emp_Work_Type_ID, Emp_Salary, LOWER(Emp_Email), 0);
        END IF;
    END IF;

    Row_Count := SQL%ROWCOUNT;
END;

【问题讨论】:

  • 是您运行的实际程序,还是简化的程序?你确定没有 ID = 50 的行吗?
  • 这是一个简化的。是的,它确认没有 ID = 50 的行
  • 向我们展示真实的代码。问题出在您尚未发布的地方。
  • 用实际代码更新了问题

标签: oracle plsql oracle11g oracle10g


【解决方案1】:

我无法重现你所说的:

SQL> select * from users;

no rows selected

SQL> declare
  2    uid number := 50;
  3  begin
  4    if uid > 0 then
  5       update users set username = '&&un' where id = uid;
  6    else
  7       insert into users (username) values ('&&un');
  8    end if;
  9    dbms_output.put_line(sql%rowcount);
 10  end;
 11  /
Enter value for un: 50
0                              --> this is SQL%ROWCOUNT

PL/SQL procedure successfully completed.

SQL>

您发布的代码无效(没有NUBER 数据类型)。如果您发布了真正有效的内容,这将有所帮助,因为 - 正如您所说的那样 - 我们无法确定您声称的内容是否真的正确的。请复制/粘贴您自己的 SQL*Plus 会话(就像我所做的那样),以便我们了解您的真实情况以及 Oracle 的响应方式。

【讨论】:

  • 是的,你做到了。谢谢,但这还不够。请使用 SQL*Plus 会话。
  • 我已经添加了确切的程序并更新了问题
  • SQL%ROWCOUNT 你得到的也是 SELECT ,所以 - 虽然你没有更新任何东西,如果你运行的最后一个 SELECT 返回一行,你会得到“1”作为结果。不要在代码中使用 SQL%ROWCOUNT anywhere,而是在你真正需要的地方使用它(即检查你是否更新了某些东西)。
【解决方案2】:

更新后添加SQL%ROWCOUNT获取更新计数

UPDATE EMPLOYEES
            SET USERNAME = LOWER(User_Name), PASSWORD = Emp_Password, FULL_NAME = Emp_Full_Name, DATE_OF_BIRTH = Emp_Date_Of_Birth, GENDER_ID = Emp_Gender_ID, WORK_TYPE_ID = Emp_Work_Type_ID, SALARY = Emp_Salary, EMAIL = LOWER(Emp_Email)
            WHERE EMPLOYEE_ID = ID;
Row_Count := SQL%ROWCOUNT;

【讨论】:

    【解决方案3】:

    现在更清楚了。

    这段代码:

    SELECT COUNT(1) INTO Username_Row_Count FROM EMPLOYEES WHERE LOWER(USERNAME) = LOWER(User_Name) AND EMPLOYEE_ID <> ID;
    SELECT COUNT(1) INTO Email_Row_Count FROM EMPLOYEES WHERE LOWER(EMAIL) = LOWER(Emp_Email) AND EMPLOYEE_ID <> ID;
    

    必须更新Username_Row_CountEmail_Row_Count的值,使条件

    IF(Username_Row_Count = 0 AND Email_Row_Count = 0) THEN
    

    总是错误的。并且永远不会执行更新。结果,在您的 Row_Count 变量中,您将获得最后一次选择的结果,即 1 行。

    【讨论】:

    • 所以我必须在更新语句后立即添加SQL%ROWCOUNT 语句,在插入后添加另一个?
    • @A.M.Roomi,是的,这样会好很多。 在您实际对数据执行某些操作时更新此变量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-24
    • 1970-01-01
    • 2015-01-26
    • 2023-03-17
    • 2022-01-23
    • 2018-05-12
    • 2021-09-20
    相关资源
    最近更新 更多