Including variable into dynamic sql

Hi,
Ive problems including v_end_month variable.
which is the correct way to include v_end_month in the next dynamic sql expression?
v_end_month DATE;
v_max_day DATE;
EXECUTE IMMEDIATE 'SELECT max(date) FROM table1 WHERE trunc(date,''mm'') = '''||v_end_month||'' INTO v_max_day;thanks in advanced..

what is the way to know if I need the statement to be dynamic in the first place?Are you building the SQL string with, for example, a variable table name?
More generally, is there any part of the statement that's not known at runtime?
If the answer's no, then you don't need dynamic SQL, just use :
SELECT max(dt)
INTO v_max_day
FROM table1
WHERE trunc(dt, 'MM') = v_end_month
;

Similar Messages

  • Problem returning variables from dynamic SQL/PLSQL

    Hi, I have a problem I am trying to solve using a very short piece of dynamic SQL or PLSQL but I am having problems getting the variable values out of the dynamic block.
    I have 16 counters whose names are made up of three variable parts - 'scheme', 'contributory category' and 'employment category'
    The 'scheme' can be either 'no1', 'no2', 'off', 'cg' or 'amc'
    The 'contributory category' can be either 'cont' or 'noncont'
    The 'employment category' can be either 'ft' or 'pt'
    (There are only 16 because only 16 combinations are possible)
    For example the total counter name could be 'v_cg_noncont_ft_count'
    I have created a variable by concatenating the various elements called v_incr_count_name which holds the name of the counter I want to increment.
    I am running this whole thing within an anonymous PLSQL block so I cannot use global variables meaning that my variables are not visible within a dynamic PLSQL block.
    I believe this means that either I need to bind the variables within a PLSQL block or use a SELECT FROM INTO SQL block.
    I have tried a few solutions with no luck such as the following PLSQL:
    v_incr_count := 'v_'||v_scheme||'_'||v_cont_cat||'_'||v_emp_cat||'_count';
    sql_stmt := 'BEGIN :a := :a + 1; END;';
    EXECUTE IMMEDIATE sql_stmt USING v_incr_count_name;
    Unfortunately I am getting the 'IN bind variable bound to an OUT position' error which I believe is because it is trying to return a value into v_incr_count_name which has been defined by default as an IN variable. The problem is that I need to store the returned value into the variable whose name is stored in v_incr_count_name.
    Another solution I tried is:
    v_incr_count_name := 'v_'||v_scheme||'_'||v_cont_cat||'_'||v_emp_cat||'_count';
    sql_stmt := 'SELECT '||v_incr_count_name||' + 1 FROM DUAL';
    EXECUTE IMMEDIATE sql_stmt INTO v_return;
    This solution gives me an 'Invalid colum error'
    Any help would be greatly appreciated
    Cheers, Dan

    Repost:
    Problem with variables in dynamic SQL/PLSQL

  • Problem with variables in dynamic SQL/PLSQL

    Hi, I have a problem I am trying to solve using a very short piece of dynamic SQL/PLSQL but I am having problems getting the variable values out of the dynamic block.
    I need to increment a counter which could be any one of 16 counters I am using and I want to avoid using nested IF statements.
    The variable to be incremented is made up of the 'scheme', the 'contributory category' and the 'employment category' (although not every combination is valid)
    The 'scheme' can be either 'no1', 'no2', 'off', 'cg' or 'amc'
    The 'contributory category' can be either 'cont' or 'noncont'
    The 'employment category' can be either 'ft' or 'pt'
    For example the total variable name could be 'v_cg_noncont_ft_count'
    I have created a variable by concatenating the various elements called v_incr_count_name which holds the name of the variable I want to increment.
    I am running this within an anonymous PLSQL block so I cannot use global variables meaning that my variables are not visible within a dynamic PLSQL block.
    As a result I think I will need to use bind variables with a PLSQL block or a SELECT FROM INTO SQL string
    I have tried various solutions including the following PLSQL solution:
    v_incr_count_name := 'v_'||v_scheme||'_'||v_cont_cat||'_'||v_emp_cat||'_count';
    sql_stmt := 'BEGIN :a := :a + 1; END;';
    EXECUTE IMMEDIATE sql_stmt USING v_incr_count_name;
    Unfortunately I am getting the 'IN bind variable bound to an OUT position' error which I suppose makes sense as I am trying to change the value of a variable in the main PLSQL block from within the dynamic block.
    Another (SQL) solution I tried was:
    v_incr_count_name := 'v_'||v_scheme||'_'||v_cont_cat||'_'||v_emp_cat||'_count';
    sql_stmt := 'SELECT '||v_incr_count_name||' + 1 FROM DUAL';
    EXECUTE IMMEDIATE sql_stmt INTO v_return;
    While this executes and returns the incremented value into v_return, I am still left unable to copy the returned value into the variable whose name is stored in v_incr_count_name
    Any help appreciated
    Cheers, Dan

    this shows the syntax for the using clause
    declare
    a number := 1;
    b number := null;
    v varchar2(10) := 'A';
    begin
    execute immediate 'begin :v1 := :v1 + 1; end;' using in out a;
    dbms_output.put_line(a);
    end;
    /but what you want cannot be done
    SQL> declare
      2  a number := 1;
      3  b number := null;
      4  v varchar2(10) := 'A';
      5  begin
      6  execute immediate 'begin '||v||' := :v1 + 1; end;' using in out a;
      7  dbms_output.put_line(a);
      8  end;
      9  /
    declare
    ERROR at line 1:
    ORA-06550: line 1, column 7:
    PLS-00201: identifier 'A' must be declared
    ORA-06550: line 1, column 7:
    PL/SQL: Statement ignored
    ORA-06512: at line 6the variable "V" contains the name of the desired output variable ("A"). this errors because "A" is not defined within the scope of the dynamic sql.
    "into the variable whose name is stored in v_incr_count_name"
    pl/sql does not support dereferencing variables, so you can't do it.

  • Compare character variable in dynamic sql

    hi all
    i have a requirment in which i'll be using a dynamic sql:
    sql_string :='select * from temp_table where emp_name='||v_name;
    execute immediate ;
    i'm getting this error
    ORA-06502: PL/SQL: numeric or value error
    this is becouse v_name is character variable and we have to write
    select * from temp_table where emp_name='joe';
    can any one plz help me out..

    More correctly you should use bind variables (if you really really have to do dynamic SQL in the first place)...
    sql_string :='select * from temp_table where emp_name=:n;
    execute immediate sql_string using v_name;This allows the optimiser to re-use the execution plan rather than hard-parsing the query every time.
    However this still isn't right because within PL/SQL you will need to be selecting your result INTO something e.g.
    sql_string :='select * from temp_table where emp_name=:n;
    execute immediate sql_string into v_data using v_name;v_data will be a variable declared suitably to accept whatever data is being selected in the query.

  • Invalid table name when pass in the table name as variable in dynamic sql

    Hi,
    I need to create a stored procedure which will return a list of data to my java application like the following.
    first, select the table name from the first table.
    For example : SELECT T_NAME FROM MDR_SMSTABLES
    second, select the data from the table which returned by first select statement
    For example : SELECT * FROM T_NAME.
    I use dynamic sql with cursor to select the data. But it returns "java.sql.SQLException: ORA-00903: invalid table name"
    I fetch the table name to varchar2. I think this might the cause it returns me the this error. But i don't know what type should i put for the table name other then varchar2.
    val2 VARCHAR2(200);
    OPEN cv FOR
    SELECT T_NAME FROM MDR_SMSTABLES WHERE T_DATE=d_dt_sent;
    FETCH cv INTO val2;
    WHILE cv%FOUND
    LOOP
    OPEN refcur FOR
    'SELECT * FROM :t WHERE MID = :m' USING val2, msg_id;
    EXIT WHEN refcur IS NOT NULL;
    FETCH cv INTO val2;
    END LOOP;
    As my stored procedure is quite long, so i just paste some of the code here. Hope the information is enough. Can anyone please help?
    Thanks

    DECLARE
    val2 VARCHAR2 (200);
    cv sys_refcursor;
    refcur sys_refcursor;
    BEGIN
    OPEN cv FOR
    SELECT table_name
    FROM user_tables
    WHERE table_name IN ('EMP', 'DEPT');
    FETCH cv INTO val2;
    WHILE cv%FOUND
    LOOP
    OPEN refcur FOR 'SELECT * FROM '||val2;
    EXIT WHEN refcur IS NOT NULL;
    FETCH cv INTO val2;
    END LOOP;
    END;

  • Unknow number of binding variables in Dynamic SQL

    I have to use a dynamic sql and binding variables. The problem is the number of binding variable varies due to the form input.
    EX.
    if ( something is not null ) then
    query := query || ' and column = :column';
    end if;
    if ( something_else is not null ) then
    query := query || ' and another_column = :another_column';
    end if;
    When I use in my USING clause, I don't know which of the four combinations of column/another_column I could be
    open query;
    open query using A,B;
    open query using A;
    open query using B;
    How can I solve this problem?
    Thanks a lot!

    Always with NVL:
    query := query || ' AND column = NVL(:column,column ) AND another_column = NVL(:another_column,another_column)';Invoke:
    DECLARE
      a_null CHAR(1); -- set to NULL automatically at run time
    BEGIN
      --open query
      open query using (a_null,a_null)
      --open query using A,B
      open query using A,B;
      --open query using A
      open query using A,a_null;
      --open query using B
      open query using a_null ,B;
    END;
    /Edited by: jortri on 04-dic-2008 18:34

  • Include variable into xpath expression of transformation activity

    Are we able to include variable from the BPEL process into the xpath expression of the transformation activity?
    I tried it but I received error saying it does not recognize the function bpws:getVariableData('loopCounter') when I included it into the xpath expression inside the transformation.
    Thanks.
    Kenny

    Maybe I am giving a bad example. Instead of bpws:getVariableData('loopCounter'), I need something like bpws:getVariableData('accountName') which is being used in the filter like /root/accounts/account[name=bpws:getVariableData('accountName')]
    The assign will not work in this xpath expression because it return multiple nodes in source.

  • Declaring variable using Dynamic SQL

    Hi guys,
    I need to declare a variable base on a result.
    <snipplet>
    DECLARE
    v_objname VARCHAR2(50);
    BEGIN
    SELECT OBJECT_NAME
    INTO v_objname
    FROM USER_OBJECTS
    WHERE OBJECT_ID = 'xxx'
    AND OBJECt_TYPE = 'TABLE';
    -- now i need to declare a rowtype variable base on the objname
    -- e.g v_rowname v_objname%ROWTYPE;
    </snipplet>
    q1) May i know how do i do that ?
    Regards,
    Noob

    This sounds like a precursor to building a "generic" piece of code. As Boneist says... Bad Idea.
    If dynamically generated queries really need to be written (justify why first!) and you're not sure of the columns that are going to be returned, then you would preferably use the DBMS_SQL package to build the query and use positional notation to obtain the data from the dynamic columns, using the describe ability of dbms_sql to get information on the column types etc.
    e.g.
    (From my standard answers...)
    As sys user:
    CREATE OR REPLACE DIRECTORY TEST_DIR AS '\tmp\myfiles'
    GRANT READ, WRITE ON DIRECTORY TEST_DIR TO myuser
    /As myuser:
    CREATE OR REPLACE PROCEDURE run_query(p_sql IN VARCHAR2
                                         ,p_dir IN VARCHAR2
                                         ,p_header_file IN VARCHAR2
                                         ,p_data_file IN VARCHAR2 := NULL) IS
      v_finaltxt  VARCHAR2(4000);
      v_v_val     VARCHAR2(4000);
      v_n_val     NUMBER;
      v_d_val     DATE;
      v_ret       NUMBER;
      c           NUMBER;
      d           NUMBER;
      col_cnt     INTEGER;
      f           BOOLEAN;
      rec_tab     DBMS_SQL.DESC_TAB;
      col_num     NUMBER;
      v_fh        UTL_FILE.FILE_TYPE;
      v_samefile  BOOLEAN := (NVL(p_data_file,p_header_file) = p_header_file);
    BEGIN
      c := DBMS_SQL.OPEN_CURSOR;
      DBMS_SQL.PARSE(c, p_sql, DBMS_SQL.NATIVE);
      d := DBMS_SQL.EXECUTE(c);
      DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);
      FOR j in 1..col_cnt
      LOOP
        CASE rec_tab(j).col_type
          WHEN 1 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);
          WHEN 2 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_n_val);
          WHEN 12 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_d_val);
        ELSE
          DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);
        END CASE;
      END LOOP;
      -- This part outputs the HEADER
      v_fh := UTL_FILE.FOPEN(upper(p_dir),p_header_file,'w',32767);
      FOR j in 1..col_cnt
      LOOP
        v_finaltxt := ltrim(v_finaltxt||','||lower(rec_tab(j).col_name),',');
      END LOOP;
      --  DBMS_OUTPUT.PUT_LINE(v_finaltxt);
      UTL_FILE.PUT_LINE(v_fh, v_finaltxt);
      IF NOT v_samefile THEN
        UTL_FILE.FCLOSE(v_fh);
      END IF;
      -- This part outputs the DATA
      IF NOT v_samefile THEN
        v_fh := UTL_FILE.FOPEN(upper(p_dir),p_data_file,'w',32767);
      END IF;
      LOOP
        v_ret := DBMS_SQL.FETCH_ROWS(c);
        EXIT WHEN v_ret = 0;
        v_finaltxt := NULL;
        FOR j in 1..col_cnt
        LOOP
          CASE rec_tab(j).col_type
            WHEN 1 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);
                        v_finaltxt := ltrim(v_finaltxt||',"'||v_v_val||'"',',');
            WHEN 2 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_n_val);
                        v_finaltxt := ltrim(v_finaltxt||','||v_n_val,',');
            WHEN 12 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_d_val);
                        v_finaltxt := ltrim(v_finaltxt||','||to_char(v_d_val,'DD/MM/YYYY HH24:MI:SS'),',');
          ELSE
            v_finaltxt := ltrim(v_finaltxt||',"'||v_v_val||'"',',');
          END CASE;
        END LOOP;
      --  DBMS_OUTPUT.PUT_LINE(v_finaltxt);
        UTL_FILE.PUT_LINE(v_fh, v_finaltxt);
      END LOOP;
      UTL_FILE.FCLOSE(v_fh);
      DBMS_SQL.CLOSE_CURSOR(c);
    END;This allows for the header row and the data to be written to seperate files if required.
    e.g.
    SQL> exec run_query('select * from emp','TEST_DIR','output.txt');
    PL/SQL procedure successfully completed.Output.txt file contains:
    empno,ename,job,mgr,hiredate,sal,comm,deptno
    7369,"SMITH","CLERK",7902,17/12/1980 00:00:00,800,,20
    7499,"ALLEN","SALESMAN",7698,20/02/1981 00:00:00,1600,300,30
    7521,"WARD","SALESMAN",7698,22/02/1981 00:00:00,1250,500,30
    7566,"JONES","MANAGER",7839,02/04/1981 00:00:00,2975,,20
    7654,"MARTIN","SALESMAN",7698,28/09/1981 00:00:00,1250,1400,30
    7698,"BLAKE","MANAGER",7839,01/05/1981 00:00:00,2850,,30
    7782,"CLARK","MANAGER",7839,09/06/1981 00:00:00,2450,,10
    7788,"SCOTT","ANALYST",7566,19/04/1987 00:00:00,3000,,20
    7839,"KING","PRESIDENT",,17/11/1981 00:00:00,5000,,10
    7844,"TURNER","SALESMAN",7698,08/09/1981 00:00:00,1500,0,30
    7876,"ADAMS","CLERK",7788,23/05/1987 00:00:00,1100,,20
    7900,"JAMES","CLERK",7698,03/12/1981 00:00:00,950,,30
    7902,"FORD","ANALYST",7566,03/12/1981 00:00:00,3000,,20
    7934,"MILLER","CLERK",7782,23/01/1982 00:00:00,1300,,10The procedure allows for the header and data to go to seperate files if required. Just specifying the "header" filename will put the header and data in the one file.
    Adapt to output different datatypes and styles are required.
    I have never found any need, ever* to have to write dynamic PL/SQL code. It just shouldn't be necessary. If you're finding yourself heading in that direction, seriously take a step back and re-consider your design and what it actually is you're trying to achieve. There almost always will be a better way.

  • Bind variables and Dynamic sql

    I have this function which works only when i'm not passing bind variables. The moment i add bind variables it is not able to execute the function.
    Oracle Db Version: 8.1
    Thanks
    Source Code
    FUNCTION TestFunction( In_Test_id in Number,
    In_Asof in Date )
    Return ScoreType
    IS
    LvScore ABC.LV_SCORE.SCORE%TYPE;
    DVScore ABC.LV_SCORE.SCORE%TYPE;
    Begin
    EXECUTE IMMEDIATE
    'SELECT SCORE,DVSCORE
    FROM
    SELECT SCORE,DVSCORE
    DENSE_RANK() OVER (PARTITION BY TEST_ID ORDER BY ASOF_DT DESC) AS score_RANK
    FROM ABC.LV_SCORE
    WHERE TEST_ID = :x
    AND ASOF_DT <= :y
    ) WHERE score_RANK = 1'
    INTO LvScore,DVScore
    USING In_tEST_ID,In_Asof;
    Return ScoreType( LvScore,
    DVScore);
    End;

    It just keeps on executing for sometime and then disconnects itself from database What was the indication that told you that it disconnected? Was there a visible indication of this disconnect?
    Did you get ORA-03113?
    ===========================================
    ORA-03113: end-of-file on communication channel
    Cause: The connection between Client and Server process was broken.
    Action: There was a communication error that requires further investigation. First, check for network problems and review the SQL*Net setup. Also, look in the alert.log file for any errors. Finally, test to see whether the server process is dead and whether a trace file was generated at failure time.

  • Pass variable into execute sql task

    hi
    i want to execute my stored proc, in ssis package . i have 2 parameter, so i need pass values from another table one by one.
    i need to execute stored proc for each from another table, by passing values
    how to do it

    hi
    i want to execute my stored proc, in ssis package . i have 2 parameter, so i need pass values from another table one by one.
    i need to execute stored proc for each from another table, by passing values
    how to do it
    You can do it as follows
    1. Add a variable of type object in SSIS
    2. Add a execute sql task with query as
    SELECT field1,field2
    FROM Table
    Set resultset option as Full resultset and in resultset tab map the resultset to object variable.
    3. Add a ForEach loop with ADO enumerator and map it to object variable. Inside loop add two variable to get each iterative values for field1 and field2
    4. Inside loop add a execute sql task and set command as
    EXEC ProcedureName ?,?
    Map the parameters to two variables created inside the loop.
    On executing package the procedure gets executed for each record in the table.
    Please Mark This As Answer if it helps to solve the issue Visakh ---------------------------- http://visakhm.blogspot.com/ https://www.facebook.com/VmBlogs

  • How to pass variable into lov sql query using like operator

    hi.
    i want to use a lov where i want to pass a variable using like operator.
    my query is
    select empno,name from table where empno like ':ed%';
    my empno is A001 TO A199 AND B001 TO B199 so i want show either A% or B% empno
    how can i do this ?
    reagrds

    kindly press Shift+F1 at a time you face this error to see the exact Oracle error message.
    and provide us with that detail
    and its better if you start new topic for that error... because that will be new error,,,
    -- Aamir Arif
    Edited by: Aamiz on Apr 7, 2010 12:27 PM

  • Creating a dynamic SQL query builder class

    I have a jobs table where each row contains information about jobs run on a machine. I have a web view of this database which shows different information and queries for this information are built using the following fields:
    TYPE
    TITLE
    NODE
    STATUS (an array of 4 different possible statuses)
    TIMESTAMP
    GUID (will be used when a view of a specific job (row in the table) is requested, no other search criteria needed when this view is required.)
    All the criteria will be passed from the view layer into a search criteria object which is then passed to the DAO class which passes it to a BuildSQL class to use it to build the SQL.
    There are many different "views" of the data which will result in many different combinations of criteria being passed down to the data access layer. (for example a status of failed and a timestamp resulting in all the jobs run in the last 2 hours)
    As there are a number of different search criteria used in each query I'm having trouble designing the class to dynamically build the query. Are there any standard ways of doing this out there that could guide me?
    At the moment I'm seeing this class as being a large combination of if statements and not really being very dynamic.
    I was thinking maybe checking all the criteria to see if its null, if so ignore it straight away and then running through all the other criteria and appending one by one to the may SELECT which has already been created. Quite how i'd decided whether it would need an AND or OR before it I dont know.
    Are there any standard proven ways to approach this because i've done a search here and on google and not really come back with much, so any advice would be great. I've got to say I'm pretty new to java and don't really have many bright ideas here!

    Well my dear friend... I did something special for a business logic support to an web autocomplete component.
    The criteria building was based on a custom variable into the SQL statement:
    SELECT * FROM TABLE WHERE __MC__ AND (FIXED CRITERIA)
    Where:
    *FIXED CRITERIA: Is a fixed criteria that doesn't variate
    *__MC__: Is a "custom variable" defined for me to make the replacement.
    There are two main clases:
    *SQLBuilder: It has many logic to build SQL Statements
    *Multicriteria: It has the specific logic to insert into a SQL statement multiple criterias
    // The SQLBuilder class
    public class SQLBuilder {
        public static final String MC = "__MC__";
        static String buildMultiCriteria(String sql, Object[] params) throws Exception {
            for(int i=0; i<params.length; i++) {
                if(params[i] instanceof MultiCriteria) {
                    sql = sql.replaceFirst("__MC__",
                            ((MultiCriteria)params).getCriteria());
    params[i] = null;
    return sql;
    // The MultiCriteria class
    public class MultiCriteria {
    public static final int BEGINS = 0;
    public static final int ENDS = 1;
    public static final int CONTAINS = 2;
    private String criteria = null;
    public MultiCriteria(String[] fields, String value, int type) throws Exception {
    String[] tokens = value.split(" ");
    StringBuffer sb = new StringBuffer("(");
    for(int i=0; i<fields.length; i++) {
    for(int j=0; j<tokens.length; j++) {
    if(tokens[j].length()>0) {
         sb.append(fields[i].toUpperCase());
         sb.append(" LIKE '");
         sb.append(toType(tokens[j], type));
         sb.append("'");
         if(j<tokens.length-1) sb.append(" OR ");
    if(i<fields.length-1) sb.append(" OR ");
    sb.append(")");
    criteria = sb.toString();
    public String getCriteria() {
    return criteria;
    private final String toType(String value, int type) throws Exception {
    switch(type) {
         case BEGINS:
         value = value + "%";
         break;
         case ENDS:
         value = "%" + value;      
         break;
         case CONTAINS:
         value = "%" + value + "%";      
         break;
         default:
         throw new Exception("Undefined MutiCriteria type");
    return value;
    // I use the MultiCriteria this way
    // criteria is a string introduced in a html input text
    // The class splits the string by " " and ensemble multiple criterias
    // for the given fields permuting them with the tokens resulting of the
    // split
    MultiCriteria mc = new MultiCriteria(
    new String[] {"FIELD_01", "FIELD_02"},
         criteria,
         MultiCriteria.CONTAINS
    I think this idea could help you.
    Anything else, write me at [email protected]
    Best Regards,

  • Dynamic SQL in Triggers

    Does anyone know if it is possible to have dynamic SQL statements
    within a trigger.
    for example,
    sql_str := 'insert into log_'||table_name||'values
    (''A'',:new.descr)';
    execute immediate sql_str;
    I kept on getting an internal error as follows
    ORA-00600: internal error code, arguments: [15212], [3], [], [],
    ORA-06512: at "CDC.TG_BI_COMPANY_C", line 30
    ORA-04088: error during execution of trigger 'CDC.TG_BI_COMPANY_C'
    Thanks in advance

    Hi,
    This is a bug i think ... a long shot but let us see what the
    people at oracle have to say for this.... I Am posting it on
    metalink....
    Here is the corrected code...
    create or replace trigger atrig
    before insert on A
    For Each Row
    Declare
    a number;
    begin
    execute immediate 'insert into ' || 'a_log values(:1)'
    using :new.a;
    end;
    This works....
    Always use bind Variables in Dynamic SQl ... Good Practice ....
    Regards,
    Ganesh R

  • Dynamic SQL with cursor variables in pro*c

    Please, what I need to do in order to be able
    to do something like this:
    EXEC SQL DECLARE :c CURSOR FOR :s;
    In other words: I want to use variables
    in cursor names.
    Is it possible ? How ?
    Thank you.

    OK. Here is an example of a Dynamic SQL #4 program I wrote several years ago (It's still running in production). It is currently running on a Sun E10K with Oracle 8.1.5. This code is JUST the pro*c part of a program which uses IBM MQ Series. MQ passes this program a Select SQL statement (as well as other parameters) as an argument. The Pro*c code allocates the structures, parses, and fetches, and executes the statement. I realize that this will not be easy to read. There are SOME comments in the code. However, I realize that to read anyone elses code is a chore. When you add Dynamic #4 to the list, it becomes much more complicated. Anyway, you'll probably need to copy and paste the code to a text file. It will be easier to read.
    ==========================================
    Code
    ==========================================
    | Program: mqsql.pc |
    | Creator: Jim Wartnick |
    | Purpose: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
    | XXXXXXXXXXX |
    | Date: 01/03/1997 |
    | Modifications: |
    #include"mqsql.h"
    #define DEBUG
    #ifdef DEBUG
    FILE *fp=stdout;
    #endif
    int
    disconnect_db() {
    char msg[256], oraclmsg[256];
    char buf[MAX_STRING_LENGTH+4];
    int buf_len = 0, msg_len = 0;
    EXEC SQL
    COMMIT WORK RELEASE;
    #ifdef DEBUG
    fprintf(fp, " --> Disconnecting from database. RC: %d.\n", sqlca.sqlcode);
    fflush(fp);
    #endif
    if (sqlca.sqlcode != 0) {
    buf_len = sizeof(oraclmsg)-1;
    sqlglm(oraclmsg, &buf_len, &msg_len);
    oraclmsg[msg_len] = '\0';
    error("disconnect_db()", "disconnect", sqlca.sqlcode, oraclmsg);
    return(FAILURE);
    return(SUCCESS);
    int
    connect_db() {
    char msg[256], oraclmsg[256];
    char buf[MAX_STRING_LENGTH+4];
    int buf_len = 0, msg_len = 0;
    char user[4];
    strcpy(user, "/");
    EXEC SQL
    CONNECT :user;
    #ifdef DEBUG
    fprintf(fp, " --> Connecting to database. RC is %d\n", sqlca.sqlcode);
    fflush(fp);
    #endif
    if (sqlca.sqlcode != 0) {
    buf_len = sizeof(oraclmsg)-1;
    sqlglm(oraclmsg, &buf_len, &msg_len);
    oraclmsg[msg_len] = '\0';
    sprintf(Results, "%9d", sqlca.sqlcode);
    error("connect_db()", "connect", sqlca.sqlcode, oraclmsg);
    return(FAILURE);
    return(SUCCESS);
    int
    allocate_sqlda() {
    | Initialize the SQLDA structure. |
    | We only need the select descriptor |
    | because we do not have any bind |
    | variables. |
    if ((Select_da = sqlald(
    MAX_COLUMN_COUNT,
    MAX_COLUMN_STRING_LENGTH,
    MAX_INDICATOR_VARS
    )) == (SQLDA *) 0) {
    #ifdef DEBUG
    fprintf(fp, " Memory allocation for Select Descriptor failed.\n");
    fflush(fp);
    #endif
    strcpy(Results, "000000001");
    error("allocate_sqlda()", "create SQLDA", 0, "Memory Error");
    return(FAILURE);
    #ifdef DEBUG
    fprintf(fp, " Memory allocation for Select Descriptor succeeded.\n");
    fflush(fp);
    #endif
    Select_da->N = MAX_COLUMN_COUNT;
    return(SUCCESS);
    int
    prepare_sql() {
    char msg[256], oraclmsg[256];
    int buf_len = 0, msg_len = 0;
    | Prepare the Sql statement. |
    EXEC SQL
    PREPARE sql_stmt
    FROM :Sql;
    #ifdef DEBUG
    fprintf(fp, " Prepared SQL: %s. RC: %d.\n", Sql, sqlca.sqlcode);
    fflush(fp);
    #endif
    if (sqlca.sqlcode != 0) {
    buf_len = sizeof(oraclmsg)-1;
    sqlglm(oraclmsg, &buf_len, &msg_len);
    oraclmsg[msg_len] = '\0';
    sprintf(Results, "%9d", sqlca.sqlcode);
    error("prepare_sql()", "Parse", sqlca.sqlcode, oraclmsg);
    return(FAILURE);
    return(SUCCESS);
    int
    declare_cursor() {
    char msg[256], oraclmsg[256];
    int buf_len = 0, msg_len = 0;
    | Set up the cursor to loop through |
    EXEC SQL
    DECLARE sql_cursor
    CURSOR FOR sql_stmt;
    #ifdef DEBUG
    fprintf(fp, " Declared cursor. RC: %d\n", sqlca.sqlcode);
    fflush(fp);
    #endif
    if (sqlca.sqlcode != 0) {
    buf_len = sizeof( oraclmsg)-1;
    sqlglm(oraclmsg, &buf_len, &msg_len);
    oraclmsg[msg_len] = '\0';
    sprintf(Results, "%9d", sqlca.sqlcode);
    error("declare_cursor()", "declare cursor", sqlca.sqlcode, oraclmsg);
    return(FAILURE);
    return(SUCCESS);
    int
    open_cursor() {
    char msg[256], oraclmsg[256];
    int buf_len = 0, msg_len = 0;
    | Open the cursor. |
    EXEC SQL
    OPEN sql_cursor;
    #ifdef DEBUG
    fprintf(fp, " Opened cursor. RC:%d\n", sqlca.sqlcode);
    fflush(fp);
    #endif
    if (sqlca.sqlcode != 0) {
    buf_len = sizeof(oraclmsg)-1;
    sqlglm(oraclmsg, &buf_len, &msg_len);
    oraclmsg[msg_len] = '\0';
    sprintf(Results, "%9d", sqlca.sqlcode);
    error("open_cursor()", "open cursor", sqlca.sqlcode, oraclmsg);
    return(FAILURE);
    return(SUCCESS);
    int
    describe_select_list() {
    char msg[256], oraclmsg[256];
    int buf_len = 0, msg_len = 0;
    | Get description of columns |
    EXEC SQL
    DESCRIBE SELECT LIST FOR sql_stmt
    INTO Select_da;
    #ifdef DEBUG
    fprintf(fp, " Described columns. RC %d\n", sqlca.sqlcode);
    fflush(fp);
    #endif
    if (sqlca.sqlcode != 0) {
    buf_len = sizeof(oraclmsg)-1;
    sqlglm(oraclmsg, &buf_len, &msg_len);
    oraclmsg[msg_len] = '\0';
    sprintf(Results, "%9d", sqlca.sqlcode);
    error("describe_select_list()", "describe select list", sqlca.sqlcode, oraclmsg);
    return(FAILURE);
    return(SUCCESS);
    int
    setup_sqlda() {
    char buf[MAX_STRING_LENGTH+4];
    int done = FALSE, nullok = 0, i = 0;
    #ifdef DEBUG
    fprintf(fp, " --> Setting up SQLDA.\n");
    fflush(fp);
    #endif
    if (allocate_sqlda() == FAILURE)
    return(FAILURE);
    if (prepare_sql() == FAILURE)
    return(FAILURE);
    if (declare_cursor() == FAILURE)
    return(FAILURE);
    if (open_cursor() == FAILURE)
    return(FAILURE);
    if (describe_select_list() == FAILURE)
    return(FAILURE);
    | Too many columns in select list. |
    if (Select_da->F < 0) {
    strcpy(Results, "000000001");
    error("setup_sqlda()", "check select list count", 0, "Too many values in select list");
    return(FAILURE);
    | Set the number of columns to the actual |
    | number of columns. |
    Select_da->N = Select_da->F;
    | We are going to convert all fields to a string. |
    for (i == 0; i < Select_da->F; i++) {
    sqlnul(&(Select_da->T), &(Select_da->T[i]), &nullok);
    Select_da->T[i] = EXT_STRING;
    Select_da->L[i] = MAX_STRING_LENGTH;
    | Allocate the result area to be as big as |
    | MAX_STRING_LENGTH. |
    if ((Select_da->V[i] = malloc(Select_da->L[i])) == NULL) {
    #ifdef DEBUG
    fprintf(fp, " Allocation of column values failed.\n");
    fflush(fp);
    #endif
    strcpy(Results, "000000001");
    error("setup_sqlda()", "allocate column values", 0, "Memory Error");
    return(FAILURE);
    if ((Select_da->I[i] = (short *) malloc(sizeof(short))) == NULL) {
    #ifdef DEBUG
    fprintf(fp, " Allocation of idicator values failed.\n");
    fflush(fp);
    #endif
    strcpy(Results, "000000001");
    error("setup_sqlda()", "allocate indicator values", 0, "Memory Error");
    return(FAILURE);
    #ifdef DEBUG
    fprintf(fp, " Allocation of memory for values succeeded.\n");
    fflush(fp);
    #endif
    return(SUCCESS);
    | add_eom adds the end of message |
    | delimiter (an aditional comma). |
    int
    add_eom() {
    char *result_ptr;
    if (strlen(Results) >= sizeof(Results) - 1) {
    strcpy(Results, "000000001");
    error("add_eom()", "Add eom failed. Size overflow", 0, "Memory Error");
    return(FAILURE);
    result_ptr = &Results[strlen(Results)-1];
    while (*result_ptr && (*result_ptr != ','))
    result_ptr--;
    if (*result_ptr) {
    result_ptr++;
    *(result_ptr++) = ',';
    *result_ptr = '\0';
    return(SUCCESS);
    int close_cursor() {
    char msg[256], oraclmsg[256];
    int buf_len = 0, msg_len = 0;
    | Close the cursor. |
    EXEC SQL
    CLOSE sql_cursor;
    #ifdef DEBUG
    fprintf(fp, " Closing cursor. RC: %d\n", sqlca.sqlcode);
    fflush(fp);
    #endif
    if (sqlca.sqlcode != 0) {
    buf_len = sizeof(oraclmsg)-1;
    sqlglm(oraclmsg, &buf_len, &msg_len);
    oraclmsg[msg_len] = '\0';
    error("generate_sql()", "close cursor", sqlca.sqlcode, oraclmsg);
    return(FAILURE);
    return(SUCCESS);
    int
    fetch() {
    char msg[256], oraclmsg[256];
    char buf[MAX_STRING_LENGTH+4];
    int buf_len = 0, msg_len = 0;
    EXEC SQL
    FETCH sql_cursor
    USING DESCRIPTOR Select_da;
    #ifdef DEBUG
    fprintf(fp, " --> Fetching rows. RC %d\n", sqlca.sqlcode);
    fflush(fp);
    #endif
    if (sqlca.sqlcode != 0) {
    if (sqlca.sqlcode != NODATAFOUND) {
    buf_len = sizeof(oraclmsg)-1;
    sqlglm(oraclmsg, &buf_len, &msg_len);
    oraclmsg[msg_len] = '\0';
    error("fetch()", "Error fetching row.", sqlca.sqlcode, oraclmsg);
    return(sqlca.sqlcode);
    return(NODATAFOUND);
    return(SUCCESS);
    | Free up any memory structures. |
    void
    free_memory() {
    int i = 0;
    for (i = 0; i < Select_da->F; i++) {
    free(Select_da->V[i]);
    free(Select_da->I[i]);
    | generate_sql() uses the message we received from the queue |
    | (a SQL statement) to query the database. We have to use |
    | dynamic Sql Version 4 for this type of Sql. The number of |
    | columns we are selecting is unknown. This means we can't |
    | use the INTO clause. |
    int
    generate_sql() {
    char buf[MAX_STRING_LENGTH+4];
    int rc = SUCCESS, done = FALSE, nullok = 0, i = 0;
    #ifdef DEBUG
    if ((fp = fopen(SQLLOG, "a")) == NULL)
    fp = stderr;
    #endif
    | Connect to the database |
    if (connect_db() == FAILURE)
    return(FAILURE);
    if (setup_sqlda() == FAILURE)
    return(FAILURE);
    | Place the answer in a comma delimited buffer. |
    memset(Results, NULL, sizeof(Results));
    done = FALSE;
    while (!done) {
    rc = fetch();
    if (rc != SUCCESS) {
    if (Results[0] == '\0')
    sprintf(Results, "%9d,", rc);
    done = TRUE;
    else {
    | Put return code of success in first. |
    if (Results[0] == '\0')
    strcpy(Results, "000000000,");
    for (i = 0; i < Select_da->F; i++) {
    Select_da->V[i][Select_da->L[i]] = '\0';
    | Check to see if the value is null. |
    if (*Select_da->I[i] < 0)
    strcpy(buf, " ,");
    else
    sprintf(buf, "%s,", Select_da->V[i]);
    if (strlen(Results) + strlen(buf) > sizeof(Results)) {
    strcpy(Results, "000000001");
    error("generate_sql()", "String concat failed. Size overflow", 0, "Memory Error");
    return(FAILURE);
    strcat(Results, buf);
    #ifdef DEBUG
    fprintf(fp, " --> Results %s\n", Results);
    fflush(fp);
    #endif
    | Close the cursor. |
    close_cursor();
    | Disconnect from the database |
    disconnect_db();
    | Remove trailing comma. |
    if (add_eom() == FAILURE)
    return(FAILURE);
    #ifdef DEBUG
    fflush(fp);
    #endif
    free_memory();
    #ifdef DEBUG
    fclose(fp);
    #endif
    null

  • Using bind variables (in & out) with dynamic sql

    I got a table that holds pl/sql code snippets to do validations on a set of data. what the code basically does is receiving a ID and returning a number of errors found.
    To execute the code I use dynamic sql with two bind variables.
    When the codes consists of a simpel query, it works like a charm, for example with this code:
    BEGIN
       SELECT COUNT (1)
       INTO :1
       FROM articles atl
       WHERE ATL.CSE_ID = :2 AND cgp_id IS NULL;
    END;however when I get to some more complex validations that need to do calculations or execute multiple queries, I'm running into trouble.
    I've boiled the problem down into this:
    DECLARE
       counter   NUMBER;
       my_id     NUMBER := 61;
    BEGIN
       EXECUTE IMMEDIATE ('
          declare
             some_var number;
          begin
          select 1 into some_var from dual
          where :2 = 61;
          :1 := :2;
          end;
          USING OUT counter, IN my_id;
       DBMS_OUTPUT.put_line (counter || '-' || my_id);
    END;this code doesn't really make any sense, but it's just to show you what the problem is. When I execute this code, I get the error
    ORA-6537 OUT bind variable bound to an IN position
    The error doesn't seem to make sense, :2 is the only IN bind variable, and it's only used in a where clause.
    As soon as I remove that where clause , the code will work again (giving me 61-61, in case you liked to know).
    Any idea whats going wrong? Am I just using the bind variables in a way you're not supposed to use them?
    I'm using Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit

    Correction. With execute immediate binding is by position, but binds do not need to be repeated. So my statement above is incorrect..
    You need to bind it once only - but bind by position. And the bind must match how the bind variable is used.
    If the bind variable never assigns a value in the code, bind as IN.
    If the bind variable assigns a value in the code, bind as OUT.
    If the bind variable assigns a value and is used a variable in any other statement in the code, bind as IN OUT.
    E.g.
    SQL> create or replace procedure FooProc is
      2          cnt     number;
      3          id      number := 61;
      4  begin
      5          execute immediate
      6  'declare
      7          n       number;
      8  begin
      9          select
    10                  1 into n
    11          from dual
    12          where :var1 = 61;       --// var1 is used as IN
    13 
    14          :var2 := n * :var1;     --// var2 is used as OUT and var1 as IN
    15          :var2 := -1 * :var2;    --// var2 is used as OUT and IN
    16  end;
    17  '
    18          using
    19                  in out id, in out cnt;  --// must reflect usage above
    20 
    21          DBMS_OUTPUT.put_line ( 'cnt='||cnt || ' id=' || id);
    22  end;
    23  /
    Procedure created.
    SQL>
    SQL> exec FooProc
    cnt=-61 id=61
    PL/SQL procedure successfully completed.
    SQL>

Maybe you are looking for