Oracle版本不同导致子查询表名相同时,查询失败

Oracle SQL查询错误解析
本文分析了一段在个人电脑上运行出现“未明确定义列”错误的Oracle SQL语句,通过修改重复的临时表名称解决了问题。文章揭示了不同Oracle版本间的行为差异,并提供了修正后的SQL代码。

一、分析思路

环境:ssm项目+oracle数据库

由于疫情,居家办公,发现公司的项目弄到自己的电脑之后,应该是能正常跑的通才对,按照故事剧情,不出意外的话就要出意外了,请看下面

看到这个界面我直接原地起飞。

代码运行异常,后来通过排查确定原因是因为SQL语句执行失败。

未明确定义列,嗯?????

这个代码在公司电脑上命名跑的好好的,在自己电脑就运行异常

接下来就是将SQL复制到Navicat中去运行,其实这个sql远没有这么简单,这是后来经过层层排查,把这段SQL简化简化再简化成了这样

SELECT
	A.REP_ID,
	A.REP_DATE,
	A.SUBMIT_ORG_ID,
	A.REP_STATUS_ID,
	DECODE(CW.REP_STATUS_ID, NULL, '待签收', 3, '已签收') CW_STATUS,
	CW.OPERATE_TIME CW_TIME
FROM
	(
		(
		SELECT
			REP_ID,
			REP_DATE,
			SUBMIT_ORG_ID, 
			MAX( TO_NUMBER( REP_STATUS_ID ) ) REP_STATUS_ID 
		FROM REP_STATUS 
		WHERE REP_ID = '00002'
			AND REP_STATUS_ID IN ( '1', '2', '5', '10' ) 
			AND REP_DATE LIKE '%2022-06%' 
		GROUP BY
			REP_ID,
			REP_DATE,
			SUBMIT_ORG_ID 
		) A 
		
		LEFT OUTER JOIN ( 
		SELECT REP_DATE, SUBMIT_ORG_ID, REP_STATUS_ID FROM REP_STATUS WHERE REP_ID = '00002' AND REP_STATUS_ID = '3' AND CHECK_DEPT_ID = '11006000' 
		) CW ON CW.SUBMIT_ORG_ID = A.SUBMIT_ORG_ID 
		
		LEFT OUTER JOIN REP_STATUS CW ON A.REP_ID = CW.REP_ID 
		AND A.REP_DATE = CW.REP_DATE 
		AND A.SUBMIT_ORG_ID = CW.SUBMIT_ORG_ID 
		AND CW.REP_STATUS_ID = '3' 
		AND CW.CHECK_DEPT_ID = '11006000' 
	)

 

这是我自己的电脑执行, 好的漂亮,出错了提示 未明确定义列

相同的sql,到公司的电脑去执行

 有点模糊,反正就是能查询出来结果,这时候我就有疑问了,这是怎么回事

这里解释一下,我把查询的逻辑关系梳理了一下,其实就是在查询的时候做了三个临时表分别是

表A,表CW,表CW

这里就出现问题了,其中有两张临时表的表名都是CW,这样导致查询列不明确。

但是这个SQL在公司的电脑上却没有问题

想了一下会不会是因为Oracle的版本不同导致了这个问题呢

查了一下自己的电脑的Oracle版本和公司的版本有什么不同

自己的Oracle版本:

 公司的Oracle版本:

继续思考,首先两个临时表CW,推断出应该是高版本的Oracle自动的识别除了列字段,因为第一个临时CW表,是没有 OPERATE_TIME  字段的,所以它会自动的匹配第二个表中的数据。

二、解决办法

其实问题也非常好解决,只要两个临时表的名称不重复就好了,比如说把第二个临时表名称改为CW1,这样就能正常执行了,这也算是踩坑吧

SELECT
  A.REP_ID,
  A.REP_DATE,
  A.SUBMIT_ORG_ID,
  A.REP_STATUS_ID,
  DECODE(CW.REP_STATUS_ID, NULL, '待签收', 3, '已签收') CW_STATUS,
  CW.OPERATE_TIME CW_TIME
