PL/SQL heartbeat Query has errors


 
Thread Tools Search this Thread
Top Forums Programming PL/SQL heartbeat Query has errors
# 1  
Old 04-17-2013
PL/SQL heartbeat Query has errors

Hello, I want to query something simple which works as a standalone sqlplus query perfectly:

Table statements:
Code:
ALTER TABLE MP$PATHLOADER.ISALIVE
 DROP PRIMARY KEY CASCADE;

DROP TABLE MP$PATHLOADER.ISALIVE CASCADE CONSTRAINTS;

CREATE TABLE MP$PATHLOADER.ISALIVE
(
   ISALIVE_PK   NUMBER,
   INSERTTS     TIMESTAMP (6) NOT NULL,
   UPDATETS     TIMESTAMP (6) NOT NULL,
   VERSIONID    NUMBER NOT NULL,
   NAME         VARCHAR2 (256 CHAR) NOT NULL,
   ACTIVE       NUMBER (1) DEFAULT 0 NOT NULL
);


CREATE UNIQUE INDEX MP$PATHLOADER.ISALIVE_PK
   ON MP$PATHLOADER.ISALIVE (ISALIVE_PK);


ALTER TABLE MP$PATHLOADER.ISALIVE
ADD (  CONSTRAINT ISALIVE_PK PRIMARY KEY (ISALIVE_PK)
USING INDEX MP$PATHLOADER.ISALIVE_PK);

A Testvalue as follow:
Code:
Insert into MP$PATHLOADER.ISALIVE
   (ISALIVE_PK, 
    INSERTTS, UPDATETS, VERSIONID, NAME, ACTIVE)
 Values
   (3, TO_TIMESTAMP('01/21/2013 15:29:02,000000','MM/DD/YYYY HH24:MI:SS,FF'), TO_TIMESTAMP('01/24/2013 13:49:40,013000','MM/DD/YYYY HH24:MI:SS,FF'), 8781, '010123vb', 
    1);

And now the query for getting the differences in minutes between the timestamps:

Code:
(SELECT ABS (
             TO_NUMBER (TO_CHAR (updatets, 'dd')) * 24 * 60
           + TO_NUMBER (TO_CHAR (updatets, 'hh24')) * 60
           + TO_NUMBER (TO_CHAR (updatets, 'mi'))
           - TO_NUMBER (TO_CHAR (SYSDATE, 'dd')) * 24 * 60
           - TO_NUMBER (TO_CHAR (SYSDATE, 'hh24')) * 60
           - TO_NUMBER (TO_CHAR (SYSDATE, 'mi')))
           AS BACKLOG_MINUTES
   FROM MP$PATHLOADER.ISALIVE
  WHERE active = '1');

But then in a PL/SQL Script this does not further work anymore:

Code:
SET SERVEROUTPUT ON
SET FEEDBACK OFF

DECLARE
   CTABLES   VARCHAR2 (20);
BEGIN
   EXECUTE IMMEDIATE
      (SELECT ABS (
                   TO_NUMBER (TO_CHAR (updatets, 'dd')) * 24 * 60
                 + TO_NUMBER (TO_CHAR (updatets, 'hh24')) * 60
                 + TO_NUMBER (TO_CHAR (updatets, 'mi'))
                 - TO_NUMBER (TO_CHAR (SYSDATE, 'dd')) * 24 * 60
                 - TO_NUMBER (TO_CHAR (SYSDATE, 'hh24')) * 60
                 - TO_NUMBER (TO_CHAR (SYSDATE, 'mi')))
         INTO CTABLES
         FROM MP$PATHLOADER.ISALIVE
        WHERE active = '1');

   DBMS_OUTPUT.PUT_LINE (CTABLES);
END;
/

Could someone lend me his helping hand, please!

Thanks a lot!
# 2  
Old 04-17-2013
You did not mention how this did not work. Errors or Warnings if any?

