1

SQL Server から ORACLE に移行したばかりで、スクリプト (SQL Server スタイル) に取り組んでいます。SQL Server では、スクリプトにいくつかのロジックを適用した後、BEING TRAN - END TRAN を使用します。これは、BEGIN-END ブロック内で実行できます。Oracle では、これは少し難しいと思います。このサイトで多くのグーグルと検索を行った後、どうすればこの要件を満たすことができるかまだ明確ではありません.

スクリプト (以下に貼り付け) を実行すると、これは 1 つのトランザクションとして実行されました。また、スクリプト全体が実行されると、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    IncludedAgreementTradeTypes@RPTCORE IATT 
            INNER JOIN Entities@RPTCORE Principal ON IATT.PRINCIPALID = Principal.ENTITYID
            INNER JOIN Entities@RPTCORE Cpty ON IATT.CounterpartyId = Cpty.ENTITYID
            INNER JOIN EnumValues@RPTCORE BusLine ON IATT.BusinessLine = BusLine.ENUMVALUE AND BusLine.ENUMTYPE = 'BusinessLine'
            INNER JOIN Agreements@RPTCORE AG ON IATT.AGREEMENTID = AG.AgreementID
            INNER JOIN TradeTypes@RPTCORE 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
            INTERESTPAYMENTPERIODS@RPTCORE IPP
            INNER JOIN Agreements@RPTCORE AG ON IPP.AGREEMENTID = AG.AGREEMENTID
            LEFT OUTER JOIN Currencies@RPTCORE CUR ON IPP.CURRENCYID = CUR.CURRENCYID
            LEFT OUTER JOIN Cities@RPTCORE Cty ON IPP.MANAGINGLOCATIONID = Cty.CITYID
            LEFT OUTER JOIN MarketIndexes@RPTCORE MI ON IPP.MARKETINDEXID = MI.MARKETINDEXID
            LEFT OUTER JOIN Instruments@RPTCORE ON IPP.INSTRUMENTID = Instruments.INSTRUMENTID
            LEFT OUTER JOIN EnumValues@RPTCORE PosType ON IPP.POSITIONTYPE = PosType.ENUMVALUE AND PosType.ENUMTYPE = 'PositionType'
            LEFT OUTER JOIN EnumValues@RPTCORE CollMargType ON IPP.COLLATERALMARGINTYPE = CollMargType.ENUMVALUE AND CollMargType.ENUMTYPE = 'CollateralMarginType'
            LEFT OUTER JOIN EnumValues@RPTCORE DCC ON MI.DAYCOUNTCONVENTION = DCC.ENUMVALUE AND DCC.ENUMTYPE = 'DayCountConvention'
            LEFT OUTER JOIN EnumValues@RPTCORE CalcType ON IPP.CALCULATIONTYPE = CalcType.ENUMVALUE AND CalcType.ENUMTYPE = 'CalculationType'
            LEFT OUTER JOIN EnumValues@RPTCORE 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;
/
4

3 に答える 3

5

Oracle では通常、トランザクションが部分的に処理されないように、ビジネス トランザクションが完了したときにのみコミットします。これは、Oracle のマルチバージョニングおよびロック システムによって、ライターがリーダーをブロックせず、リーダーがライターをブロックしないことが保証されるため、他のシステムとは異なります。

DBMS_Output の問題については、ブロックの実行の途中で DBMS_Output を介してサーバーから応答を取得できません。そのために Utl_File を使用してサーバー側のファイルにデータを書き込むことを検討したい場合があります。

他の考え:

  • すべての行を削除し、そのテーブルに対して外部キーを使用する必要がない場合は、DELETE の代わりに TRUNCATE を使用することを検討してください。TRUNCATE には暗黙的なコミットが関連付けられているため、手順の最初にすべての切り捨てを適用します。

  • 大量のデータをロードしていて、維持するインデックスがあり、テーブルへの複数の同時挿入を許可する必要がない場合は、挿入で APPEND ヒントを使用してダイレクト パス挿入を呼び出すことを検討してください。

  • 挿入の ORDER BY には何らかの理由があると推測しています。通常、Oracle では、データ行が order-by 列で物理的にクラスター化されていることを確認するためです。これにより、インデックスの効率が向上します。それらの列を介したベースのアクセス。直接パス挿入を使用すると、物理的な行の順序を保証するのに役立ちますが、そのクラスタリングが必要ない場合は、ORDER BY を削除します

于 2013-02-18T10:50:35.540 に答える
1

データは 2 段階でコミットされます。DECLARE//は、トランザクションではなく、無名 PL/SQL ブロックの開始と終了をBEGIN示します。ブロック内にコミットがまったくない場合 (これはより正常です。ブロック内にトランザクション制御があるのは少し珍しいことです)、ブロックが完了した後、変更はコミットされていません - それでもロールすることができます必要に応じて戻ってください。END

DBMS_OUTPUT呼び出しはメッセージをバッファに入れ、ブロックの完了後にクライアント (SQL*Plus など) が取得して表示します。これを回避する方法はありません。そのメカニズムを使用して「ライブ」更新を取得することはできません。別のセッションから表示できるセッションのモジュール情報UTL_FILEを使用または設定するなどの代替手段がありますが、それはおそらくやり過ぎです。

各セクションの後にメッセージを表示したいだけの場合は、2 つの匿名ブロックに分割できます。その欠点は、おそらく変数を 2 回宣言する必要があり、それらがブロック間でスコープ外になることです。そのため、最初のブロックで設定したものが 2 番目のブロックでは表示されません。variableおそらく、SQL*Plusコマンドを介してバインド変数を使用して回避できます。

少なくともこの例では、PL/SQLでこれを行う必要はまったくないようですが、スクリプトにいくつかのロジックを適用すると言っていました。そうでない場合は、PL/SQL をまったく使用せずに、単純な SQL ステートメント、置換変数、およびプロンプトを使用してこれを実現できます。set feedback on行数は別として、「3行挿入」などの通常の表示だけに満足しない限り、少し注意が必要です。

于 2013-02-18T10:52:20.403 に答える
0

DBMS_OUTPUT の結果は、PL/SQL ブロックの完了後にのみ表示されます。DBMS_OUTPUT と COMMIT は相互に関連していません。スクリプトを複数のブロックに分割できる場合は、次のブロックが開始する前に、各ブロックの結果をコミットして出力できます。

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

begin
   -- step 2
   insert...
   commit ...
   dbms_output ...
end;
/
于 2013-02-18T10:53:07.473 に答える