FROM
  (
    (
    SELECT
      REP_ID,
      REP_DATE,
      SUBMIT_ORG_ID, 
      MAX( TO_NUMBER( REP_STATUS_ID ) ) REP_STATUS_ID 
    FROM REP_STATUS 
    WHERE REP_ID = '00002'
      AND REP_STATUS_ID IN ( '1', '2', '5', '10' ) 
      AND REP_DATE LIKE '%2022-06%' 
    GROUP BY
      REP_ID,
      REP_DATE,
      SUBMIT_ORG_ID 
    ) A 
    
    LEFT OUTER JOIN ( 
    SELECT REP_DATE, SUBMIT_ORG_ID, REP_STATUS_ID FROM REP_STATUS WHERE REP_ID = '00002' AND REP_STATUS_ID = '3' AND CHECK_DEPT_ID = '11006000' 
    ) CW1 ON CW1.SUBMIT_ORG_ID = A.SUBMIT_ORG_ID 
    
    LEFT OUTER JOIN REP_STATUS CW ON A.REP_ID = CW.REP_ID 
    AND A.REP_DATE = CW.REP_DATE 
    AND A.SUBMIT_ORG_ID = CW.SUBMIT_ORG_ID 
    AND CW.REP_STATUS_ID = '3' 
    AND CW.CHECK_DEPT_ID = '11006000' 
  )

将第一个临时表名称换了一下就可以了。

