如何重现流程的代码:表格 - 自动行处理(DML)

How to reproduce the code of the process : Form - Automatic Row Processing (DML)

自从我上次 post 关于遍历顶点项目 () 以来,我不得不创建一个流程,允许我循环遍历我的项目并进行多次插入。

这是我的流程代码:

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 插入操作。然后这将调用默认的 Process : Form - Automatic Row Processing (DML),这个 :

所以,这引出了我的主要问题:我如何重现这个自动默认过程的代码才能对约束、值进行相同的检查等等... 对于我的实际自定义流程,如果用户执行某种类型的插入并使用错误值调用此自定义流程,他们将看不到错误消息,并且插入也不会执行。所以,他们没有任何关于正在发生的事情的信息。

是否可以重现代码,或者我如何调整我的流程代码以检查表单的每个输入和字段插入流程之前?

再次感谢您的宝贵时间,请随时提出问题以了解更多详情,

托马斯

编辑:


首先,我有 table 个项目
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);

我还有一个视图,它从其他不同的 table 中获取值,并在视图上进行插入:

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;

我有一个 INSTEAD OF,但不能粘贴在这里,因为它太大了,但没有什么特别的,认为它是一个基本的 INSTEAD OF 触发器。

还有其他检查验证的方法吗?也许类似于 Javascript 函数,它在第一张图片中的字段下显示错误,或者像“冻结”或“锁定”验证按钮,在您解决字段上的错误之前无法按下?


更新 2

太好了,我在 JavaScript 中创建了一个验证函数。我有一个显示 apex.message.confirm 的按钮,如果用户按“确定”,则插入过程正在启动。

我的验证是检查字段的值是否为空以及价格是否在 1 到 99'999.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 = [
    "Intitulé de l'article",
    "Catégorie",
    "Bâtiment",
    "Étage - bureau",
    "Prix unitaire"
];

//Check des NULL
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] + " doit contenir une valeur",
        unsafe: false
      }
    ]);
    chkErr = 1;
  } 
}
var str = $v("P24_PRIX_UNITAIRE_ARTICLE");
//2 lines below remove the 'CHF' format mask currency
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: "Prix unitaire n'est pas entre les valeurs min et max.",
        unsafe: false}
    ]);
    chkErr = 1;
}


if ( chkErr == 0 ) { 
  /* Custom dynamic action call when no error occurred */
  apex.message.confirm("Vous êtes sur le point d'insérer "+ apex.item('P24_NB_MULT').getValue() + " articles, confirmez-vous que les données insérées sont correctes ?", function(okPressed) {
    if (okPressed) {
        $.event.trigger("insertionMultipleComm");
    }
});
}

现在,它正在运行,就像上面的第一张图片一样。

使用 apex_item 的缺点是您必须自己完成 pl/sql 中的所有工作。看来这个问题专门针对验证,所以我会专注于此。解决方案是使用验证并在该验证中循环遍历 apex_application.g_f01,并为遇到的任何错误调用 apex_error.add_error。如果有错误则不会执行页面处理。

创建类型为“返回错误文本的函数主体”的验证并执行类似的操作 - 请注意,这不是您的代码,而只是一个示例:

DECLARE
BEGIN
  FOR i IN 1 .. apex_application.g_f01.COUNT LOOP
    IF VALIDATE_CONVERSION(APEX_APPLICATION.G_F04(i) AS NUMBER) = 0 THEN
        apex_error.add_error (
            p_message          => 'Salary must be a number',
            p_display_location =>  apex_error.c_inline_in_notification);
    END IF;   
    -- add other validations for other columns if needed. 
  END LOOP; 
  RETURN NULL;
END;

现在,除了验证和 dml 过程之外,如果您手动执行所有操作,您还缺少另一个功能,那就是丢失的更新检测。用户 1 打开表格去喝杯咖啡,然后用户 2 使用相同的数据打开表格,进行一些更改并保存。然后用户 1 回来,对他已经打开的数据进行一些更改并覆盖用户 2 所做的更改。您 没有 来为此编写代码,但意识到这是一个现实世界的问题。在 apex 中,您可以使用具有 md5_checksum 属性的集合来执行此操作。 Here 是一个解释如何解决它的论坛条目