首页 > 解决方案 > 如何重现流程的代码:Form - Automatic Row Processing (DML)

问题描述

自从我上一篇关于迭代槽顶点项目的帖子(这里是链接)以来,我必须创建一个流程,允许我循环遍历我的项目并进行多次插入。

这是我的流程代码:

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;

一切正常,还有一个问题:没有约束检查,让我解释一下。通常,当我单击基本按钮以在表单上创建一行时,如果我的输入为空或某些值太高或太低,我会被卡住并会看到弹出错误消息显示错误, 像这样 :

基本插入

我猜,这是因为基本按钮使用SQL INSERT Action数据库操作CREATE执行提交页面操作。然后这将调用默认进程:表单 - 自动行处理 (DML),这个:

默认进程

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

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

再次感谢您的宝贵时间,请随时提问以获取更多详细信息,

托马斯

编辑 :


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

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

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

Sooo,我在 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");
    }
});
}

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

标签: oracleplsqlprocessconstraintsoracle-apex

解决方案


使用 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 属性的集合来执行此操作。是一个论坛条目,解释了如何解决它


推荐阅读