我有一个oracle查询
int[] child = new int[seledItems.Length];
int[] parent = new int[seledItems.Length];
for(int i = 0; i<seledItems.Length; i++)
{
string[] parts = seledItems[i].Split('-');
child[i] = int.Parse(parts[0]);
parent[i] = int.Parse(parts[1]);
}
LATEST_RECEIPT的数据类型早于varchar2(4000),此查询工作正常。由于列的长度需要扩展,我将其修改为CLOB,之后失败。任何人都可以帮我解决这个问题或提供解决方法吗?
答案 0 :(得分:1)
您可以更改内部查询以查找具有相同last_receipt
值但具有不同ID的其他行(假设ID是唯一的);如果存在另一行,则相当于您的计数返回大于一。但是你不能简单地测试两个CLOB值是否相等,你需要使用dbms_lob.compare
:
select ID
from your_table t1
where exists (
select null from your_table t2
where dbms_lob.compare(t2.LATEST_RECEIPT, t1.LATEST_RECEIPT) = 0
and t2.ID != t1.ID
-- or if ID isn't unique: and t2.ROWID != t1.ROWID
);
应用行号过滤器是tricker,因为您也无法在分析partition by
子句中使用CLOB。正如AndréSchild所说,你可以使用哈希;这里传递的是整数值3,相当于dbms_crypto.hash_sh1
(虽然理论上可以在将来的版本中改变!):
select id from (
select ID, ROW_NUMBER() over (partition by dbms_crypto.hash(LATEST_RECEIPT, 3)
order by ID) rownumber
from your_table t1
where exists (
select null from your_table t2
where dbms_lob.compare(t2.LATEST_RECEIPT, t1.LATEST_RECEIPT) = 0
and t2.ID != t1.ID
-- or if ID isn't unique: and t2.ROWID != t1.ROWID
)
)
where rownumber > 1;
当然可能会发生哈希冲突,如果发生了这种情况 - 你有两个latest_receipt
值,它们都出现过多次并且都散列到相同的值 - 那么你可能会得到太多的行。这似乎不太可能,但需要考虑。
因此,您只能查找具有相同lastest_receipt
和较低ID的行,而不是订购:
select ID
from your_table t1
where exists (
select null from your_table t2
where dbms_lob.compare(t2.LATEST_RECEIPT, t1.LATEST_RECEIPT) = 0
and t2.ID < t1.ID
);
再次假设ID是唯一的。如果不是,那么您仍然可以使用rowid
代替,但您可以较少控制找到哪些行 - 最低rowid
不一定是最低ID。据推测,您正在使用此功能来删除行。如果您实际上不介意保留哪一行以及删除哪一行,那么您仍然可以这样做:
and t2.ROWID < t1.ROWID
但是,由于您目前的订购可能是不可接受的,并且尽管风险很小,但散列可能更可取。