即使良好的查询也无法捕获Oracle中的重复行

时间:2019-01-31 15:11:27

标签: c# database oracle stored-functions

这是关于在插入后检查重复的行。我知道您会说为什么不在插入之前先检查,但是由于某些原因我们不能这样做。我们正在使用Oracle 12c。

当找到多个相同条目(transactionNumber和供应商为唯一条目)时,第一个具有最早时间的条目应作为“成功”状态传递,而其他条目则以最新的状态传递时间应被拒绝为“重复”状态。

请参见下图。

enter image description here

enter image description here

该查询似乎很有用,但有时不会捕获重复的行。当运行控制台应用程序(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
   ) ;

1 个答案:

答案 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。