Using Host Array in Open Cursor in Embedded SQL - sql-server-2012

I have this embedded SQL code:
EXEC SQL
OPEN MY_CURSOR USING :a1
END-EXEC
Where a1 is Array with 20 items, but I don't know in forward how many Host Variables I will need. It can be from 1 to 20. If I use it in this way, and actually I am using only 5 items from array, I got this error:
SQLCODE: -10000, SQLSTATE: 24000, SQLERRMC: Invalid Cursor State
Is there any possibility how to in OPEN CURSOR section send number of used items in array? Or I must use array with exact number of items?

The host variables in the "OPEN CURSOR" statement refer to parameters in the where clause.
Not data is returned on OPEN.
Instead you get each individual row by issuing a "FETCH INTO :var1, :var2 ..."
much the same a single row select.
See docs here:
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql?view=sql-server-ver15

Related

Getting parameters error when using ibm_db_dbi sql query in python

I'm trying to use the results from one query to use in the where clause of another and cannot get it to work. at the moment i'm getting an error....
ProgrammingError: ibm_db_dbi::ProgrammingError: Exception('Statement Execute Failed: [IBM][CLI Driver] CLI0100E Wrong number of parameters. SQLSTATE=07001 SQLCODE=-99999')
My code below (eventually, 'result' will just be a variable assigned to the results from another query, but for now i'm just trying to get it to work with a static variable. Thanks in advance!
import ibm_db_dbi as db
result = ['c80fS4Pn1', '9f*hzNT21']
conn = db.connect('DRIVER=DB2 zOS;'
'DATABASE=xxxx;'
'HOSTNAME=xxxx.com;'
'PORT=xxx;'
'PROTOCOL=xxxx;'
'UID=id;'
'PWD=passord;', '', '')
cur = conn.cursor()
sql = "SELECT * FROM SCHEMA.TABLE WHERE PRIM_KEY IN (?)"
cur.execute(sql, (result))
conn.close()
The reason you get error CLI0100E is because in your code-sample you show a list (called result) with two entries, while in your query there is a single parameter-marker (?)
The number of parameters to be bound (as done by the cur.execute()), must exactly match the number of parameter-markers in the query
As you usually do not know in advance the number of rows returned from a query, you usually don't know the number of parameter-markers in advance.
You could dynamically generate the number of parameter markers to match the number of rows in the previous result-set. Or you could generate the SQL string in full without parameter markers which is inefficient and might not scale.
It is wise to do in SQL the things that SQL is good at doing, such as passing the results of a sub-query into another query. Trying to do that in client side code (instead of inside the SQL engine) may be inelegant and slow.

Describe is not working in IBM DB2

I am running an query in IBM DB2 as;
DESCRIBE TABLE Schema.Table
But I am getting an error as
DESCRIBE TABLE Schema.Table Error 42601:Token Table was not valid. Valid tokens: :. SQLCODE=-104
I search a lot but can't find out the reason and as I am very new in IBM DB2 so can't figure out the matter. Is it a permission related issue?
I don't have command prompt access.
You appear to be using DB2 on IBM i (formerly known as AS/400), where catalog views are in the QSYS2 schema.
In recent versions there are also their equivalents: SYSIBM.SQLCOLUMNS and INFORMATION_SCHEMA.COLUMNS.
If you are simply trying to get catalog information for a table or view, the system catalog will work just fine, as noted in another answer by mustaccio. But if you want to embed a DESCRIBE TABLE in your RPG or COBOL program, that will work as well. One reason you might want to do this is if you have a dynamic number of columns, or you don't know the table name at compile time. You can use an sql descriptor built by describing a table or cursor to receive the output of a FETCH statement in your program. You will need an SQL Descriptor or an SQLDA to receive the description of the table. It would look something like this:
dcl-s tableName Varchar(128);
exec sql allocate sql descriptor 'D1' with max 20;
tableName = 'MYTABLE';
exec sql
describe table :tableName
using sql descriptor 'D1';
This will retrieve information about the table into the specified descriptor. In this case D1. The descriptor name can be a host variable. This example allocates a local descriptor for 20 items. If your table has more than 20 columns, you can request a larger descriptor in the ALLOCATE DESCRIPTOR statement. If you will be spreading your sql that uses a given descriptor across multiple modules, you will need to use a global descriptor by replacing 'D1' with global 'D1'. You can also use an SQLDA, but I find that those can be more difficult to work with.
To get information out of the descriptor you would use GET DESCRIPTOR. It would be beyond the scope of this site to go into all the details of what you can get out of the descriptor, but as an example you could get the column name of the first column of MYTABLE like this:
dcl-s columnName Varchar(128) Inz('');
exec sql
get sql descriptor 'D1'
value 1 :columnName = name;
Don't forget to deallocate the descriptor when you are through with it.
exec sql deallocate sql descriptor 'D1';
You can find more information on DESCRIBE TABLE here https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/db2/rbafzdescrtb.htm. The knowledge center also has information about ALLOCATE DESCRIPTOR, DEALLOCATE DESCRIPTOR, and GET DESCRIPTOR.

Use UPDATE in a loop

When I execute the following code:
for acc_row in cursor.execute("select * from tabela1"):
cursor.execute("UPDATE table_name SET column_name=? where column_name=?", ('some_value','some_value'))
I receive the following error referencing the line containing the for loop:
ProgrammingError: No results. Previous SQL was not a query
The for loop works fine without the update statement, and vice versa
Software:
Python 2.7
Windows
pyodbc 3.0.7
AccessDatabaseEngine for MS Access 2010
You are relying on the state of the cursor. object to control the for loop, but then you are modifying that object (by executing the UPDATE statement) inside the loop. You'll need to maintain two cursor objects, one to control the loop and another one to perform the UPDATEs.
If your result set isn't large this should work:
rows = cursor.execute('select * from tabela1').fetchall()
for acc_row in rows:
cursor.execute('UPDATE table_name SET column_name=? where column_name=?', (acc_row.column1, acc_row.column2))
If the result set is too large to load into memory, maintain two cursors as mentioned in Gord Thompson's answer.

Error while Querying : The value of a host variable in the EXECUTE or OPEN statement is too large for its corresponding use

On trying to use a select query statement. The input variable has 8 characters just as expected.
I dont know why this error comes for select query because for a select query it will query and if its available it will return else it will retun blank rows.
Hibernate is used. Even in mapping its correctly mapped as 8 only.
This is what i found in log file:
Cause = com.ibm.db2.jcc.a.SqlException: The value of a host variable in the EXECUTE or OPEN statement is too large for its corresponding use.
Has anybody come across this error before? Please suggest me some solutions on why this error occurs..
One possibility... This issue can come even in SELECT statement. When the parameter passed into the query is more than the size of its datatype's size, this error will pop-up.
Example:
Datatype - CHAR(12)
Search Param: "123456789012345"

Returned ref cursor not supported

I'm trying to make a chart in a database dashboard reporting software(Logi Info). I've got a PL SQL package that returns a ref cursor with multiple values but it seems the Logi Info does not support this and gives me an error ORA-00904: "DASHBOARD_PACKAGE"."GETSUMMARYDATA": invalid identifier. I think its either not supported or that my querty is wrong. This is my query:
select dashboard_package.getSummaryData(1,sysdate) from dual
Is that how to call a function that returns multiple values? if so, is there a solution to this problem (return type not supported)?
This is a compilation error. Your GETSUMMARYDATA() function is referencing an invalid object name, a table, a column or whatever. If you're using dynamic SQL you won't get this compilation error until runtime.
So, you need to code through the source of your function and find the misnamed thing. The line number which goes with the error message should help you here.
If you are using SQL*Plus, you need to use a special syntax in order to access REF CURSORS.
This is well explained in the SQL*Plus manual:
http://download.oracle.com/docs/cd/B19306_01/server.102/b14357/ch5.htm#sthref1127
So it would be something like this in your case:
VARIABLE cv REFCURSOR
EXECUTE dashboard_package.getSummaryData(1, sysdate, :cv)
print cv
Note that the position of the :cv variable depends on the definition of your procedure.
But as you did not show us the source code...
Edit
To cover all possibilies (as mentioned by APC):
If the function indeed returns a ref cursor, then the syntax is slightly different as explained in the next chapter of the manual:
http://download.oracle.com/docs/cd/B19306_01/server.102/b14357/ch5.htm#sthref1128
VARIABLE cv REFCURSOR
execute :cv := dashboard_package.getSummaryData(1, sysdate);
print cv