当只有一条记录存在且符合条件时,出现 ORA-01422 错误

问题描述 投票:0回答:2

我正在尝试在 Oracle PL/SQL 过程中选择数据。当我像这样直接从表中选择数据时

SELECT * FROM CUSTOMER_USERS
 WHERE customer_id = 'cust1234'
   AND user_id = 'cust1234user'

我得到一行数据。

用户ID CUSTOMER_ID 描述 只读 更新_BY CUST_API_KEY LAST_ACCESS_DATE
cust1234用户 cust1234 1234公司 N jdoe [api_key] 3/19/2024 2:31:37 上午

但是,当我将相同的精确条件放入带有变量的查询中时,会导致错误,描述为“ORA-01422:精确获取返回的行数超过请求的行数。”

 customerID := 'cust1234';
 userID := 'cust1234user';
 SELECT CUST_API_KEY INTO v_encValue
   FROM CUSTOMER_USERS
  WHERE customer_id = customerID
    AND userid = userID;

怎么会发生这种事?这两列组成了 PK,因此根据该标准,该表中甚至不能有重复项。我不知道它认为额外的行是什么。

oracle stored-procedures plsql
2个回答
0
投票

这在文档中有解释:

如果 SQL 语句引用的名称既属于列又属于局部变量或形式参数,则列名称优先。

所以当你这样做时:

AND userid = userID
这两个 

userid

 参考文献均适用于表格列;两者都不适用于 PL/SQL 变量。因此,至少对于 
userid
 不为空的每一行,该条件评估为 true。请注意,默认情况下,稍微不同的情况没有什么区别;您只是通过在 
customer_id
customerID
 上添加下划线来避免同样的问题。

使 PL/SQL 变量名称与列名称不同。在变量前添加一些前缀(如

l_userid

)是很常见的。在存储的 PL/SQL 块中,您还可以使用块名称(例如过程名称)和表名称/别名来限定变量 - 有些人更喜欢这样做。


0
投票
当您使用标识符时,Oracle 将尝试从本地范围(在本例中为 SQL 查询)查找该标识符的值。如果没有找到,那么它将查看外部作用域中标识符的值(例如 PL/SQL 变量)。所以你的查询:

SELECT CUST_API_KEY INTO v_encValue FROM CUSTOMER_USERS WHERE customer_id = customerID AND userid = userID;
 实际上等同于:

SELECT CUST_API_KEY INTO v_encValue FROM CUSTOMER_USERS u WHERE u.customer_id = customerID AND u.userid = u.userID;
其中 

userID

 是列值,
NOT 是 PL/SQL 变量。

始终以与列标识符不同的方式命名变量。

© www.soinside.com 2019 - 2024. All rights reserved.