oracle - 如何重现进程: Form - Automatic Row Processing (DML)的代码

标签 oracle plsql process constraints oracle-apex

自从我上一篇关于迭代槽顶点项目(here's the link)的文章以来,我必须创建一个进程,它允许我循环遍历我的项目并执行多次插入。

这是我的流程代码:

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;

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

basic insert

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

default process

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

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

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

托马斯

编辑:


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

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

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");
    }
});
}

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

最佳答案

使用 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是一个论坛条目,解释了如何解决该问题

关于oracle - 如何重现进程: Form - Automatic Row Processing (DML)的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69103039/

相关文章:

C# Windows 窗体被任务管理器杀死......有没有办法运行关机功能?

mysql - 分布式数据库与否?

c# - 针对特定场景的缓存架构建议

sql - PL/SQL 中日期比较的问题

oracle - 在Oracle数据库中存储重复时间段

oracle - PLS-00103 : Encountered the symbol “WHERE” when expecting one of the following

vb.net - 等待进程

c# - 什么是 "Error initializing filter ' drawtext' with args..."在 c# 进程类中使用 ffmpeg 时出现错误?

oracle - 在 oracle apex 中将一个页面链接到另一个页面

oracle - 以全局用户身份登录 oracle db