By the way EXECUTE IMMEDIATE statement is usually used to execute a dynamic SQL statement or anonymous PL/SQL block.

So in your PL/SQL I guess it is not required:
Code:
SET SERVEROUTPUT ON
SET FEEDBACK OFF

DECLARE
   CTABLES   VARCHAR2 (20);
BEGIN
      SELECT ABS (
                   TO_NUMBER (TO_CHAR (updatets, 'dd')) * 24 * 60
                 + TO_NUMBER (TO_CHAR (updatets, 'hh24')) * 60
                 + TO_NUMBER (TO_CHAR (updatets, 'mi'))
                 - TO_NUMBER (TO_CHAR (SYSDATE, 'dd')) * 24 * 60
                 - TO_NUMBER (TO_CHAR (SYSDATE, 'hh24')) * 60
                 - TO_NUMBER (TO_CHAR (SYSDATE, 'mi')))
         INTO CTABLES
         FROM MP$PATHLOADER.ISALIVE
        WHERE active = '1';
   DBMS_OUTPUT.PUT_LINE (CTABLES);
END;
/

# 3  
Old 04-18-2013
Quote:
Originally Posted by sdohn
...And now the query for getting the differences in minutes between the timestamps:

Code:
(SELECT ABS (
             TO_NUMBER (TO_CHAR (updatets, 'dd')) * 24 * 60
           + TO_NUMBER (TO_CHAR (updatets, 'hh24')) * 60
           + TO_NUMBER (TO_CHAR (updatets, 'mi'))
           - TO_NUMBER (TO_CHAR (SYSDATE, 'dd')) * 24 * 60
           - TO_NUMBER (TO_CHAR (SYSDATE, 'hh24')) * 60
           - TO_NUMBER (TO_CHAR (SYSDATE, 'mi')))
           AS BACKLOG_MINUTES
   FROM MP$PATHLOADER.ISALIVE
  WHERE active = '1');

...
Difference between which two timestamps?
It obviously is not the difference between "updatets" and "insertts", because "insertts" is not being used in your query.
If you are trying to find out the difference between "updatets" and "sysdate" (or current time), then consider the output of the query:

Code:
SQL>
SQL> select * from isalive;
ISALIVE_PK INSERTTS                       UPDATETS                        VERSIONID NAME           ACTIVE
---------- ------------------------------ ------------------------------ ---------- ---------- ----------
         3 21-JAN-13 03.29.02.000000 PM   24-JAN-13 01.49.40.013000 PM         8781 010123vb            1
1 row selected.
SQL>
SQL>
SQL> SELECT ABS (
  2                   TO_NUMBER (TO_CHAR (updatets, 'dd')) * 24 * 60
  3                 + TO_NUMBER (TO_CHAR (updatets, 'hh24')) * 60
  4                 + TO_NUMBER (TO_CHAR (updatets, 'mi'))
  5                 - TO_NUMBER (TO_CHAR (SYSDATE, 'dd')) * 24 * 60
  6                 - TO_NUMBER (TO_CHAR (SYSDATE, 'hh24')) * 60
  7                 - TO_NUMBER (TO_CHAR (SYSDATE, 'mi'))
  8             )
  9             AS BACKLOG_MINUTES
 10     FROM ISALIVE
 11    WHERE active = '1';
 
BACKLOG_MINUTES
---------------
           9381
 
1 row selected.
 
SQL>
SQL>

The "updatets" shows a timestamp of 24-Jan-2013 and sysdate would be some day around 18-Apr-2013 (wherever you are on the planet Earth as of now). So the difference should be about 84 days, or 84*24*60 = 302400 minutes.

Since SYSDATE is like a "running target", let's use a fixed date to see how the query behaves. I'll use the date "2/24/2013 13:48:41" as my "current date" in the following query:

Code:
SQL>
SQL> select
  2         x + y + z               as min_1,
  3         p + q + r               as min_2,
  4         x + y + z - (p + q + r) as backlog_min
  5    from (
  6            SELECT
  7                   TO_NUMBER (TO_CHAR (updatets, 'dd')) * 24 * 60 as x,
  8                   TO_NUMBER (TO_CHAR (updatets, 'hh24')) * 60    as y,
  9                   TO_NUMBER (TO_CHAR (updatets, 'mi'))           as z,
 10                   --
 11                   TO_NUMBER (TO_CHAR (dt.now, 'dd')) * 24 * 60  as p,
 12                   TO_NUMBER (TO_CHAR (dt.now, 'hh24')) * 60     as q,
 13                   TO_NUMBER (TO_CHAR (dt.now, 'mi'))            as r
 14              FROM ISALIVE,
 15                   (
 16                     select TO_DATE('02/24/2013 13:48:41', 'MM/DD/YYYY HH24:MI:SS') as now from dual
 17                   ) dt
 18             WHERE active = '1'
 19         )
 20  /
 
     MIN_1      MIN_2 BACKLOG_MIN
---------- ---------- -----------
     35389      35388           1
 
1 row selected.
 
SQL>
SQL>
SQL>

Now, the difference between "24-JAN-2013 13:49:40" and "24-FEB-2013 13:48:41" is about 30 days, or approximately 30*24*60 = 43200 minutes but the query above returns exactly 1 minute as the difference.

The fallacy in the logic would be clear if you see what is being done here. Each date is converted to minutes from the start of its own month.
So "24-JAN-2013 13:49:40" is 35389 minutes from "1-JAN-2013".
And "24-FEB-2013 13:48:41" is 35388 minutes from "1-FEB-2013".
And so the difference is 1 minute.

So if the two dates ("updatets" and SYSDATE) lie in the same month, then you'll start counting from the same date (beginning of that month) and in that case your query will work. Otherwise it won't.

For example, if the "updatets" is, say, "31-MAR-2013 23:59:59" and you run your query just one second later (when the month has changed), then the result will be incorrect.

In Oracle, the difference between two DATEs is the number of days between them. If the difference has a fractional part, then that corresponds to the number of minutes and seconds in addition to the days in between. So, the difference in minutes between two DATEs is given by this expression -

Code:
(date_1 - date_2) * 24 * 60

Using this information, the query could be written thusly -

Code:
SQL>
SQL>
SQL> SELECT
  2         updatets,
  3         TO_CHAR (dt.now, 'DD-MON-YY HH:MI:SS AM') as now,
  4         (dt.now - CAST (updatets AS DATE))*24*60  as diff_in_min
  5    FROM ISALIVE,
  6         (
  7           select TO_DATE('02/24/2013 13:48:41', 'MM/DD/YYYY HH24:MI:SS') as now from dual
  8         ) dt
  9   WHERE active = '1'
 10  /
 
UPDATETS                       NOW                   DIFF_IN_MIN
------------------------------ --------------------- -----------
24-JAN-13 01.49.40.013000 PM   24-FEB-13 01:48:41 PM  44639.0167
 
1 row selected.
 
SQL>
SQL>

Another example where the difference is about 1 minute:

Code:
SQL>
SQL>
SQL> SELECT
  2         updatets,
  3         TO_CHAR (dt.now, 'DD-MON-YY HH:MI:SS AM') as now,
  4         (dt.now - CAST (updatets AS DATE))*24*60  as diff_in_min
  5    FROM ISALIVE,
  6         (
  7           select TO_DATE('01/24/2013 13:50:41', 'MM/DD/YYYY HH24:MI:SS') as now from dual
  8         ) dt
  9   WHERE active = '1'
 10  /
 
UPDATETS                       NOW                   DIFF_IN_MIN
------------------------------ --------------------- -----------
24-JAN-13 01.49.40.013000 PM   24-JAN-13 01:50:41 PM  1.01666667
 
1 row selected.
 
