Oracle Apex 22.21 – REST数据源 – 触发器将字符串转换为数字并添加到列中

huangapple go评论51阅读模式
英文:

Oracle Apex 22.21 - REST data source - trigger to convert string to_number and add into a column

问题

这个问题是关于另一个SO问题的后续问题。

我有一个使用来自API的JSON响应的REST数据源的应用程序。有两个表ORDERS和LINES。ORDERS表包含一个名为LINES的JSON文档类型列。

我在ORDERS表上创建了一个触发器,它在ORDERS表上进行AFTER INSERT、UPDATE或DELETE操作,并维护LINES表(从ORDERS表的ORDER_ITEMS列中提取JSON数组并插入ORDER_ITEMS表以及每个列)。

来自API的示例JSON响应
[{
  "order_number": "so1223",
  "order_date": "2022-07-01",
  "full_name": "Carny Coulter",
  "email": "ccoulter2@ovh.net",
  "credit_card": "3545556133694494",
  "city": "Myhiya",
  "state": "CA",
  "zip_code": "12345",
  "lines": [
    {
      "product": "Beans - Fava, Canned",
      "quantity": 1,
      "price": $1.99
    },
    {
      "product": "Edible Flower - Mixed",
      "quantity": 1,
      "price": $1.50
    }
  ]
},
{
  "order_number": "so2244",
  "order_date": "2022-12-28",
  "full_name": "Liam Shawcross",
  "email": "lshawcross5@exblog.jp",
  "credit_card": "6331104669953298",
  "city": "Humaitá",
  "state": "NY",
  "zip_code": "98670",
  "lines": [
    {
      "order_id": 5,
      "product": "Beans - Green",
      "quantity": 2,
      "price": $4.33
    },
    {
      "order_id": 1,
      "product": "Grapefruit - Pink",
      "quantity": 5,
      "price": $5.00
    }
  ]
}]
create or replace trigger "TR_MAINTAIN_LINES"
AFTER
insert or update on "ORDERS"
for each row
begin
    if inserting or updating then
        if updating then
          delete LINES
          where order_number = :old.order_number;
        end if;
        insert into LINES ( order_number, product, quantity, price, item_image) 
        ( select :new.order_number,
                 j.product,
                 j.quantity,
                 j.price,
                 j.item_image
            from json_table( 
                     :new.lines,
                     '$[*]' columns (
                         product  varchar2(4000) path '$.product',
                         quantity number        path '$.quantity',
                         price    varchar2(4000) path '$.price', 
                         item_image varchar2(4000) path '$.item_image' ) ) j );
    end if;
end;

所以现在这个工作正常。但是,由于JSON响应中的$,PRICE列是varchar类型(例如:$1.99)。我可以在视图中使用TO_NUMBER(price, '$999,999,999.99')将其更改为数字类型。

如何在触发器内部执行这个操作?

  • 在插入或更新后触发器中,将PRICE列(varchar)转换为另一列TOTAL_PRICE(number)。
  • 我还想添加另一列UNIT_PRICE,它取TOTAL_PRICE/QUANTITY。

这些操作是否可以在给定的触发器内执行,还是我需要创建一个单独的触发器?

英文:

This question is a follow up to another SO question.

I have an app with a REST Data Source taking in JSON responses from an API. There are two tables ORDERS and LINES. The ORDERS table contains a column LINES which is a JSON Document type.

I created a trigger on my ORDERS table which runs AFTER INSERT, UPDATE or DELETE on my ORDERS table, and which maintains the LINES table (Extracts the JSON array from the ORDERS table ORDER_ITEMS column and inserts into ORDER_ITEMS table and each column).

