跳至內容
Astera Technology

匯入靜靜跳過拒收行,為何仍報成功?

正式採用暫存批次前,逐筆保留真正限制失敗。

下載完整個案資料及參考答案 ↓

先核來源與已訂規則

本例可先存各有效行,但正式採用須每筆都有已接受處理。A2、B−1、C3 同受 NOT NULL 及正數 CHECK;OR IGNORE 跳 B 卻不拋錯。更正普通插入捕捉 B 真正 CHECK275,暫停採用。

已填假設輸入
紀錄輸入 JSON
原例輸入{"records":[{"id":"A","quantity":2},{"id":"B","quantity":-1},{"id":"C","quantity":3}]}
下載可編輯 CSV ↓

比較兩條實際路徑

兩路都有暫存 A、C;分別是更正留 B 拒收資料,不再誤稱三筆全成功。

錯誤與更正路徑的輸出
路徑輸出 JSON
錯誤路徑{"released":true,"errors":[],"target":[{"id":"A","quantity":2},{"id":"C","quantity":3}]}
更正路徑{"released":false,"errors":[{"source":"B","code":275}],"target":[{"id":"A","quantity":2},{"id":"C","quantity":3}]}
下載可編輯 CSV ↓
本地 Node.js 程序:22.23.3 或 24.14.1
import {DatabaseSync} from 'node:sqlite';
import {TextDecoder} from 'node:util';
import {inflateSync} from 'node:zlib';
import {posix} from 'node:path';
import {createHash} from 'node:crypto';
const rows=(db,sql)=>db.prepare(sql).all().map(r=>({...r}));
const failed=(action)=>{try{action();return null;}catch(e){return {code:e.errcode??e.code??e.name};}};

import assert from 'node:assert/strict';
const run=function run(i,corrected=true){
    const db=new DatabaseSync(':memory:');try{db.exec('CREATE TABLE target(id TEXT PRIMARY KEY,quantity INTEGER NOT NULL CHECK(quantity>0));');const errors=[];
      for(const r of i.records){const error=failed(()=>db.prepare('INSERT '+(corrected?'':'OR IGNORE ')+'INTO target VALUES(?,?)').run(r.id,r.quantity));if(error)errors.push({source:r.id,code:error.code});}
      return {released:errors.length===0,errors,target:rows(db,'SELECT * FROM target ORDER BY id')};
    }finally{db.close();}
  };
const cases=[{"label":"misleading base","input":{"records":[{"id":"A","quantity":2},{"id":"B","quantity":-1},{"id":"C","quantity":3}]},"expected":{"released":true,"errors":[],"target":[{"id":"A","quantity":2},{"id":"C","quantity":3}]},"corrected":false},{"label":"corrected base","input":{"records":[{"id":"A","quantity":2},{"id":"B","quantity":-1},{"id":"C","quantity":3}]},"expected":{"released":false,"errors":[{"source":"B","code":275}],"target":[{"id":"A","quantity":2},{"id":"C","quantity":3}]},"corrected":true},{"label":"all valid writes","input":{"records":[{"id":"A","quantity":2}]},"expected":{"released":true,"errors":[],"target":[{"id":"A","quantity":2}]},"corrected":true},{"label":"empty permitted input batch","input":{"records":[]},"expected":{"released":true,"errors":[],"target":[]},"corrected":true},{"label":"missing quantity is retained as rejection","input":{"records":[{"id":"A","quantity":2},{"id":"B","quantity":null}]},"expected":{"released":false,"errors":[{"source":"B","code":1299}],"target":[{"id":"A","quantity":2}]},"corrected":true}];
for(const test of cases){
  const actual=run(test.input,test.corrected);
  assert.deepEqual(actual,test.expected,test.label);
  console.log(test.label,actual);
}
下載可執行例子 ↓

下次載入前核邊界

全部有效 A 可收;本例明准空批次,不會有拒收輸入。B 數量欠值則違 NOT NULL1299,保留有效暫存 A,但暫停正式採用。

可編輯邊界紀錄及預期輸出
情況輸入 JSON預期輸出 JSON
所有輸入行有效{"records":[{"id":"A","quantity":2}]}{"released":true,"errors":[],"target":[{"id":"A","quantity":2}]}
明准的空批次{"records":[]}{"released":true,"errors":[],"target":[]}
欠缺數量留拒收記錄{"records":[{"id":"A","quantity":2},{"id":"B","quantity":null}]}{"released":false,"errors":[{"source":"B","code":1299}],"target":[{"id":"A","quantity":2}]}
下載可編輯 CSV ↓

三筆輸入存到兩行,是否證明整批成功?

查看參考答案

不是,錯路跳過 B。須留其 275 處理記錄,更正前暫停正式採用。

相關資源