Oracle - 无法使用绑定变量更新表记录

Posted

技术标签:

【中文标题】Oracle - 无法使用绑定变量更新表记录【英文标题】:Oracle - Cannot update table record using bind variable 【发布时间】:2015-06-15 21:50:09 【问题描述】:

此查询返回 1 行:

SELECT col1, col2 FROM table1 WHERE col1 = :column1;

但这更新了 0 行:

UPDATE table1 SET col2 = :column2  WHERE col1 = :column1;
COMMIT;

我添加了这个约束来将 col1 设置为主键,但它没有修复它。

ALTER TABLE table1 ADD CONSTRAINT col1_pk PRIMARY KEY (col1);

我正在从 SQL Developer 尝试这个,知道为什么它不更新行吗?

编辑

col1 是VARCHAR2(32 BYTE) NOT NULL

col2 是CLOB NOT NULL

EDIT 2:测试用例,在选择和更新语句中设置 :var1 为 0011223344556677。

CREATE TABLE MY_TABLE 
   (    COL1 VARCHAR2(32 BYTE) NOT NULL ENABLE, 
    COL2 CLOB, 
     CONSTRAINT "MY_TABLE_PK" PRIMARY KEY ("COL1")
   )

INSERT INTO MY_TABLE (COL1, COL2) VALUES ('0011223344556677', '1434407992143440799214344079921434407992');

SELECT * FROM MY_TABLE WHERE COL1 = :var1;

UPDATE MY_TABLE SET COL2 = 'test' WHERE COL1 = :var1;
   COMMIT;

【问题讨论】:

某些东西无法追踪。如果select 返回单行,则update 将修改恰好1 行,假设它们在相同的上下文中运行。如果您的select 在它选择的行未提交的会话中运行,而update 在不同的会话中运行,则update 将看不到有问题的行。如果其他会话在 update 发生并提交更改之前删除了该行,则 update 将更新 0 行。不过,在某种程度上,提供一个显示该行实际上没有更新的测试用例会很有帮助。 如何确定update修改了0行?如果所有这些都在单个会话中完成并且select 返回一行,则两个语句的绑定变量值实际上不同,或者您实际上没有执行updateupdate 正在修改行,你错过了它。 感谢 @JustinCave,检查 Edit 2 中的测试用例。 SQL Developer 显示消息:“0 行已更新。提交完成。”在脚本输出中。我在同一个会话中使用相同的绑定变量值进行选择和更新。 你怎么知道绑定变量的值对于两个语句是一样的? 当我在 SQL Developer 中执行语句时,它会提示一个对话框输入绑定,在那里我输入 0011223344556677 for :var1 (实际上,sql developer 存储了这个值,所以我只需要输入一次)。你试过测试用例吗?它会更新您环境中的行吗? 【参考方案1】:

TL;DR - 确保存储在绑定变量中的值被解析为字符串而不是数字。

我已经在 SQL Developer(版本 4.0.3.16)中运行了这个:

CREATE TABLE MY_TABLE 
   (    COL1 VARCHAR2(32 BYTE) NOT NULL ENABLE, 
    COL2 CLOB, 
     CONSTRAINT "MY_TABLE_PK" PRIMARY KEY ("COL1")
   );
/
INSERT INTO MY_TABLE (COL1, COL2) VALUES ('0011223344556677', '1434407992143440799214344079921434407992');
/
VARIABLE var1 VARCHAR2(32);
/
BEGIN
  :var1 := '0011223344556677';
END;
/
SELECT * FROM MY_TABLE WHERE COL1 = :var1;
/
UPDATE MY_TABLE SET COL2 = 'test' WHERE COL1 = :var1;
/
COMMIT;
/
SELECT * FROM MY_TABLE;
/

它运行良好:

table MY_TABLE created.
1 rows inserted.
anonymous block completed
COL1                             COL2                                                                           
-------------------------------- --------------------------------------------------------------------------------
0011223344556677                 1434407992143440799214344079921434407992                                         

1 rows updated.
committed.
COL1                             COL2                                                                           
-------------------------------- --------------------------------------------------------------------------------
0011223344556677                 test                                                                             

如果将变量赋值更改为(去掉引号):

BEGIN
  :var1 := 0011223344556677;
END;

然后将值解析为数字,忽略前导零,输出为:

table MY_TABLE created.
1 rows inserted.
anonymous block completed
no rows selected


0 rows updated.
committed.
COL1                             COL2                                                                           
-------------------------------- --------------------------------------------------------------------------------
0011223344556677                 1434407992143440799214344079921434407992

【讨论】:

有没有办法在不声明 VARIABLE var1 的情况下做到这一点?必须有一种方法,因为我能够为 select 和 insert 语句做到这一点。 否 - 如果您使用 CTRL-ENTER 运行查询,则 SQL Developer 将隐式定义变量(可能没有正确的数据类型),但如果您使用 F5 作为脚本运行它,那么将告诉你绑定变量没有定义,你需要手动定义它(就像我做的那样)。 当我在 SQL Developer 中运行你的脚本时,虽然你定义了 var1 并设置了一个值,但它会提示一个对话框输入 var1 绑定,所以我输入 0011223344556677(不带引号)并正确更新行,但它对我不起作用,因为我不应该手动定义变量,因为我必须在 C 中使用 OCILIB 来执行此操作。 您可以使用准备好的语句在 OCILIB 中尝试它,看看它是否有效(它应该),如果无效,那么您可以在不同的问题中发布 OCILIB 源并询问。关于为什么当您手动输入值时 SQL 开发人员不执行您想要的操作,我没有明确的答案,但它可能是在某处对用户隐藏的影响相等比较的隐式类型转换使用 - 以编程方式执行,您可以定义类型,不要遇到问题。

以上是关于Oracle - 无法使用绑定变量更新表记录的主要内容,如果未能解决你的问题,请参考以下文章

Oracle中触发器内的select语句出现错误的绑定变量错误

在 to_date 函数中使用 cx_oracle 变量时无法正确绑定

无法使 PHP 更新功能正常工作

无法在 oracle SQL 开发人员中更新内部 if 条件

更新 oracle8i 数据库中我们无法使用正则表达式的记录

无法更新oracle sql表