<think> 首先,用户的问题是:“我想查找在Oracle数据库中复制重复相同数据的SQL语句 请问Oracle数据库复制重复相同数据的SQL语句”。所以,用户想要知道如何在Oracle数据库中复制重复数据的具体SQL语句。 回顾系统级指令: - 所有行内数学达式必须使用$...$格式,但这里的问题是关于SQL语句的,可能不涉及数学达式,所以这部分可能不适用。 - 独立公式使用$$...$$,但同样,这里不是数学内容。 - LaTeX语法正确:确保任何代码或特殊格式正确。 - 使用中文回答:整个回答必须用中文。 - 生成相关问题:在回答末尾生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识:[^1]、[^2]等。 用户提供了三个引用: - 引用[1]: 关于SQL查询数据的基本介绍。 - 引用[2]: 关于Oracle SQL语句,特别是OR和AND的使用。 - 引用[3]: 关于查看最近执行的SQL语句。 用户说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 但在这个对话中,这是用户的第一个问题,没有之前的对话历史。所以,我需要直接基于当前问题回答。 现在,用户的核心需求是:在Oracle数据库中复制重复相同数据的SQL语句。意思是,用户想要复制数据,使某些数据行重复出现。 可能的SQL操作: - 如果用户想复制现有的行到另一个或同一,可以使用INSERT语句结合SELECT。 - 例如,复制A的所有行到B:INSERT INTO table_b SELECT * FROM table_a; - 但用户指定“复制重复相同数据”,可能意味着在同一个中创建额外的副本行。 - 或者,用户可能在查找找出重复数据的SQL语句(如用于识别重复项),但问题说的是“复制重复相同数据”,所以更倾向于创建副本。 常见场景: 1. **复制数据到另一个:** INSERT INTO new_table SELECT * FROM old_table; 2. **在同一个中复制行:** INSERT INTO table_name SELECT * FROM table_name; 但需要小心,因为这可能导致无限循环或错误。 - 更好的方式是使用WHERE条件或指定列。 3. **创建重复行:** 例如,INSERT INTO table_name (col1, col2) VALUES (value1, value2); 多次执行,但这不高效。 - 使用INSERT INTO ... SELECT ... FROM ... WHERE ... 来复制特定行。 用户说“复制重复相同数据”,可能意味着生成额外的副本行。或许用户在问如何插入重复数据。 另一个角度:用户可能误述了。或许是查找重复数据(IDENTIFYING duplicates),而不是复制(COPYING)。但问题明确说“复制重复相同数据”,所以我会假设是创建副本。 基于引用: - 引用[1]和[2]是关于查询的,引用[3]是关于查看历史SQL。 - 引用中提到“查询”,但不是直接关于复制数据。 - 我需要回答基于知识:如何复制数据。 可能的SQL语句: - 复制所有行到另一个:INSERT INTO table2 SELECT * FROM table1; - 复制特定行:INSERT INTO table2 SELECT * FROM table1 WHERE condition; - 在同一个中创建副本:INSERT INTO table1 SELECT * FROM table1 WHERE primary_key > some_value; 但需要确保有WHERE条件避免无限循环。 - 对于复制行,可以使用ROWID或唯一键来复制特定行。 标准方法: - 要复制一行,可以使用:INSERT INTO table_name (col1, col2) SELECT col1, col2 FROM table_name WHERE primary_key = some_value; - 这创建该行的另一个副本。 回答结构: - 用中文清晰回答。 - 提供SQL语句示例。 - 自然地引用提供的引用,如果相关。 - 在末尾生成相关问题。 生成相关问题: - 根据用户问题,相关问题可能包括:如何识别重复数据?如何删除重复数据?Oracle数据库的其他数据操作语句? 最终回答: 1. 解释如何复制数据。 2. 给出SQL示例。 3. 添加引用标识如果适用。 4. 生成相关问题。 </think> ### 如何复制重复数据在 Oracle 数据库中 在 Oracle 数据库中,复制重复数据(即在同一个或另一个中创建现有数据的额外副本)通常使用 SQL 的 `INSERT INTO ... SELECT` 语句实现。这允许您基于现有数据生成新行。以下是常见场景和对应的 SQL 语句示例,注意操作前务必备份数据,以避免意外数据损坏。 #### 1. **在同一个中复制所有行** - 此方法复制整个的所有行,创建完全相同的副本行。但需注意:如果有主键或唯一约束,直接复制可能导致约束冲突。您可以先禁用约束或使用临时。 - **SQL 语句示例:** ```sql -- 复制的所有行到同一个 INSERT INTO your_table_name (column1, column2, column3) SELECT column1, column2, column3 FROM your_table_name; ``` - 说明: - 替换 `your_table_name` 为您的名。 - 指定列名(如 `column1, column2, column3`)以防止完整性错误。 - 如果有自增主键,需排除主键列或用 `WHERE` 条件过滤。 - **示例场景:** 假设中没有唯一约束,此语句会将所有数据复制一份,使总行数翻倍。 #### 2. **在同一个中复制特定行** - 如果您只想复制满足特定条件的行(如基于某个列值),可以添加 `WHERE` 子句。这在复制重复条目时非常有用。 - **SQL 语句示例:** ```sql -- 复制符合条件的数据行(例如,status 为 'active' 的行) INSERT INTO your_table_name (column1, column2, column3) SELECT column1, column2, column3 FROM your_table_name WHERE status = 'active'; ``` - 说明: - 使用 `WHERE` 条件(如 `status = 'active'`)筛选要复制的行。 - 引用 [^2] 中提到的逻辑运算符(如 `OR` 和 `AND`)可增强筛选灵活性,例如:`WHERE (column1 = 'value1' OR column1 = 'value2') AND column2 = 'fixed'`。 - **实际应用:** 如果您想复制特定客户的订单数据,可使用此语句快速生成模拟数据。 #### 3. **复制数据到另一个** - 将数据复制到另一个(新或现有),避免在同一个中引发约束冲突。Oracle 支持使用 `SELECT` 子句直接插入。 - **SQL 语句示例:** ```sql -- 复制所有数据到另一个(假设结构相同) INSERT INTO new_table SELECT * FROM original_table; -- 或指定列复制(推荐) INSERT INTO new_table (col1, col2, col3) SELECT col1, col2, col3 FROM original_table; ``` - 说明: - 确保目标 `new_table` 已存在且结构与源兼容。 - 引用 [^1] 提到 SQL 提供了灵活的数据查询功能,此操作利用了 `SELECT` 的查询能力实现数据复制。 - **注意事项:** 如果目标不同结构,需在 `SELECT` 中添加转换达式。 #### 4. **复制带有重复项的特定数据** - 如果您需要基于重复值复制数据(如复制所有重复行),可先用子查询识别重复项,再插入。 - **SQL 语句示例:** ```sql -- 找出并复制重复行(例如,基于 column1 的重复值) INSERT INTO your_table_name (column1, column2, column3) SELECT column1, column2, column3 FROM your_table_name WHERE column1 IN ( SELECT column1 FROM your_table_name GROUP BY column1 HAVING COUNT(*) > 1 ); ``` - 说明: - 子查询 `HAVING COUNT(*) > 1` 识别 `column1` 出现多次的行。 - 此语句复制这些重复行,创建额外副本。 - **优化提示:** 结合引用 [^3] 的方法,使用 `v$sql` 视图查看历史 SQL 执行情况,验证复制操作的正确性。 ### 注意事项 - **约束处理:** 如果有主键、唯一索引或触发器,复制操作可能失败。建议: - 使用 `ROWID` 或临时绕过约束。 - 执行前禁用约束:`ALTER TABLE your_table_name DISABLE CONSTRAINT constraint_name;` - **性能考虑:** 复制大量数据时,添加 `COMMIT` 分批提交(如每 1000 行)以提高效率。 - **安全备份:** 执行前运行备份查询(如 `SELECT * FROM your_table_name WHERE ...`),确保数据安全[^1]。 通过以上 SQL 语句,您可以灵活地在 Oracle 中复制重复数据。如需验证操作,可参考历史 SQL 执行记录[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值