I have a dynamic stored procedure, which I'm using to run multiple select queries. I have defined something like below.
CREATE PROCEDURE DYNAMIC
(IN IN_COLUMN1 VARCHAR(150),
IN IN_COLUMN2 VARCHAR(500),
IN IN_COLUMN3 VARCHAR(500),
IN IN_COLUMN4 CHAR(08),
IN IN_COLUMN5 DATE,
IN IN_COLUMN6 CHAR(05),
OUT OUT_COLUMN1 CHAR(01),
OUT OUT_COLUMN2 DEC(4,0),
OUT OUT_COLUMN3 DEC(4,0),
OUT OUT_COLUMN4 CHAR(04),
OUT OUT_COLUMN5 DATE
The problem here, when I run Query1, I will have input passed from COBOL DB2 program in IN_COLUMN1,IN_COLUMN2,IN_COLUMN3 and OUTPUT will be fetched into OUT_COLUMN1. I will initialize all INPUT in program, Due to the other OUTPUT parameters like OUT_COLUMN2,OUT_COLUMN3,OUT_COLUMN4 and OUT_COLUMN5 will have null, I'm getting SQLCODE "-305".
To fix this I tried to set OUTPUT parameters to default like below and got error while deploying.
OUT OUT_COLUMN2 DEC(4,0) DEFAULT NULL,
Is there any way to handle this. I'm using COBOL to call the stored procedure running in DB2.
Assuming IBM Enterprise COBOL,
To handle null values in COBOL host variables in SQL you need to assign a "null indicator" for each nullable variable.
See: Using host variables in SQL Statements (with examples in COBOL).
The null indicator will typically be negative if the result variable is null.
By default, all parameters to a DB2 for z/OS Native SQL Stored Procedure are nullable. (Db2 for z/OS 12.0.0 - Creating Native SQL Procedures)
For other ways of solving what I perceive is the task at hand,
Whilst I think at least DB2 User-defined Functions may support function overloading, stored procedures does not. That could have been an alternative.
Otherwise might I suggest returning a dynamic result set from your stored procedure? Then it would be up to the caller of the stored procedure to handle different configurations of the result sets, which is totally doable in COBOL.
Regarding UDF Overloading:
"A schema can contain several functions that have the same name but each of which have a different number of parameters or parameters with different data types. Also, a function with the same name, number of parameters, and types of parameters can exist in multiple schemas."
https://www.ibm.com/support/knowledgecenter/SSEPEK_11.0.0/sqlref/src/tpc/db2z_functionresolution.html
Hope it was to some help.
Related
I need to have a Text data type column (instead of an Lvarchar, for space reasons) in a table. But I have a problem. If I pass the insert/select statement from C#, with the parameter being a string, the connector will do the type conversion automatically and everything works fine.
But I want to have it on a stored procedure. Although, it doesn't let me:
have a Text data type as an input parameter;
have load/unload statements in a stored procedure (that way I could just pass the string and unload and then load it to the table);
can't seem to make a data type conversion in informix...
So... Given this situation, how can I possibly do this? I'm aware that a Text data type is hell to work with but it's also great for saving storage space and not pre-setting a size limit. Correct me if I'm mistaken, as I'm new to Informix.
In this case, I just need to save text (which may or may not be big/small) and return it when needed. Don't need to work it in any way other than that.
Frequently, PSPP/SPSS syntax documentation (example) suggests I must to pass a list of variables with /VARIABLES=var_list and this is not an optional subcommand.
But I have a lot of datasets to process. I would like to programmatically get a list of all variables in the active dataset, pass that to a procedure, and then generate a file from the procedure output.
I've tried /VARIABLES=* but that didn't work.
error: DESCRIPTIVES: Syntax error at `*': expecting variable name.
You can use display variables. or display dictionary. to generate a table of all variables and their attributes which could then be captured using OMS. However if you want to pass all variables to a function that expects a list you can use all, i.e. descriptives /variables= all..
/VARIABLES is often optional in procedures, but ALL stands for all the variables. If you need to refine by a particular measurement level, type or other metadata, try the SPSSINC SELECT VARIABLES extension command. This command applies various filters based on the metadata and creates a macro with the variables that pass. You can then use that in any context.
The web seems a bit short on working examples for something that should be quite common. A plain Jane example of "Get me some records". This is my first ever Stored proc and all I want is to see some records. Why is that so flipping hard? ;-) I figure that if I can get one example that works, I can tune it from there into something I can really use. This is taken from another example I found on the web. Doesn't compile because CURSOR declaration is a syntax error of some sort.
CREATE PROCEDURE "SCHEMA"."GETRESULTSET (
IN "p1" VARCHAR(30))
DYNAMIC RESULT SETS 1
BEGIN
DECLARE CURSOR cur1 WITH RETURN ONLY TO CLIENT FOR
SELECT partitioninfo FROM SCHEMA.SessionInfo where username = p1;
OPEN cur1;
END;
Anyway, sure could use a clue. I saw an example where the CURSOR was declared separately from the SQL but then there wasn't an example that showed how to get the variable into the SQL when it was declared as a VARCHAR. The example I am working off of was pretty old but it's the best I could find.
A Teradata MACRO would be a better solution for what you have described.
REPLACE MACRO [MyDB].GetResultSet(p1 VARCHAR(30)) AS (
SELECT "Partition"
FROM DBC.SessionInfo
WHERE UserName = :p1;
);
EXEC MyDB.GetResultSet
While a stored procedure could be used to accomplish the task cursor based logic used in other popular database systems (Oracle, SQL Server, etc.) can lead to bad programming habits in Teradata. Generally, processing large cursors in Teradata degrades performance. Many things that you have have used cursor for in other DBMS' are better served to be done with SET based logic where possible.
That being said cursors can be used successfully in Teradata to perform certain tasks that require conditional logic or dynamic SQL processing. I hope this helps and if you have a more concrete example you need help with I'd be happy to offer some suggestions.
Edit:
This DDL for your procedure works against Teradata 13.10:
CREATE PROCEDURE "SCHEMA"."GETRESULTSET" (
IN "p1" VARCHAR(30))
DYNAMIC RESULT SETS 1
BEGIN
DECLARE cur1 CURSOR WITH RETURN ONLY TO CLIENT FOR
SELECT "Partition" FROM "SCHEMA".SessionInfo where username = p1;
OPEN cur1;
END;
The cursor name has to proceed the CURSOR key word. PartitionInfo is not a valid column on DBC.SessionInfo. Not sure if "Schema" gets replaced by MyBatis or not, so you may have to tweak the SELECT statement.
I have a requirement like inserting a large data from visual prolog end to the oracle database and also most importantly all the data needs to be injected through a single stored procedure call. I have tried them passing the data as string values, but there is a constraint in visual prolog like the length the string variable cannot exceed '250' characters. So passing them as strings is not viable for my requirement. so I tried passing the data in the form of prolog list using term_str(). But unfortunately the list/array item is not handled at the oracle end. My DBA has suggested me to pass the large data in the form of an array objects.
Do anybody have an idea how to convert the array data into an array object in visual prolog. or any other recommendations for inserting the large data into database through a single stored procedure call??
Not sure about Visual Prolog, but for SWI there is a nice
chapter in the manual on the ODBC
We have an old application that reads in SQL text files and sends them to Sybase ASE 12.51. Our legacy app was written in Delphi 5 and is using the BDE TQuery component for this process and accessing Sybase with the BDE SQLinks for Sybase.
Pseudo code:
SQLText=readSQLFile;
aTQuery.SQL.add(SQLText);
aTQuery.ExecSQL;
Recently we moved our DB access layer to the Delphi XE ADO implementation - TADOQuery, using the Sybase supplied ADO provider, still using same model:
SQLText=readSQLFile;
aTADOQuery.SQL.add(SQLText)
aTADOQuery.ExecSQL;
After migrating to ADO, we discovered that certain data was missing. We traced the failure to this SQL construct:
Select myColumn from myTable
Where tranID = null
Knowing that this construct is sematically questionable at best, I did a 'double take' when I saw this code, but Sybase 12.5 accepts it - however using ADO, this segment fails.
We decided to change:
Where tranID = null
to
Where tranID is null
Then the missing data was loaded - problem solved, for this segment and several others as well.
Does anyone have an explanation for this behavior? Where/why did ADO apparently intercept and reject this seqment whereas the BDE passed it thru?
TIA
"NULL" has a very special meaning, and SQL needs a special handling. You can't compare a value to "NULL", that's why there is the special operator IS (NOT) NULL to check for it. An exhaustive explanation would take some space, here a simple explanation.
From a "mathematical" point of view, NULL can be thought as "infinity". You can't compare two infinite values easily, for example think about the set of integer numbers and even numbers. Both are infinite, but it seems logical the former is larger than the latter. All you can say IS both sets are infinite.
That's also helps to explain for example why 1 + NULL returns NULL and so on (usually only aggregate functions like SUM() ecc. may ignore NULL values - ignore, not turn NULLs into zeroes).
This metaphor may not hold true in sorting, because some databases choose to consider NULL less than any value (some kind of -infinity and thereby returning them first in ascending order), other the other way round. Some have an option to set where to return NULLs.
Check your database documentation about NULL arithmetics and NULL comparisons. field = NULL should have never been used, don't know if Sybase accepts it, but most SQL implementations don't, and I guess it is not SQL standards compliant. It is far better to get used to the IS (NOT) NULL syntax.
Update: Sybase has a "set ansinull" option, from the documentation (always RTFM!), in 12.5.1 it was expanded to disallow the '= NULL' syntax (when set to ON to make it compliant with SQL standards). When set to OFF '= NULL' works as 'IS NULL'.
Maybe the SQL Links or the ADO provider set it to one value or the other.