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, DanRepost:
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, Danthis 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?
ThanksDECLARE
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.
KennyMaybe 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,
NoobThis 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 ithi
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 ?
reagrdskindly 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, -
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 advanceHi,
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 - 64bitCorrection. 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
-
How to create a *.lnk file in the ipaq
how to create the .lnk file and where in the Ipaq? if yes so how or can u write me an example thanks itzik
-
Error/warning message "you don't have permission to modify files in this network location"
Hi, We have a windows server 2008 running, and we access it via remote desktop. And there's this certain folder that all users access, and where we save important files. So, since this is where important files are stored, we wanted to disable deletio
-
Occasionally Sessionrestore doesn't show my tabs as they were when I closed Firefox, but as they were at some seemingly random (but persistent if trying again) point between starting and ending my previous session. Occasionally they're exactly as the
-
How to add dynamic security in ADF 11g. User names will come from database table not from jazn-data.xml. Or, How can i create UI based on ADF security policy? Can anyone help me?
-
Why do you need to auto-update almost everyday?
I turn on the pc, click on your browser and you immediately stop me by starting your update.The last three times were within the last two days, stopping me from getting at my gmail when I needed it.I'm using Explorer till I'm done being pissed off or