Oracle 是否可以将提交应用于脚本中的每个插入?

Oracle 是否可以将提交应用于脚本中的每个插入?,oracle,commit,transaction-isolation,Oracle,Commit,Transaction Isolation,我刚刚从SQL Server迁移到ORACLE,正在编写一个脚本(SQL Server风格)。 在SQL Server中,在脚本中应用一些逻辑后,我们使用BEING-END-TRAN。这可以在开始-结束块内完成。 在甲骨文,我发现这有点困难。在这个网站上进行了大量的谷歌搜索之后,我仍然不清楚如何才能满足这个要求 当我运行脚本(粘贴在下面)时,它作为一个事务运行。一旦整个脚本执行完毕,DBMS_OUTPUT.Put_行也会显示出来。 有没有办法在每次提交后打印DBMS_OUTPUT.Put_行 此

我刚刚从SQL Server迁移到ORACLE,正在编写一个脚本(SQL Server风格)。 在SQL Server中,在脚本中应用一些逻辑后,我们使用BEING-END-TRAN。这可以在开始-结束块内完成。 在甲骨文,我发现这有点困难。在这个网站上进行了大量的谷歌搜索之后,我仍然不清楚如何才能满足这个要求

当我运行脚本(粘贴在下面)时,它作为一个事务运行。一旦整个脚本执行完毕,DBMS_OUTPUT.Put_行也会显示出来。 有没有办法在每次提交后打印DBMS_OUTPUT.Put_行

此外,如果有任何其他方法可以处理此脚本,我也愿意接受这些想法,以便在脚本移动到下一个子查询之前提交每个子查询。。。请让我知道

这是我的剧本:

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;
/

Oracle中的通常做法是仅在业务事务完成时提交,这样事务就不会被部分处理。这与其他一些系统不同,因为Oracle的多版本控制和锁定系统确保写入程序不会阻止读卡器,读卡器也不会阻止写入程序

对于DBMS_输出问题,在执行块的过程中,不能通过DBMS_输出从服务器获得响应。您可能想看看如何使用Utl_文件将数据写入服务器端文件

其他想法:

  • 如果要删除每一行并且不需要对该表使用外键,请考虑使用TRUNCATE而不是DELETE。TRUNCATE有一个与之关联的隐式提交,因此在过程开始时应用所有的TRUNCATE

  • 如果您正在加载批量数据,需要维护索引,并且不需要允许多个同时插入到表中,请考虑在插入上使用APPEND提示来调用直接路径插入

  • 我猜插入的ORDER BY是有原因的——通常在Oracle中,它将确保数据行在ORDER BY列上进行物理聚集,这将提高通过这些列进行基于索引的访问的效率。使用直接路径插入将有助于保证物理行顺序,但如果不需要集群,则通过


Oracle的通常做法是仅在业务事务完成时提交,这样事务就不会被部分处理。这与其他一些系统不同,因为Oracle的多版本控制和锁定系统确保写入程序不会阻止读卡器,读卡器也不会阻止写入程序

对于DBMS_输出问题,在执行块的过程中,不能通过DBMS_输出从服务器获得响应。您可能想看看如何使用Utl_文件将数据写入服务器端文件

其他想法:

  • 如果要删除每一行并且不需要对该表使用外键,请考虑使用TRUNCATE而不是DELETE。TRUNCATE有一个与之关联的隐式提交,因此在过程开始时应用所有的TRUNCATE

  • 如果您正在加载批量数据,需要维护索引,并且不需要允许多个同时插入到表中,请考虑在插入上使用APPEND提示来调用直接路径插入

  • 我猜插入的ORDER BY是有原因的——通常在Oracle中,它将确保数据行在ORDER BY列上进行物理聚集,这将提高通过这些列进行基于索引的访问的效率。使用直接路径插入将有助于保证物理行顺序,但如果不需要集群,则通过


数据将分两个阶段提交。
声明
/
开始
/
结束
表示匿名事务的开始和结束,而不是事务。如果在块内根本没有提交(这更正常;在块内有事务控制有点不寻常),那么在块完成后,您的任何更改都不会提交——如果您愿意,您仍然可以回滚

您的调用将消息放入缓冲区,客户端(例如SQL*Plus)在块完成后检索并显示该缓冲区。这是没有办法的-你不能使用这种机制获得“实时”更新。还有一些替代方法,例如使用
UTL_文件
,或者用于可以从另一个会话查看的会话,但是对于您似乎正在做的事情来说,这可能有些过头了

如果您只想在每个部分后看到消息,可以将其拆分为两个匿名块。这样做的缺点可能是必须声明两次变量,并且它们将超出块之间的范围-因此您在第一个块中设置的内容在第二个块中不可见。您也许可以通过SQL*Plus
variable
命令使用绑定变量来解决这个问题


您似乎根本不需要在PL/SQL中这样做,至少在本例中是这样,尽管您说过您将在脚本中应用一些逻辑。如果事实并非如此,那么您可以使用简单的SQL语句、替换变量和提示符来实现这一点,而不必使用PL/SQL。除了行计数之外,这有点棘手,除非您对正常的
设置反馈感到满意,如“插入3行”。

数据将分两个阶段提交。
声明
/
开始
/
结束
表示匿名事务的开始和结束,而不是事务。如果在块内根本没有提交(这更正常;在块内有事务控制有点不寻常),那么在块完成后,您的任何更改都不会提交——如果您愿意,您仍然可以回滚

您的调用将消息放入缓冲区,客户端(例如SQL*Plus
begin
   -- step 1
   insert 
   commit ...
   dbms_output ...
end;
/

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