2013-02-18 50 views
1

我剛剛從SQL Server移動到ORACLE,並且正在處理腳本(SQL Server樣式)。 在SQL Server中,我們在腳本中應用一些邏輯之後使用BEING TRAN-END TRAN。這可以在BEGIN-END塊內完成。 在Oracle中,我發現這有點困難。經過大量的谷歌搜索和搜索這個網站,我仍然不清楚我怎麼能滿足這個要求。可以提交應用於腳本中的每個INSERT INTO?

當我運行腳本(粘貼在下面)時,它作爲一個事務運行。並且一旦整個腳本被執行,DBMS_OUTPUT.Put_line也會顯示。 每次提交後,有沒有辦法打印DBMS_OUTPUT.Put_line?

而且,我打開思路,如果有任何其他的方式來對這個劇本的工作,讓每一個子查詢提交腳本移動到下一個子查詢之前...請讓我知道。

這裏是我的腳本:

SET SERVEROUTPUT ON; 
--spool Consolidated.log; 
WHENEVER SQLERROR EXIT SQL.SQLCODE; 
SET DEFINE OFF; 

ALTER SESSION SET GLOBAL_NAMES=FALSE; 

DECLARE 
ExtractType   NUMBER(9); 
RecordsExtracted NUMBER(9); 
CurStatus   NUMBER(9); 
StartDate   date; 
ErrorMessage  NVARCHAR2(1000); 
LastExtrctTimestamp DATE; 


BEGIN  
    -- AgreementTradeTypes 
    StartDate := sysdate; 
    ExtractType := 44; 

    DELETE FROM AgreementTradeTypes; 

    INSERT INTO AgreementTradeTypes (AgreementId,AgreementName,PrincipalId,Principal,CounterpartyId,Counterparty, TradeTypeId,TradeTypeName,BusinessLine,AdditionalCriteria) 
    -- From CORE DB 
    SELECT 
      IATT.AgreementId, AG.AgreementName, IATT.PRINCIPALID, Principal.ENTITYNAME Principal, 
      IATT.COUNTERPARTYID, Cpty.ENTITYNAME Counterparty, 
      IATT.TradeTypeID, TT.TradeTypeName, BusLine.ENUMTEXT BusinessLine, IATT.ADDITIONALCRITERIA 
    FROM [email protected] IATT 
      INNER JOIN [email protected] Principal ON IATT.PRINCIPALID = Principal.ENTITYID 
      INNER JOIN [email protected] Cpty ON IATT.CounterpartyId = Cpty.ENTITYID 
      INNER JOIN [email protected] BusLine ON IATT.BusinessLine = BusLine.ENUMVALUE AND BusLine.ENUMTYPE = 'BusinessLine' 
      INNER JOIN [email protected] AG ON IATT.AGREEMENTID = AG.AgreementID 
      INNER JOIN [email protected] TT ON IATT.TRADETYPEID = TT.TradeTypeID 
    ORDER BY IATT.AgreementId; 
    RecordsExtracted := SQL%RowCount; 

    DBMS_OUTPUT.put_line('AgreementTradeTypes Records Extracted:' || RecordsExtracted);  

    -- On Success 
    CurStatus := 2; 
    ErrorMessage := 'AgreementTradeTypes Complete'; 

    INSERT INTO ExtractRecords(ExtractType, RecordsExtracted, Status, ExtractTimestamp, StartDate, EndDate, ErrorMessage) 
    VALUES (ExtractType, RecordsExtracted, CurStatus, SysDate, StartDate, SysDate, ErrorMessage); 

    INSERT INTO LoadRecords (LoadType,Status,LoadTimestamp,StartDate,EndDate) 
    VALUES (ExtractType, CurStatus, SysDate, StartDate, SysDate); 

    COMMIT; /* Committing first Block */ 

    -- INTEREST PAYMENT PERIODS 
    StartDate := sysdate; 
    ExtractType := 57; 

    DELETE FROM InterestPaymentPeriods; 

    INSERT INTO InterestPaymentPeriods (InterestPaymentPeriodId,AgreementId,AgreementName,CurrencyId,CurrencyName,InstrumentId,InstrumentName,PositionType,CollateralMarginType,PeriodStart,PeriodEnd,NextPeriodEnd,AccruedInterest,OpeningBalance,EndingBalance,MarketIndexId,MarketIndexName,Spread,DayCountConvention,CalculationType,ManagingLocation,BusinessLine) 
    -- From CORE DB 
    SELECT 
      IPP.INTERESTPAYMENTPERIODID, IPP.AGREEMENTID, AG.AGREEMENTNAME, IPP.CURRENCYID, CUR.CODE CurrencyName, IPP.INSTRUMENTID, 
      Instruments.DESCRIPTION InstrumentName, PosType.ENUMTEXT PositionType, CollMargType.ENUMTEXT CollateralMarginType, 
      IPP.PERIODSTART, IPP.PERIODEND, IPP.NEXTPERIODEND, IPP.ACCRUEDINTEREST, IPP.OPENINGBALANCE, IPP.ENDINGBALANCE, 
      IPP.MARKETINDEXID, MI.MARKETINDEXNAME, IPP.SPREAD, DCC.ENUMTEXT DayCountConvention, CalcType.ENUMTEXT CalculationType, 
      Cty.CITYNAME ManagingLocation, BusLine.ENUMTEXT BusinessLine 
    FROM 
      [email protected] IPP 
      INNER JOIN [email protected] AG ON IPP.AGREEMENTID = AG.AGREEMENTID 
      LEFT OUTER JOIN [email protected] CUR ON IPP.CURRENCYID = CUR.CURRENCYID 
      LEFT OUTER JOIN [email protected] Cty ON IPP.MANAGINGLOCATIONID = Cty.CITYID 
      LEFT OUTER JOIN [email protected] MI ON IPP.MARKETINDEXID = MI.MARKETINDEXID 
      LEFT OUTER JOIN [email protected] ON IPP.INSTRUMENTID = Instruments.INSTRUMENTID 
      LEFT OUTER JOIN [email protected] PosType ON IPP.POSITIONTYPE = PosType.ENUMVALUE AND PosType.ENUMTYPE = 'PositionType' 
      LEFT OUTER JOIN [email protected] CollMargType ON IPP.COLLATERALMARGINTYPE = CollMargType.ENUMVALUE AND CollMargType.ENUMTYPE = 'CollateralMarginType' 
      LEFT OUTER JOIN [email protected] DCC ON MI.DAYCOUNTCONVENTION = DCC.ENUMVALUE AND DCC.ENUMTYPE = 'DayCountConvention' 
      LEFT OUTER JOIN [email protected] CalcType ON IPP.CALCULATIONTYPE = CalcType.ENUMVALUE AND CalcType.ENUMTYPE = 'CalculationType' 
      LEFT OUTER JOIN [email protected] BusLine ON IPP.BUSINESSLINE = BusLine.ENUMVALUE AND BusLine.ENUMTYPE = 'BusinessLine'; 
    RecordsExtracted := SQL%RowCount;  

    DBMS_OUTPUT.put_line('InterestPaymentPeriods Records Extracted:' || RecordsExtracted); 

    -- On Success 
    CurStatus := 2; 
    ErrorMessage := 'Interest_Payment_Periods Complete'; 

    INSERT INTO ExtractRecords(ExtractType, RecordsExtracted, Status, ExtractTimestamp, StartDate, EndDate, ErrorMessage) 
    VALUES (ExtractType, RecordsExtracted, CurStatus, SysDate, StartDate, SysDate, ErrorMessage); 

    INSERT INTO LoadRecords (LoadType,Status,LoadTimestamp,StartDate,EndDate) 
    VALUES (ExtractType, CurStatus, SysDate, StartDate, SysDate); 

    COMMIT; /* Committing Second Block */ 
