这是关于在插入后检查重复的行。我知道您会说为什么不在插入之前先检查,但是由于某些原因我们不能这样做。我们正在使用Oracle 12c。
当找到多个相同条目(transactionNumber和供应商为唯一条目)时,第一个具有最早时间的条目应作为“成功”状态传递,而其他条目则以最新的状态传递时间应被拒绝为“重复”状态。
请参见下图。
该查询似乎很有用,但有时不会捕获重复的行。当运行控制台应用程序(C#)来加载1000个数据时,我最终在1000个数据中得到2个重复。在生产中,我们在50 000个数据中得到了少于15个重复。我知道它还不错,但是有一种方法可以做比这个查询更好?完全没有重复!
Oracle DB似乎无法控制,或者我在此查询中做错了什么?我们应该为此查询创建索引吗?有什么建议吗?
import Api from './path/to/api'
import { call, put } from 'redux-saga/effects'
function fetchProductsApi() {
return Api.fetch('/products')
.then(response => ({ response }))
.catch(error => ({ error }))
}
function* fetchProducts() {
const { response, error } = yield call(fetchProductsApi)
if (response)
yield put({ type: 'PRODUCTS_RECEIVED', products: response })
else
yield put({ type: 'PRODUCTS_REQUEST_FAILED', error })
}
我的桌子是:
function checkDuplicate(i_vendor varchar2,i_transactionnumber varchar2, i_txId
raw) return number
is
transactionId raw(16);
o_result number;
BEGIN
select tx.id into transactionId from (select tx.id,row_number() over (order by tx.trans_time asc) as seqnum
from test_tx_log tx
where tx.transactionnumber = i_transactionnumber and lower(tx.vendor) = lower(i_vendor)) tx where seqnum = 1;
o_result := CASE transactionId = i_txId WHEN true THEN 1 ELSE 0 END;
return o_result;
END;
C#
Create TABLE test_tx_log
(
id RAW(16) not null,
status VARCHAR2 (300) NOT NULL,
trans_time TIMESTAMP NOT NULL,
receiptnumber VARCHAR2 (100) NULL,
transactionnumber VARCHAR2 (120) NULL,
customerreference VARCHAR2 (100) NULL,
vendor VARCHAR2 (100) NULL
) ;
答案 0 :(得分:0)
更改(select tx.id,row_number() over (order by tx.trans_time asc) as seqnum
到
(select tx.id,row_number() over (order by tx.trans_time, tx.id asc) as seqnum
按trans_time,tx.id排序,而不仅仅是trans_time。
没有订单,就没有保证的订单返回,因此查询中ID的顺序在trans_time内是随机的。
在您的示例中, 当您使用第一个ID调用该函数时,第一个ID是第一个序列号并匹配。
当您使用第二个ID调用函数时,第二个ID是第一个序列号,并且也匹配。
将ID添加到订单中将确保最早的trans_time内两个呼叫的ID 1都为seqnum 1。