ORA-01779: 无法修改与非键值保存表对应的列

本文详细介绍了在使用Oracle进行数据更新时遇到ORA-01779错误的原因及解决方案,通过实例展示了如何正确设置主键以避免该错误,并深入分析了Oracle在此操作中确保数据唯一性的机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. <span style="font-size:18px;">项目中通过子查询更新数据时遇到<span style="color: rgb(255, 0, 0); ">ORA-01779: 无法修改与非键值保存表对应的列</span>,模拟过程如下:</span>  

1、创建测试表

  1. CREATE TABLE tt1 (ID INT,col1 VARCHAR2(20));  
  2. CREATE TABLE tt2 (ID INT,cola VARCHAR2(20));  

2、录入测试数据

  1. INSERT INTO tt1 VALUES(1,'tt1id1');  
  2. INSERT INTO tt1 VALUES(2,'tt1id2');  
  3. INSERT INTO tt2 VALUES(1,'tt2id1');  
  4. INSERT INTO tt2 VALUES(2,'tt2id2');  
  5. INSERT INTO tt1 VALUES(3,'tt1id3');  
  6. INSERT INTO tt2 VALUES(4,'tt2id4');  
  7. COMMIT;  
3、执行更新

  1. UPDATE (SELECT tt1.col1 ,tt2.cola,tt1.id,tt2.id FROM tt1,tt2 WHERE  tt1.ID=tt2.ID)  
  2. SET col1=cola;  
       报错:ORA-01779: 无法修改与非键值保存表对应的列

4、分析

      根据错误提示:”无法修改与非键值保存表对应的列”,初步推断为tt2中没有主键?

      那么在tt2上添加主键后再更新试试

  1. ALTER TABLE tt2 ADD CONSTRAINT pk_tt2_id PRIMARY KEY(ID);  
  2.   
  3. UPDATE (SELECT tt1.col1 ,tt2.cola,tt1.id,tt2.id FROM tt1,tt2 WHERE  tt1.ID=tt2.ID)  
  4. SET col1=cola;  
      发现可以成功更新数据。

      然后将在tt2上加的主键删除,再在tt1上添加主键试试, 

  1. ALTER TABLE tt2 DROP CONSTRAINT pk_tt2_id;  
  2. ALTER TABLE tt1 ADD CONSTRAINT pk_tt1_id PRIMARY KEY(ID);  
      再执行第3 步中的更新语句,发现还是报错:ORA-01779: 无法修改与非键值保存表对应的列

5、结论:

      用A表去更新B表的数据,A表的关联条件必须为主键,Oracle这样做的目的是保证表A的满足关联条件的数据是唯一的,

      这样在更新B表数据时才有意义(自己都不确定怎么影响别人,是吧,hehe),

      当然,如果两表关联的字段都为主键,则无论谁更新谁都没有问题。

      结论:用A表数据更新B表数据,则A与B的对应关系为:1:1 或 1:n。

### Oracle `listener.ora` 文件配置详解及功能说明 #### 1. 基本概念 `listener.ora` 是 Oracle 数据库中的一个重要配置文件,用于定义监听器的行为和参数。它位于 `$ORACLE_HOME/network/admin` 目录下,主要负责管理客户端与数据库之间的连接请求。 #### 2. 主要组成部分及其作用 以下是 `listener.ora` 的核心部分以及它们的功能: - **LISTENER** 定义监听器的主要描述符,指定协议地址以便接收来自客户端的连接请求。 ```plaintext LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 10.161.97.163)(PORT = 1521)) (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521)) ) ) ``` 上述配置示监听器通过两个不同的协议(TCP 和 IPC)接受连接请求[^1]。 - **SID_LIST_<Listener_Name>** 指定监听器可以识别的服务标识符(SID),并提供这些服务的相关信息。 ```plaintext SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = orcl) (SID_NAME = orcl) (ORACLE_HOME = /u01/app/oracle/product/12/db_1) ) ) ``` 这里指定了一个名为 `orcl` 的实例,并关联到特定的 `$ORACLE_HOME` 路径[^1]。 - **ENVS 参数** ENVS 参数允许设置环境变量键值对,通常用于扩展进程或其他外部程序的调用。 ```plaintext (ENVS = "EXTPROC_DLLS=ONLY:/data01/oracleDB/product/11.2.0/db_1/bin/oraclr11.dll") ``` 此处设置了动态链接库路径以支持某些特殊需求的应用程序[^4]。 - **ADR_BASE_<Listener_Name>** 自动诊断存储库的基础目录位置,用于保存错误日志和其他诊断数据。 ```plaintext ADR_BASE_LISTENER = /data01/oracleDB ``` 明自动诊断记录将被存放在 `/data01/oracleDB` 下面[^2]。 #### 3. 配置后的操作指南 完成 `listener.ora` 修改之后,需执行以下命令来应用更改: - 启动监听器:`lsnrctl start <监听器名字>`[^3] - 停止监听器:`lsnrctl stop <监听器名字>`[^3] - 查看状态:`lsnrctl status <监听器名字>` 此外还可以利用 `tnsping` 工具测试目标别名对应的数据库连通情况[^3]。 --- ### 示例代码展示 下面是一个完整的 `listener.ora` 配置样例: ```plaintext # listener.ora Network Configuration File: $ORACLE_HOME/network/admin/listener.ora SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = mydb.example.com) (SID_NAME = mydb) (ORACLE_HOME = /path/to/oracle/home) ) ) LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (ADDRESS = (PROTOCOL = IPC)(KEY = MYIPC)) ) ) ADR_BASE_LISTENER = /path/to/diag/base ``` 此示例展示了如何为单个数据库实例创建基本的监听器配置。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值