Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在oracle中创建更新后触发器以及如何在WPF C#应用程序中使用它_C#_.net_Wpf_Oracle_Triggers - Fatal编程技术网

如何在oracle中创建更新后触发器以及如何在WPF C#应用程序中使用它

如何在oracle中创建更新后触发器以及如何在WPF C#应用程序中使用它,c#,.net,wpf,oracle,triggers,C#,.net,Wpf,Oracle,Triggers,问题 我的oracle数据库中有三个表,即customer(包含客户的详细信息)、AccountDetails(包含客户帐户的详细信息)和Transaction表。现在我要做的是在oracle中创建一个触发器,它在AccountDetails(操作是取款和存款)更新后执行,当触发器执行时,它将在事务表中输入记录- T_ID非空数字(10) 客户ID非空编号(10) ACC_NO NOT NULL NUMBER(10) T_型VARCHAR2(20) T_金额编号(20,2) 日期时间日期 现在我

问题

我的oracle数据库中有三个表,即customer(包含客户的详细信息)、AccountDetails(包含客户帐户的详细信息)和Transaction表。现在我要做的是在oracle中创建一个触发器,它在AccountDetails(操作是取款和存款)更新后执行,当触发器执行时,它将在事务表中输入记录- T_ID非空数字(10)
客户ID非空编号(10)
ACC_NO NOT NULL NUMBER(10)
T_型VARCHAR2(20) T_金额编号(20,2) 日期时间日期

现在我不知道如何在事务表中创建触发器和插入值。 T_type列中的值应该是基于交易的贷方或借方,并且只有在我从这些函数中发送要插入的值时才能发送。但是如何发送呢

ViewModelCode

private void Transactions(object obj)
        {
            Transactions tr = new Transactions();
            TransactionsViewModel trvm = new TransactionsViewModel(Id);
            tr.DataContext = trvm;
            tr.Show();
        }
private void Withdraw(object obj)
        {
            try
            {
                con = new OracleConnection(connectionString);
                con.Open();
                OracleDataReader reader;
                cmd = new OracleCommand($"Select Acc_No,Balance from Account_Details where PIN='{Convert.ToInt32(Pin)}'", con);
                reader = cmd.ExecuteReader();
                
                if (reader.Read())
                {
                    if((Amount>0) && (Convert.ToInt32(reader.GetValue(1))>Amount))
                    { 
                        cmd = new OracleCommand($"Update Account_Details SET Balance=Balance -'{Amount}' where Customer_ID='{Id}' and PIN='{Pin}'", con);
                        int n=cmd.ExecuteNonQuery();
                        if (n > 0)
                        {
                            cmd = new OracleCommand($"Select Balance from Account_Details where PIN='{Convert.ToInt32(Pin)}'", con);
                            reader = cmd.ExecuteReader();
                            MessageBox.Show("Remaining Balance:" + reader.GetValue(0));
                        }
                    }
                    else
                    {
                        MessageBox.Show("Insufficient balance");
                    }
                }
                else
                {
                    MessageBox.Show("Incorrect PIN");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());

            }
            finally
            {
                con.Close();
                con.Dispose();
            }

        }
        private void Deposit(object obj)
        {
            try
            {
                con = new OracleConnection(connectionString);
                con.Open();
                OracleDataReader reader;  
                if (Amount > 0 && Pin!=null) 
                { 
                    cmd = new OracleCommand($"Update Account_Details SET Balance=Balance +'{Amount}' where Customer_ID='{Id}' and PIN='{Pin}'", con);
                    int n=cmd.ExecuteNonQuery();
                    if(n>0)
                    {
                       cmd = new OracleCommand($"Select Balance from Account_Details where PIN='{Convert.ToInt32(Pin)}'", con);
                       reader = cmd.ExecuteReader();
                       MessageBox.Show("Current Balance:" +reader.GetValue(0));

                    }
                    else
                    {
                      MessageBox.Show("Incorrect PIN");
                    }
                }
                else
                {
                    MessageBox.Show("Enter a valid amount");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());

            }
            finally
            {
                con.Close();
                con.Dispose();
            }
        }

使用触发器中的:NEW和:OLD值来确定余额是增加了还是减少了,并动态分配T_类型

CREATE OR REPLACE TRIGGER transaction_trg
AFTER UPDATE ON account_details
FOR EACH ROW
DECLARE
  v_t_type varchar2(20);
