You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何复现Oracle APEX Form - Automatic Row Processing (DML)的约束校验逻辑用于批量插入

Oracle APEX 自定义批量插入进程的校验实现方案

背景说明

我之前编写过遍历APEX项的相关实现,后续基于该逻辑开发了自定义PL/SQL进程,实现循环遍历项执行批量插入功能。

现有批量插入代码

BEGIN
FOR i IN apex_application.g_f01.FIRST..apex_application.g_f01.LAST
LOOP
    INSERT INTO vue_articles
(
    nom_article, 
    fk_categorie_article,
    fk_amortissement, 
    prix_unitaire_article,
    pk_fk_etage_bureau,
    commentaire_article 
    )
VALUES
(
    :P24_NOM_ARTICLE, 
    :P24_FK_CATEGORIE_ARTICLE, 
    :P24_FK_AMORTISSEMENT,
    TO_NUMBER(:P24_PRIX_UNITAIRE_ARTICLE,'FM999G999G999G999G990D00C'),
    :P24_PK_FK_ETAG_BUREAU, 
    apex_application.g_f01(i)
    );
END LOOP;
END;

遇到的问题

当前功能运行正常,但缺少约束校验能力:

  • 常规表单点击CREATE按钮时,会执行提交页面动作,触发SQL INSERT数据库操作,调用默认进程Form - Automatic Row Processing (DML),如果输入为空、数值超出范围会自动弹出错误提示;
  • 自定义进程执行插入时如果值非法,不会返回任何错误提示,插入直接失败,用户无法感知问题原因。
    需要实现的能力:
  • 复现默认自动进程的校验逻辑,实现相同的约束、数值校验能力
  • 或是调整现有自定义进程代码,在插入前完成表单所有输入项的校验
  • 也可以接受前端校验方案,实现和默认效果一致的字段下错误提示,或是设置校验不通过时禁用提交按钮

附加结构信息

物品表结构

CREATE TABLE inv_tb_article(
   pk_article INT,
   date_ajout_article DATE DEFAULT SYSDATE CONSTRAINT ct_nn_date_ajout_article NOT NULL,
   nom_article VARCHAR(50) CONSTRAINT ct_nn_nom_article NOT NULL,
   prix_unitaire_article NUMBER(7,2) CONSTRAINT ct_nn_prix_unitaire_article NOT NULL,
   montant_amorti_article REAL,
   prix_net_article REAL,
   fk_amortissement INT,
   fk_categorie_article INT CONSTRAINT ct_nn_fk_categorie_article NOT NULL,
   commentaire_article VARCHAR(50),
   CONSTRAINT ct_pk_article PRIMARY KEY(pk_article),
   CONSTRAINT ct_fk_amortissement FOREIGN KEY(fk_amortissement) REFERENCES inv_tb_amortissement(pk_amortissement),
   CONSTRAINT ct_fk_categorie_article FOREIGN KEY(fk_categorie_article) REFERENCES inv_tb_categorie(pk_categorie),
   CONSTRAINT ct_ck_prix_unitaire_article CHECK(prix_unitaire_article BETWEEN 0 AND 100000)
);
ALTER INDEX ct_pk_article RENAME TO ind_pk_article;
CREATE INDEX ind_fk_amortissement ON inv_tb_article(fk_amortissement);
CREATE INDEX ind_fk_categorie_article ON inv_tb_article(fk_categorie_article);
CREATE INDEX ind_nom_article ON inv_tb_article(nom_article);

关联视图定义

插入操作是在多表关联视图VUE_ARTICLES上执行,已为视图配置基础INSTEAD OF触发器,视图定义如下:

CREATE OR REPLACE VIEW VUE_ARTICLES AS 
  select PK_ARTICLE, 
    DATE_AJOUT_ARTICLE, 
    NOM_ARTICLE, 
    FK_CATEGORIE_ARTICLE, 
    FK_AMORTISSEMENT, 
    PRIX_UNITAIRE_ARTICLE,
    MONTANT_AMORTI_ARTICLE, 
    PRIX_NET_ARTICLE, 
    PK_FK_SERVICE, 
    PK_FK_ETAGE_BUREAU,
    CODE_SERVICE,
    code_active_directory,
    fk_batiment,
    nom_departement,
    commentaire_article,
    ctrl_aj_date,
    ctrl_aj_user,
    ctrl_mo_date,
    ctrl_mo_user,
    ctrl_mo_jeton,
    nom_categorie
 from   INV_TB_ARTICLE
 INNER JOIN inv_tb_posseder ON inv_tb_article.pk_article = inv_tb_posseder.pk_fk_article
 INNER JOIN inv_tb_service ON inv_tb_posseder.pk_fk_service = inv_tb_service.pk_service
 INNER JOIN inv_tb_departement ON inv_tb_service.fk_departement = inv_tb_departement.pk_departement
 INNER JOIN inv_tb_etage_bureau ON inv_tb_posseder.pk_fk_etage_bureau = inv_tb_etage_bureau.pk_etage_bureau
 INNER JOIN inv_tb_batiment ON inv_tb_etage_bureau.fk_batiment = inv_tb_batiment.pk_batiment
 INNER JOIN inv_tb_categorie ON inv_tb_article.fk_categorie_article = inv_tb_categorie.pk_categorie;

最终实现方案

我已经通过JavaScript实现了前端校验功能,按钮点击时先清空历史错误,检查必填项是否为空、单价是否在1到99999.99区间,校验通过后弹出确认框,确认后触发批量插入事件,实现效果和默认校验一致,代码如下:

apex.message.clearErrors();

var chkErr = 0;
var arr = [
   'P24_NOM_ARTICLE', 
   'P24_FK_CATEGORIE_ARTICLE',
   'P24_BATIM', 
   'P24_PK_FK_ETAG_BUREAU', 
   'P24_PRIX_UNITAIRE_ARTICLE'
];
var arrLabel = [
    "物品名称",
    "分类",
    "建筑",
    "楼层-办公室",
    "单价"
];

// 空值校验
for (var i in arr) {
  if ($v(arr[i]).length == 0) {
    apex.message.showErrors([
      {
        type: apex.message.TYPE.ERROR,
        location: ["inline", "page"],
        pageItem: arr[i],
        message: arrLabel[i] + "不能为空",
        unsafe: false
      }
    ]);
    chkErr = 1;
  } 
}
var str = $v("P24_PRIX_UNITAIRE_ARTICLE");
// 移除货币格式掩码中的'CHF'标识
str = str.slice(0, -3); 
if (parseFloat(str.replace(/[^\d\.]/g,'')) > 99999.99 || parseFloat(str.replace(/[^\d\.]/g,''))<1){
    apex.message.showErrors([{
        type: apex.message.TYPE.ERROR,
        location: ["inline", "page"],
        pageItem: "P24_PRIX_UNITAIRE_ARTICLE",
        message: "单价不在合法的取值范围内",
        unsafe: false}
    ]);
    chkErr = 1;
}


if ( chkErr == 0 ) { 
  /* 校验无错误时触发自定义动态动作 */
  apex.message.confirm("您即将插入"+ apex.item('P24_NB_MULT').getValue() + "条物品数据,请确认输入信息是否正确?", function(okPressed) {
    if (okPressed) {
        $.event.trigger("insertionMultipleComm");
    }
});
}

目前该方案已正常运行,效果和默认校验一致。

内容的提问来源于stack exchange,提问作者ThomasT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 23:42:04