END; 

--spool off; 
/

回答

1

的數據將分兩個階段進行提交。 DECLARE/BEGIN/END表示匿名PL/SQL block的開始和結束,而不是交易。如果在塊內部沒有提交(這將更加正常;在塊內部進行事務控制有點不尋常),那麼在塊完成後,您的任何更改都不會被提交 - 您仍然可以滾動回來,如果你想。

DBMS_OUTPUT通話將消息到緩衝區中,其中客戶端(例如在SQL * Plus)檢索和顯示模塊完成後。這是沒有辦法的 - 你不能使用這種機制進行「實時」更新。還有其他選擇,例如使用UTL_FILEsetting module information作爲可以從另一個會話中查看的會話,但這對於您似乎正在做的事情可能是過度的。

如果您只想在每個部分之後看到消息,則可以將其拆分爲兩個匿名塊。其缺點是可能需要兩次聲明變量,並且它們將超出塊之間的範圍 - 因此,在第一個塊中設置的內容在第二個塊中將不可見。你也許可以通過SQL * Plus variable命令解決這個問題。

根本不需要在PL/SQL中這麼做,至少在這個例子中,儘管你說你會在腳本中應用一些邏輯。如果情況並非如此,那麼您可以使用簡單的SQL語句,替換變量和提示來實現此目的,而不使用PL/SQL。除了行數之外,這有點棘手,除非你喜歡正常的set feedback on顯示,比如'插入3行'。

+0

非常感謝您的詳細描述。你清除了很多疑問和問題。你的答覆是拼圖拼圖的正確組成部分,昨天做了很多Google搜索之後,我錯過了。 非常感謝! – Shikha 2013-02-19 03:05:45

5

Oracle中的通常的做法是提交商業交易完成時,才使交易不是部分處理。這與其他一些系統不同,因爲Oracle的多版本和鎖定系統確保編寫者不會阻止讀者,讀者也不會阻止編寫者。

對於DBMS_Output問題,您不能通過DBMS_Output在通過塊的執行過程中通過DBMS_Output從服務器獲取響應。您可能希望查看使用Utl_File將數據寫入服務器端文件。

其他的想法:

  • 考慮使用TRUNCATE而不是刪除,如果你刪除的每一行以及你不需要使用外鍵對這個表。 TRUNCATE有一個與它相關的隱式提交,所以在過程開始時應用所有截斷。

  • 如果您要加載批量數據,需要維護索引,並且不需要允許多個同時插入表中,請考慮在插入上使用APPEND提示以調用直接路徑插入。

  • 我猜插入的ORDER BY是出於某種原因 - 通常在Oracle中,它將確保數據行在物理上按照列順序聚合,這導致通過這些列提高基於索引訪問的效率。使用直接路徑插入,將有助於保證物理行排序,但如果你不需要該羣集然後刪除ORDER BY

+0

我目前還沒有足夠的積分投票給你。非常感謝細節。這幫助我瞭解了Oracle如何比昨天更好地工作。 :) – Shikha 2013-02-19 03:04:02

0

DBMS_OUTPUT的結果只有在完成PL/SQL塊後纔會顯示。 DBMS_OUTPUT和COMMIT不相互關聯。如果您可以將腳本分割爲多個塊,則可以在下一個塊開始之前獲取每個塊已提交併打印的結果。

begin 
    -- step 1 
    insert 
    commit ... 
    dbms_output ... 
end; 
/

begin 
    -- step 2 
    insert... 
    commit ... 
    dbms_output ... 
end; 
/