BEGIN
  CASE 
    WHEN :old.balance > :new.balance THEN v_t_type := 'withdraw'
    WHEN :old.balance < :new.balance THEN v_t_type := 'deposit'
    ELSE v_t_type := 'none'
  END CASE;
  
  -- assuming that customer_id and acc_no are fields in the account_details 
  -- table (and are thus part of the transaction that fired the trigger)
  -- and that t_id is a number provided by a database sequence...

  IF v_t_type IN ('withdraw','deposit') THEN
    INSERT INTO TRANSACTION (T_ID, CUSTOMER_ID, ACC_NO, T_TYPE)
      VALUES (t_id_seq.nextval, :new.customer_id, :new.acc_no, v_t_type);
  END IF;

END transaction_trg;
/
创建或替换触发器事务\u trg
更新帐户详细信息后
每行
声明
v_t_型varchar2(20);
开始
案例
当:old.balance>:new.balance然后v_t_类型:='draw'
当:old.balance<:new.balance然后v_t_类型:=“存款”
其他v_t_类型:='无'
终例;
--假设客户id和帐户编号是帐户详细信息中的字段
--表(因此是触发触发器的事务的一部分)
--这个t_id是一个由数据库序列提供的数字。。。
如果v_t_输入('draw','deposit'),那么
插入交易(T\U ID、客户ID、账号、T\U类型)
值(t_id_seq.nextval、:new.customer_id、:new.acc_no、v_t_type);
如果结束;
结束交易;
/

我得到了我问题的答案:

  create or replace trigger Transaction_trg
    after update on Account_details
    for each row
    declare
    pragma autonomous_transaction;
    begin
     if(:New.Balance <> :Old.Balance) then
       if(:New.Balance < :old.Balance) then
       
        insert into transactions(T_ID,Customer_ID,Acc_No,T_Type,T_Amount,T_DateTime) values(TransactionId.nextval,:old.Customer_Id,:Old.Acc_No,'Debit',(:old.Balance-:New.Balance),sysdate);
        commit ;
        end if;
       if(:New.Balance > :old.Balance) then
        insert into transactions(T_ID,Customer_ID,Acc_No,T_Type,T_Amount,T_DateTime) values(TransactionId.nextval,:old.Customer_Id,:Old.Acc_No,'Credit',(:New.Balance-:OLd.Balance),sysdate);
        commit;
        end if;
    end if;
    end;
创建或替换触发器事务\u trg
更新帐户详细信息后
每行
声明
布拉格自治交易;
开始
如果(:New.Balance:Old.Balance)那么
如果(:New.Balance<:old.Balance),则
将值(TransactionId.nextval、:old.Customer\u ID、:old.Acc\u No、'Debit'、(:old.Balance-:New.Balance)、sysdate)插入交易(T\u ID、客户ID、账户编号、T\u类型、T\u金额、T\u日期时间)中;
犯罪
如果结束;
如果(:New.Balance>:old.Balance),则
将值(TransactionId.nextval、:old.Customer\u ID、:old.Acc\u No、'Credit'、(:New.Balance-:old.Balance)、sysdate)插入交易(T\u ID、客户ID、账户编号、T\u类型、T\u金额、T\u日期时间)中;
犯罪
如果结束;
如果结束;
结束;

我可以提出一些改进代码的建议吗?:使您的条件更像是保护声明:检查“不好”条件,如果满足条件,则尽早退出该方法。这将使您的代码更易于阅读。您还应该使用
using
语句,并为连接对象设置一个局部变量。我还建议使用参数化SQL查询,并使用两个单独的OracleCommand变量。这些建议与您的问题无关,我只是想帮助您改进现有代码。谢谢您的建议。我将尝试改进我的代码。然后v_t_类型:='Debit'amount=:old.balance-:new.balance然后v_t_类型:='Credit'amount=:new.balance-:old.balance我为上述金额添加了一些代码,但仍然显示错误-无效的sql语句。请帮助@pmdbaamount:=:old.balance-:new.balance这是添加的行。它仍然显示编译错误的成功,不要在触发器中放入提交或自治_事务。提交必须来自父事务,否则如果触发事务或您的自治事务因任何原因回滚,您将导致数据损坏。触发的插入应始终是与插入帐户详细信息相同的交易的一部分。