0

Thanks for looking...

I've spent hours researching this and I can't believe it's that difficult to do something in PL/SQL that is simple in TSQL.

I have a simple query that joins 2 tables:

     Select DISTINCT
      to_char(TO_DATE('1899123000', 'yymmddhh24')+ seg.NOM_DATE, 'mm/dd/yyyy') AS "Record Date"
    , cd.CODE
    , EMP.ID
    , EMP.SHORT_NAME

    FROM
     EWFM.GEN_SEG seg join EWFM.SEG_CODE cd ON seg.SEG_CODE_SK = cd.SEG_CODE_SK
     join EMP on seg.EMP_SK = EMP.EMP_SK
    where NOM_DATE = vMyDate;

I use Toad Date Point and I'm querying against an Oracle Exadata source. The resulting query will be dropped into a visualization tool like QlikView or Tableau. I'd like to create a simple variable to use the the WHERE clause as you can see in the code.

In this example, NOM_DATE is an integer such as 42793 (2/27/2017) as you can see in the first row "Record Date". Nothing new here, not very exciting... Until... I tried to create a variable to make the query more dynamic.

I've tried a surprising variety of examples found here, all have failed. Such as:
declare myDate number(8); Begin myDate := 42793; --Fail ORA-06550 INTO Clause is expected

variable nomDate NUMBER
DEFINE nomDate = 42793
EXEC : nomDate := ' & nomDate'
...where NOM_DATE = ( & nomDate) ;

--ORA-00900: invalid SQL statement

and

variable nomDate NUMBER;
EXEC nomDate := 42793;
select count(DET_SEG_SK) from DET_SEG
where NOM_DATE = :nomDate;

--ORA-00900: invalid SQL statement

and several more.. hopefully you get the idea. I've spent a few hours researching stackoverflow for a correct answer but as you can see, I'm asking you. From simple declarations like "Var" to more complex " DECLARE, BEGIN, SELECT INTO...." to actually creating Functions, using cursors to iterate the output.... I still can't make a simple variable to use in a Where clause.

Please explain the error of my ways.

--Forlorn SQL Dev

6
  • Firstly, I assume you mean PL/SQL, not TSQL. Secondly, I tried you first example, and I do not see a problem; it works for me. So I think it's must be something very simple or very bizarre ! Can you cut/paste your whole (first) example? Commented Mar 1, 2017 at 19:11
  • Inside PL/SQL (a named package/procedure/function etc) you can just declare variables in the declare section and then refer to them wherever you like. Your example beginning declare mydate number(8); works fine (just needs an end;) and I can't see how it could give INTO clause is expected since that only applies to select statements. The variable and define syntax is really from the SQL*Plus command line tool which is emulated in various ways by desktop applications so you may need to explain how you are running it. Commented Mar 1, 2017 at 19:14
  • My guess is that the problem is not the variable declaration but the report output - something like stackoverflow.com/questions/351489/… Commented Mar 1, 2017 at 19:19
  • BobC: here's the first example in it's entirety ' declare myDate number(8); Begin myDate := 42793; SELECT DISTINCT to_char(TO_DATE('1899123000', 'yymmddhh24')+ seg.NOM_DATE, 'mm/dd/yyyy') AS "Record Date" , cd.CODE , EMP.ID , EMP.SHORT_NAME , seg.MEMO , seg.AUDIT_INS_DATE FROM EWFM.GEN_SEG seg join EWFM.SEG_CODE cd ON seg.SEG_CODE_SK = cd.SEG_CODE_SK join EMP on seg.EMP_SK = EMP.EMP_SK where NOM_DATE = myDate; end; ' Thanks for the interest Commented Mar 1, 2017 at 19:43
  • @mf.cummings. I don't see your example... Commented Mar 1, 2017 at 19:44

3 Answers 3

1

Since you are using an implicit cursor, you have to select then INTO variables. Now I d not know the data types of you variables, so I have just guessed in this example below, but hopefully you get the point.

Two other things I should mention

  1. Why are you TO_CHARing you DATE. Just use a DATE datatype. Also, I think your format mask is wrong too 1899123000 does not match yymmddhh24.
  2. In explicit cursor expects exactly one row; no rows and you get NO_DATA_FOUND; more than one and you get TOO_MANY_ROWS
Declare 
   myDate number(8) := 42793; 
    /* These 4 variable data types are a guess */
   v_record_date varchar2(8);
   v_cd_code varchar2(10);
   v_emp_id number(4);
   v_emp_short_name varchar2(100);
 BEGIN 
 Select DISTINCT to_char(TO_DATE('1899123000', 'yymmddhh24')
                     + eg.NOM_DATE, 'mm/dd/yyyy') AS "Record Date" 
 , cd.CODE 
 , EMP.ID 
 , EMP.SHORT_NAME 
 INTO v_record_date, v_cd_code, v_emp_id, v_emp_short_name
 FROM EWFM.GEN_SEG seg 
 join EWFM.SEG_CODE cd 
   ON seg.SEG_CODE_SK = cd.SEG_CODE_SK 
 join EMP 
     on seg.EMP_SK = EMP.EMP_SK 
 where NOM_DATE = myDate; 
 END;
 /
Sign up to request clarification or add additional context in comments.

Comments

1
VARIABLE vMyDate NUMBER;

BEGIN
  :vMyDate  := 42793;
END;
/

-- or
-- EXEC :vMyDate := 42793;

SELECT DISTINCT
       TO_CHAR( DATE '1899-12-30' + seg.NOM_DATE, 'mm/dd/yyyy') AS "Record Date"
     , cd.CODE
     , EMP.ID
     , EMP.SHORT_NAME
FROM   EWFM.GEN_SEG seg
       join EWFM.SEG_CODE cd
       ON seg.SEG_CODE_SK = cd.SEG_CODE_SK
       join EMP
       on seg.EMP_SK = EMP.EMP_SK
WHERE  NOM_DATE = :vMyDate;

1 Comment

So Close! I typed it almost exactly omitting the / after END; (I was under the impression that was a SQL* command to treat the lines as a block) and it failed. I did it again with the / and the Bind Variable box popped up 2x, I entered the correct value in it both times and it ran as expected. I have more to learn about binding variables but this is the closest to correct answer yet.
0

You put the variables with getter and setter in a package.

Then use a view that uses the package getter

Personally I prefer to use a collection that way I can do a select * from table (packagage.func(myparam))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.