Home » Developer & Programmer » Forms » Dynamically passing the Columns values (oracle 10g,oracle 11g)
Dynamically passing the Columns values [message #592144] Mon, 05 August 2013 00:04 Go to next message
chandan.rattan
Messages: 84
Registered: December 2008
Location: India
Member

HI all,

I am trying a pl/sql block which which take a string and execute it dynamically. Suppose below is string
 M_COL := Q'[(P_CODE=> ':DEPTNO',P_CODE_TYPE => 'STATE')]';

Now trying to execute it. using below

 M_STR := 'SELECT CHK_DEPT' || M_COL || ' FROM EMP WHERE EMPNO=''7499''';

  EXECUTE IMMEDIATE M_STR
    INTO M_DATE;


Now what i want is M_STR vairable to executed as
SELECT CHK_DEPT(P_CODE=> DEPTNO,P_CODE_TYPE => 'STATE') FROM EMP WHERE EMPNO='7499'
instead of

SELECT CHK_DEPT(P_CODE=> 'DEPTNO',P_CODE_TYPE => 'STATE') FROM EMP WHERE EMPNO='7499'

other in other way in parameter P_CODE Column value of DEPTNO should be passed.Also note that DEPTNO column in string M_COL is Dynamic.i.e

 M_COL := Q'[(P_CODE=> ':DEPTID',P_CODE_TYPE => 'STATE')]'; OR
 M_COL := Q'[(P_CODE=> ':EMP_ID',P_CODE_TYPE => 'STATE')]';


Any suggestions, Please share with me.

[Updated on: Mon, 05 August 2013 00:05]

Report message to a moderator

Re: Dynamically passing the Columns values [message #592146 is a reply to message #592144] Mon, 05 August 2013 00:40 Go to previous messageGo to next message
dariyoosh
Messages: 538
Registered: March 2009
Location: France
Senior Member
Hello,

I think what you're looking for is the USING clause of EXECUTE IMMEDIATE.

Here is an example

SET SQLBLANKLINES ON;
SET SERVEROUTPUT ON;

CREATE OR REPLACE FUNCTION incrFun(p_intVal IN PLS_INTEGER)
RETURN PLS_INTEGER
AUTHID CURRENT_USER
IS
BEGIN
    RETURN p_intVal + 1;
END incrFun;
/
SHOW ERRORS;



<<bk>>
DECLARE
    intVal  PLS_INTEGER := 12;
    result  PLS_INTEGER;
    STMT CONSTANT VARCHAR2(100) := 
        'SELECT incrFun(p_intVal=>:b_intVal) 
         FROM   "PUBLIC".dual';
BEGIN
    EXECUTE IMMEDIATE bk.STMT
        INTO    bk.result
        USING   IN  bk.intVal;
    sys.dbms_output.put_line('result = ' || bk.result);
END;
/

SET SERVEROUTPUT OFF;


Function created.

No errors.
result = 13

PL/SQL procedure successfully completed.

SQL> 


Regards,
Dariyoosh

[Updated on: Mon, 05 August 2013 01:05]

Report message to a moderator

Re: Dynamically passing the Columns values [message #592152 is a reply to message #592146] Mon, 05 August 2013 01:31 Go to previous messageGo to next message
chandan.rattan
Messages: 84
Registered: December 2008
Location: India
Member

Well not exactly ....but somwhow manage to resolved the problem. Thanks
Re: Dynamically passing the Columns values [message #592153 is a reply to message #592152] Mon, 05 August 2013 01:34 Go to previous messageGo to next message
dariyoosh
Messages: 538
Registered: March 2009
Location: France
Senior Member
chandan.rattan wrote on Mon, 05 August 2013 08:31
Well not exactly ....
What do you mean?

chandan.rattan wrote on Mon, 05 August 2013 08:31
but somwhow manage to resolved the problem.
Then please post your solution so we can see what you have done.

Regards,
Dariyoosh
Re: Dynamically passing the Columns values [message #592156 is a reply to message #592153] Mon, 05 August 2013 03:00 Go to previous messageGo to next message
chandan.rattan
Messages: 84
Registered: December 2008
Location: India
Member

I have created as function
FUNCTION FN_CONV_BIND_VAR(P_STR VARCHAR2) RETURN VARCHAR2 IS
    M_STR      VARCHAR2(4000);
    M_COL_1    VARCHAR2(60);
    M_COL_2    VARCHAR2(60);
    M_BIND_POS NUMBER;
    M_COMM_POS NUMBER;
    M_OCC      NUMBER;
  BEGIN
  
    M_STR := P_STR;
  
    M_OCC := LENGTH(M_STR) - LENGTH(REPLACE(M_STR, '&'));
  
    IF M_OCC > 0 THEN
    
      FOR I IN 1 .. M_OCC LOOP
      
        M_BIND_POS := INSTR(M_STR, '&');
      
        M_COMM_POS := INSTR(M_STR, '''', M_BIND_POS);
      
        DBMS_OUTPUT.PUT_LINE(M_COMM_POS || '<>' || M_BIND_POS);
      
        M_COL_1 := SUBSTR(M_STR,
                          M_BIND_POS + 1,
                          M_COMM_POS - M_BIND_POS - 1);
      
        M_COL_2 := SUBSTR(M_STR, M_BIND_POS, M_COMM_POS - M_BIND_POS);
      
        M_STR := REPLACE(M_STR, '''' || M_COL_2 || '''', M_COL_1);
      END LOOP;
    
      RETURN M_STR;
    
    ELSE
    
      RETURN M_STR;
    
    END IF;
  
  END;


Re: Dynamically passing the Columns values [message #592157 is a reply to message #592156] Mon, 05 August 2013 03:10 Go to previous messageGo to next message
dariyoosh
Messages: 538
Registered: March 2009
Location: France
Senior Member
Now I'm really confused about what you try to do and I don't really get the point of defining this function. Just to make sure that I understood the original problem correctly, you want to execute a dynamic SQL statement which is in fact a function call whose parameter list is to be defined at run time, is that your problem? If yes why don't you use the USING clause of the EXECUTE IMMEDIATE?

Regards,
Dariyoosh
Re: Dynamically passing the Columns values [message #592159 is a reply to message #592157] Mon, 05 August 2013 03:54 Go to previous messageGo to next message
chandan.rattan
Messages: 84
Registered: December 2008
Location: India
Member

Smile Well actually i found other way to resolve the problem.
CREATE OR REPLACE FUNCTION FN_CONV_BIND_VAR(P_STR VARCHAR2) RETURN VARCHAR2 IS
  M_STR      VARCHAR2(4000);
  M_COL_1    VARCHAR2(60);
  M_COL_2    VARCHAR2(60);
  M_BIND_POS NUMBER;
  M_COMM_POS NUMBER;
  M_OCC      NUMBER;
BEGIN

  M_STR := P_STR;

  M_OCC := LENGTH(M_STR) - LENGTH(REPLACE(M_STR, ':'));

  IF M_OCC > 0 THEN
  
    FOR I IN 1 .. M_OCC LOOP
    
      M_BIND_POS := INSTR(M_STR, ':');
    
      M_COMM_POS := INSTR(M_STR, '''', M_BIND_POS);
    
      DBMS_OUTPUT.PUT_LINE(M_COMM_POS || '<>' || M_BIND_POS);
    
      M_COL_1 := SUBSTR(M_STR, M_BIND_POS + 1, M_COMM_POS - M_BIND_POS - 1);
    
      M_COL_2 := SUBSTR(M_STR, M_BIND_POS, M_COMM_POS - M_BIND_POS);
    
      M_STR := REPLACE(M_STR, '''' || M_COL_2 || '''', M_COL_1);
    END LOOP;
  
    RETURN M_STR;
  
  ELSE
  
    RETURN M_STR;
  
  END IF;

END;


chk_dept function

CREATE OR REPLACE FUNCTION CHK_DEPT(P_CODE VARCHAR2,P_CODE_TYPE VARCHAR2) RETURN VARCHAR2 IS
  M_NAME DEPT.DNAME%TYPE;
BEGIN
  FOR I IN (SELECT DNAME FROM DEPT WHERE DEPTNO = P_CODE) LOOP
    M_NAME := I.DNAME;
  END LOOP;
  RETURN M_NAME;
END;


sql block

DECLARE
  M_COL    VARCHAR2(4000);
  M_STR    VARCHAR2(4000);
  M_RESULT VARCHAR2(4000);
BEGIN
  M_COL := Q'[(P_CODE=> ':DEPTNO',P_CODE_TYPE => 'STATE')]';
  DBMS_OUTPUT.PUT_LINE(M_COL);
  M_COL := FN_CONV_BIND_VAR(M_COL);
  DBMS_OUTPUT.PUT_LINE(M_COL);

  M_STR := 'SELECT CHK_DEPT' || M_COL || ' FROM EMP WHERE EMPNO=''7499''';

  EXECUTE IMMEDIATE M_STR
    INTO M_RESULT;
  DBMS_OUTPUT.PUT_LINE(M_RESULT);
END;
Re: Dynamically passing the Columns values [message #592161 is a reply to message #592159] Mon, 05 August 2013 04:05 Go to previous messageGo to next message
dariyoosh
Messages: 538
Registered: March 2009
Location: France
Senior Member
You may be able to find different solutions for a given problem (and all of them are not necessarily proper solutions). But that's not the point. My question was: do you need to write a dynamic SQL statement which is a function call, whose parameter list are to be defined at run time? If the answer is yes, then my second question is why don't you use the USING clause of the EXECUTE IMMEDIATE which allows in fact to bind values?

IMHO, answering the above questions worth more than searching alternative solutions.

Regards,
Dariyoosh
Re: Dynamically passing the Columns values [message #592163 is a reply to message #592161] Mon, 05 August 2013 04:25 Go to previous messageGo to next message
chandan.rattan
Messages: 84
Registered: December 2008
Location: India
Member

See dariyoosh,

USING clause of the EXECUTE IMMEDIATE i cannot use it as i have mentioned in my post that that its even string is dnamic
Quote:

Also note that DEPTNO column in string M_COL is Dynamic.i.e

M_COL := Q'[(P_CODE=> ':DEPTID',P_CODE_TYPE => 'STATE')]'; OR
M_COL := Q'[(P_CODE=> ':EMP_ID',P_CODE_TYPE => 'STATE')]'; OR
M_COL := Q'[(P_CODE=> ':SAL',P_CODE_TYPE => 'STATE')]';


So it M_COL may have any column which i wont be knowing in run time also.So thats why cannot use USING in excute immediate.

I didnt answer your question as i thought you would get idea from code that how i am trying other approach.
Re: Dynamically passing the Columns values [message #592164 is a reply to message #592163] Mon, 05 August 2013 04:39 Go to previous message
dariyoosh
Messages: 538
Registered: March 2009
Location: France
Senior Member
chandan.rattan wrote on Mon, 05 August 2013 11:25
USING clause of the EXECUTE IMMEDIATE i cannot use it as i have mentioned in my post that that its even string is dnamic

What do you mean its even string is dynamic? Are you talking about the function actual parameters?

chandan.rattan wrote on Mon, 05 August 2013 11:25

Also note that DEPTNO column in string M_COL is Dynamic.i.e

M_COL := Q'[(P_CODE=> ':DEPTID',P_CODE_TYPE => 'STATE')]'; OR
M_COL := Q'[(P_CODE=> ':EMP_ID',P_CODE_TYPE => 'STATE')]'; OR
M_COL := Q'[(P_CODE=> ':SAL',P_CODE_TYPE => 'STATE')]';

There is no department number in the above code.

chandan.rattan wrote on Mon, 05 August 2013 11:25

So it M_COL may have any column which i wont be knowing in run time also.So thats why cannot use USING in excute immediate.
A check department function that can accept as parameter: employee_id, salary and department_id and all of these values for the very same formal parameter ???? Check your application design !

Sorry I think I cannot continue this discussion anymore as I don't have the details of your tables/functions nor their description.

However, I think you should have a look at PL/SQL Language Reference: 7 PL/SQL Dynamic SQL

Regards,
Dariyoosh
Previous Topic: Where i can use Clear_List?
Next Topic: ora-03113 end of file communication
Goto Forum:
  


Current Time: Fri Apr 26 09:39:58 CDT 2024