1

I created a procedure from querying other tables including transaction tbl to settle all transaction records with a reference number and date automatically stamped on it.

What I try to do is my settle_transaction procedure needs to generate my query from the selected statement and insert them into the settlement table. Meanwhile, I also need to update the ref_num and processed date as a "stamp" to the transaction table so that I don't have duplicated settlement when calling the procedure again. Otherwise, I don't know how to stop showing the same settlement data twice

Here is the procedure to output a settlement tbl and structure similar below:

BEGIN
    for r_client in 
    (
        select clientid,
        client_name, sum(transaction) total_amount
        from transaction_tbl tran join terminal_tbl term
        on tran.terminalid = term.terminalid join client_tbl c on c.clientid = term.clientid
        where refnr is null
    )
    loop
    v_refnr := get_refnr;
        insert into settlement_tbl
        (
            Ref_Num, 
            Total,
            CLIENTID,
            TITLE, 
            processeddate
        )
        values (v_refnr, total_amount, clientid,
        name,sysdate);
update_refnr(v_refnr, sysdate)
        end loop;
END

Output:

| reference_num | total amount | client id | client name | processed_date |
|---------------|--------------|-----------|-------------|----------------|

When I execute the above procedure, it populates all the result from the select query. However, if I execute again, it will duplicate the same result especially the total amount.

I'm seeking a solution to put another procedure/function inside this settlement procedure to prevents duplicate records from the selected query in this procedure.

I use the ref. no# and process_date to update the existing reference num and date to the transaction tbl show below.

| transaction_num | transaction amount | reference_num | processed_date |
|-----------------|--------------------|---------------|----------------|

Here is the attempted code I put inside the settlement procedure but still shows duplicated records and can not update to the transaction tbl.

procedure update_refnr(
  p_refnr in number,
  p_processeddate in date
)
is
begin
    UPDATE TRANSACTION t 
       SET t.refnr = p_refnr
     WHERE EXISTS (SELECT p_processeddate 
                     FROM terminal_tbl
                    WHERE t.TERMINALID= term.TERMINALID
                      AND t.processeddate = p_processeddate
                      AND t.refnr IS NULL);   
--exception handling below

end update_refnr;

I also tried other SQL reference but cannot compile.

Ideally, I don't have duplicated records in my settlement tbl when I retrieve each record from my stored procedure.

Stu_Dent
  • 370
  • 1
  • 4
  • 19
  • I am not sure I completely understand your question, why not fix the original procedure so it doesn’t create duplicates? You are using different column names or aliases in your examples and code so it’s hard to follow along. Maybe add some sample data to the question – Joakim Danielson May 11 '19 at 08:16
  • Because the transaction keeps running all the time, I make a settlement table to generate a total amount from each client at any time, otherwise, it will the previous transaction again. Hope you understand this my problem. – Stu_Dent May 11 '19 at 08:22
  • Not sure I do, is the first procedure only a select query? – Joakim Danielson May 11 '19 at 08:29
  • That looks like you are doing INSERT in that procedure and not only SELECT. – Joakim Danielson May 11 '19 at 08:37
  • @JoakimDanielson, yes, because I need to insert the query values to the settlement table. – Stu_Dent May 11 '19 at 08:46
  • *"I also tried other mssql reference "* - SQL Server and Oracle are different database platforms and have different syntaxes. In this case SQL Server supports ANSi 92 joins in UPDATE (and DELETE), and Oracle doesn't. Which is a shame, because it's a highly neat solution. – APC May 11 '19 at 08:58
  • 1
    Have you tried using `Merge`. Your problem statement appear to me more kind of `Merge`. – XING May 11 '19 at 09:02

1 Answers1

1

You want to insert new data into your table only when it doesn't already exist. As others have said, you can use MERGE to do that:

BEGIN
  for r_client in (select clientid,
                          client_name,
                          sum(transaction) total_amount
                     from transaction_tbl tran
                     join terminal_tbl term
                       on tran.terminalid = term.terminalid
                     join client_tbl c
                       on c.clientid = term.clientid
                     where refnr is null)
  loop
    v_refnr := get_refnr;

    MERGE INTO settlement_tbl s
      USING (SELECT v_refnr      AS REF_NUM,
                    total_amount AS TOTAL,
                    clientid     AS CLIENTID,
                    name         AS TITLE,
                    SYSDATE      AS PROCESSEDDATE
               FROM DUAL) d
        ON (s.REF_NUM = d.REF_NUM)
      WHEN NOT MATCHED THEN
        INSERT (Ref_Num,   Total,   CLIENTID,   TITLE,   processeddate)
        VALUES (d.REF_NUM, d.TOTAL, d.CLIENTID, d.TITLE, d.PROCESSEDDATE);

    update_refnr(v_refnr, sysdate);
  END LOOP;
END;

WHEN NOT MATCHED inserts new data when v_refnr does not already exist in your table.

Best of luck.

  • Not only I want to insert new data to a settlement table, but also link the ref_num and processed date back to the transaction table that I originally generate total amount from each transaction, so that I can see which transaction already been settled and avoid duplication with that ref_num. – Stu_Dent May 11 '19 at 11:42
  • I got client name with this `Error(22,17): PL/SQL: ORA-00904: "name": invalid identifier` – Stu_Dent May 11 '19 at 12:00
  • In your original code you used `name` - I just copied it from there. Did you perhaps mean `client_name`? – Bob Jarvis - Слава Україні May 11 '19 at 12:05
  • Yes, I follow your suggestion and got above error, is that alias causing this issue? – Stu_Dent May 11 '19 at 12:12
  • I wonder why using dual instead of the r_client record in this scenario? – Stu_Dent May 11 '19 at 14:36
  • In a MERGE statement the `USING` clause must name a table, not a record. If you didn't have to call `update_refnr` for each row you could replace the use of DUAL in the `USING` clause with the cursor which reads from TRANSACTION_TBL, etc. In scenarios like this it's quite common to use a `SELECT...FROM DUAL` to provide the necessary table. – Bob Jarvis - Слава Україні May 11 '19 at 19:49
  • The TRANSACTION_TBL only contains `ref_num` and `processed date`, should it work replace the dual with the transaction table? – Stu_Dent May 12 '19 at 02:07
  • I suppose so. Give that a try. – Bob Jarvis - Слава Україні May 12 '19 at 03:14
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/193200/discussion-between-stu-dent-and-bob-jarvis). – Stu_Dent May 12 '19 at 03:55