如何用DBMS_OUTPUT.PUT_LINE打印出当前时间?

时间:2018-05-22 07:56:14

标签: database oracle plsql timestamp oracle-sqldeveloper

我使用以下代码执行导出数据泵。

set serveroutput on;
DECLARE
  ind NUMBER;              -- Loop index
  h1 NUMBER;               -- Data Pump job handle
  percent_done NUMBER;     -- Percentage of job complete
  job_state VARCHAR2(30);  -- To keep track of job state
  le ku$_LogEntry;         -- For WIP and error messages
  js ku$_JobStatus;        -- The job status from get_status
  jd ku$_JobDesc;          -- The job description from get_status
  sts ku$_Status;          -- The status object returned by get_status
  >>>>>>>>>>>>>>v_systimestamp TIMESTAMP := SYSTIMESTAMP;<<<<<<<<<<<<<<

BEGIN

  h1 := DBMS_DATAPUMP.OPEN('EXPORT','SCHEMA',NULL,'EXAMPLE3','LATEST');

  DBMS_DATAPUMP.ADD_FILE(h1, 'dumpfile.dmp', 'EXPORT_DIRECTORY', NULL, DBMS_DATAPUMP.KU$_FILE_TYPE_DUMP_FILE, 1);

  DBMS_DATAPUMP.METADATA_FILTER(h1,'SCHEMA_EXPR','IN (''SchemaName'')');

  DBMS_DATAPUMP.START_JOB(h1);



  percent_done := 0;
  job_state := 'UNDEFINED';
  while (job_state != 'COMPLETED') and (job_state != 'STOPPED') loop
             DBMS_OUTPUT.PUT_LINE(v_systimestamp);
    dbms_datapump.get_status(h1,
           dbms_datapump.ku$_status_job_error +

           dbms_datapump.ku$_status_job_status +
           dbms_datapump.ku$_status_wip,-1,job_state,sts);
    js := sts.job_status;

-- If the percentage done changed, display the new value.

    if js.percent_done != percent_done
    then

      dbms_output.put_line('*** Job percent done = ' ||
                           to_char(js.percent_done));
      percent_done := js.percent_done;
    end if;

-- If any work-in-progress (WIP) or error messages were received for the job,
-- display them.

   if (bitand(sts.mask,dbms_datapump.ku$_status_wip) != 0)
    then

      le := sts.wip;
    else
      if (bitand(sts.mask,dbms_datapump.ku$_status_job_error) != 0)
      then
        le := sts.error;
      else
        le := null;
      end if;
    end if;
    if le is not null
    then
      ind := le.FIRST;
      while ind is not null loop
        >>>>>>>>>>>>>>DBMS_OUTPUT.PUT_LINE(v_systimestamp);<<<<<<<<<<<<<<
        dbms_output.put_line(le(ind).LogText);
        ind := le.NEXT(ind);
      end loop;
    end if;
  end loop;

-- Indicate that the job finished and detach from it.

  dbms_output.put_line('Job has completed');
  dbms_output.put_line('Final job state = ' || job_state);
  dbms_datapump.detach(h1);
END;

问题是出口需要太长时间。使用此SQL代码需要25分钟。架构的大小为1.8 GB。

我想知道个别步骤花了多少时间。这就是我想在每个流程步骤之后插入时间戳的原因。然后我可以看到个别步骤需要多长时间。

我在代码中用(&gt;&gt;&gt;&gt;&lt;&lt;&lt;&lt;&lt;)标记了时间戳的代码。

时间戳没有更新时间。每个过程后我都需要CURRENT时间。你能救我吗?

3 个答案:

答案 0 :(得分:1)

在您的代码中,您将在脚本开头设置v_systimestamp的值 - 这在整个脚本运行期间不会更改。您可以在记录之前重置该值:

v_systimestamp TIMESTAMP := SYSTIMESTAMP
DBMS_OUTPUT.PUT_LINE(v_systimestamp)

或在您想要监控的每个部分之前和之后执行以下操作(不需要变量):

DBMS_OUTPUT.PUT_LINE('Time Started: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS'));

DBMS_OUTPUT.PUT_LINE('Time Ended: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS'));

答案 1 :(得分:1)

此处示例'CURRENT_TIMESTAMP'

curDateTime  TIMESTAMP := CURRENT_TIMESTAMP ;
DBMS_OUTPUT.PUT_LINE('CUR TIME '|| curDateTime);

答案 2 :(得分:0)

如果您运行的程序需要很长时间,DBMS_OUTPUT.PUT_LINE不会有太大帮助。好吧,它会显示一些东西,但是 - 当你使用循环时,根据迭代次数,DBMS_OUTPUT可能会超出缓冲区大小或超出SQL * Plus中的可见行数(如果你使用它),你将失去部分输出。

此外,在程序结束之前,您不会看到DBMS_OUTPUT.PUT_LINE的单个字母

因此,我建议您使用另一种方法 - 一种简单的日志记录,需要一个表,一个序列和一个(自治事务)过程。这是脚本:

CREATE TABLE a1_log
(
   id      NUMBER,
   datum   DATE,
   descr   VARCHAR2 (500)
);

CREATE SEQUENCE seqlognap START WITH 1 INCREMENT BY 1;

CREATE OR REPLACE PROCEDURE a1_p_log (par_descr IN VARCHAR2)
IS
   PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
   INSERT INTO a1_log
      SELECT seqlognap.NEXTVAL, SYSDATE, par_descr FROM DUAL;

   COMMIT;
END a1_p_log;

然后将A1_P_LOG调用放入您自己的过程中;

之类的东西
begin
  a1_p_log('selecting from a large table');
  select ... into ... from ...;

  a1_p_log('entering the loop');
  while ... loop
    a1_p_log('doing something');
  end loop;

  a1_p_log('the end');
end;

这里自治事务很重要 - 它会在日志表中提交插入(不影响主事务),因此您可以(在另一个会话中)跟踪执行,只需通过反复发布

  SELECT *
    FROM a1_log
ORDER BY id;

它会显示(想象中的例子):

1   22.05.2018 18:13:00    selecting from a large table
2   22.05.2018 18:20:07    entering the loop
3   22.05.2018 18:20:07    doing something
4   22.05.2018 18:20:08    doing something
5   22.05.2018 18:20:09    doing something
6   22.05.2018 18:20:10    the end

并且您会发现第1步需要7分钟才能执行,因此 - 这就是您需要调查的内容。这意味着您不必等待主程序完成 - 取消它并开始解决瓶颈问题。修好后,再次运行一切。