SAMPLE JSON RESPONSE FROM API
[ {
  "order_number": "so1223",
  "order_date": "2022-07-01",
  "full_name": "Carny Coulter",
  "email": "ccoulter2@ovh.net",
  "credit_card": "3545556133694494",
  "city": "Myhiya",
  "state": "CA",
  "zip_code": "12345",
  "lines": [
    {
      "product": "Beans - Fava, Canned",
      "quantity": 1,
      "price": $1.99
    },
    {
      "product": "Edible Flower - Mixed",
      "quantity": 1,
      "price": $1.50
    }
  ]
},
{
  "order_number": "so2244",
  "order_date": "2022-12-28",
  "full_name": "Liam Shawcross",
  "email": "lshawcross5@exblog.jp",
  "credit_card": "6331104669953298",
  "city": "Humaitá",
  "state": "NY",
  "zip_code": "98670",
  "lines": [
    {
      "order_id": 5,
      "product": "Beans - Green",
      "quantity": 2,
      "price": $4.33
    },
    {
      "order_id": 1,
      "product": "Grapefruit - Pink",
      "quantity": 5,
      "price": $5.00
    }
  ]
},
]
create or replace trigger "TR_MAINTAIN_LINES"
AFTER
insert or update on "ORDERS"
for each row
begin
    if inserting or updating then
        if updating then
          delete LINES
          where order_number = :old.order_number;
        end if;
        insert into LINES ( order_number, product, quantity, price, item_image) 
        ( select :new.order_number,
                 j.product,
                 j.quantity,
                 j.price,
                 j.item_image
            from json_table( 
                     :new.lines,
                     '$[*]' columns (
                         product  varchar2(4000) path '$.product',
                         quantity number        path '$.quantity',
                         price    varchar2(4000) path '$.price', 
                         item_image varchar2(4000) path '$.item_image' ) ) j );
    end if;
end;

So this works as expected right now. However, the PRICE column is a varchar type due to the '$' in the JSON response. (Ex: $1.99). I'm able to change this to a number type in a view by using TO_NUMBER(price,'$999,999,999.99').

How can I do this within the trigger?

  • Have the trigger after insert or update, convert the PRICE column (varchar) to a another column TOTAL_PRICE (number).
  • I also want to add another column UNIT_PRICE which takes TOTAL_PRICE/QUANTITY.

Are these possible within the given trigger or would I have to create a separate trigger?

答案1

得分: 1

对于列TOTAL_PRICE

是的,可以在触发器中完成这个操作。将列添加到lines表,并修改插入语句

...
       insert into LINES ( order_number, product, quantity, price, total_price, item_image) 
        ( select :new.order_number,
                 j.product,
                 j.quantity,
                 j.price,
                 TO_NUMBER(j.price,'$999.99'),
                 j.item_image
            from json_table( 
                     :new.lines,
                     '$[*]' columns (
                         product  varchar2(4000) path '$.product',
                         quantity number        path '$.quantity',
                         price    varchar2(4000) path '$.price', 
                         item_image varchar2(4000) path '$.item_image' ) ) j );
...
对于列UNIT_PRICE

这也可以在触发器中完成,但更合理的做法是在这里添加一个"虚拟列",因为单位价格始终是TOTAL_PRICE/QUANTITY。虚拟列无法更新/插入,只能选择 - 值始终是最新的

alter table lines add unit_price number generated always as ( total_price / quantity ) virtual;
英文:
For column TOTAL_PRICE

Yes this can be done in the trigger. Add the column to the lines table and modify the insert statement

...
       insert into LINES ( order_number, product, quantity, price, total_price, item_image) 
        ( select :new.order_number,
                 j.product,
                 j.quantity,
                 j.price,
                 TO_NUMBER(j.price,'$999.99'),
                 j.item_image
            from json_table( 
                     :new.lines,
                     '$[*]' columns (
                         product  varchar2(4000) path '$.product',
                         quantity number        path '$.quantity',
                         price    varchar2(4000) path '$.price', 
                         item_image varchar2(4000) path '$.item_image' ) ) j );
...
For column UNIT_PRICE

This can be done in the trigger as well but... it makes more sense to add a "virtual column" here since unit price is always TOTAL_PRICE/QUANTITY. A virtual column cannot be updated/inserted, only selected - the value is always up to date

alter table lines add unit_price number generated always as ( total_price / quantity ) virtual;

huangapple
  • 本文由 发表于 2023年2月14日 20:51:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/75448104.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定