SQL>
SQL>
SQL>

I used the CAST function because the datatype of "updatets" is TIMESTAMP.
Accordingly, your query would be -

Code:
select (sysdate - cast(updatets as date))*24*60 as diff_in_min from isalive where active = '1';


Last edited by durden_tyler; 04-18-2013 at 03:10 AM..
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Programming

Help writing SQL query

Hello All, I hope I'm posting this in the right section. I have zero sql query writing skill, in fact, I've never done it before, but for some reason, a request came across my desk to get information from one of our databases. I have about 200 ticket numbers that have no information attached,... (8 Replies)
Discussion started by: bbbngowc
8 Replies

2. Programming

Getting error in sql query

Hi All , I have tried many times am getting syntax error on 'UNION' can anybody tell me ... INSERT INTO table1 ( Type , num_items , num_letters , total_value ) (select type='1', num_items, num_letters=count(*), total_value=sum(letter_value) from table2 where num_items = 1 (1 Reply)
Discussion started by: Venkatesh1
1 Replies

3. Shell Programming and Scripting

Run SQL thru shell script: how to get a new line when run sql query?

Hi, this's Pom. I'm quite a new one for shell script but I have to do sql on shell script to query some information from database. I found a concern to get a new line...When I run my script, it retrieves all data as wondering but it's shown in one line :( What should I do? I'm not sure that... (2 Replies)
Discussion started by: Kapom
2 Replies

4. Shell Programming and Scripting

problem in SQL query

I used the following code code select * from tablename where columnname Instead of printing the expected output it prints all the files in the present directory since there is a "*" in the code. Is there any way to overcome the problem? Thanks Ananth (2 Replies)
Discussion started by: Ananthdoss
2 Replies

5. Shell Programming and Scripting

create sql query

Hi Everyone, Can anyone pls help me out......with my requirement, i am struggling since 3 days. Please find the requirement below my file contains below data R1|Array/Network Resistor - VIP|V_RES_CLASS|V_MOUNT_FEATURE|SURFACE MOUNT|AND|8533.10.00.20|8533.10.00.20| R1|Array/Network Resistor... (9 Replies)
Discussion started by: jam_prasanna
9 Replies

6. Shell Programming and Scripting

How to use sql data file in unix csv file as input to an sql query from shell

Hi , I used the below script to get the sql data into csv file using unix scripting. I m getting the output into an output file but the output file is not displayed in a separe columns . #!/bin/ksh export FILE_PATH=/maav/home/xyz/abc/ rm $FILE_PATH/sample.csv sqlplus -s... (2 Replies)
Discussion started by: Nareshp
2 Replies

7. UNIX and Linux Applications

SQL Lite query

Hello Everyone, I am looking to write a script that will run on many machines in a network at the same time. They need to write a result to a common location. I plan to use a SQLlite database as this common writing point. But the concern I have is how SQLlite will react to multiple writes that... (1 Reply)
Discussion started by: garric
1 Replies

8. Shell Programming and Scripting

how to handle sql loader errors in unix

hi all, how to handle sql loader errors in unix shell ?? thanks in advance gemini (3 Replies)
Discussion started by: gemini106
3 Replies

9. Shell Programming and Scripting

rsh and sql query

Hi ... I am doing a switch user and then rsh and then running a sql query . I am successfull in rsh and logging into the database , but my query doesnt run .. Here's the command : su - linus -c "rsh -l linus psmf ORACLE_SID=SMP;export ORACLE_SID;sqlplus... (1 Reply)
Discussion started by: sars
1 Replies

10. Shell Programming and Scripting

& in SQL query

I have a script that looks for all jobs that contain a particular calendar. Some of the calendars have '&' in them and sql freaks out when it encounters that.. is there a way around this? I have tried: select job_name from job where run_calendar='1&15dom' select job_name from job... (3 Replies)
Discussion started by: Lindarella
3 Replies
Login or Register to Ask a Question