AS400 Call a stored procedure from another stored procedure - c#

I am trying to call a stored procedure from another stored procedure.
I tried different syntax but with no success.
The first stored procedure returns a table. For the test, I just want to return from the second stored procedure what I got from the first one.
First stored procedure (SP01):
BEGIN
DECLARE C2 CURSOR WITH RETURN FOR
SELECT DISTINCT TBL.*
FROM LIB.TABLE1 TBL;
OPEN C2 ;
END
It works fine when calling it from c#.
Second stored procedure (SP02):
BEGIN
DECLARE C2 CURSOR WITH RETURN FOR
CALL SP01();
OPEN C2 ;
END
I am getting an error:
Vendor Code: -104
Message: [SQL0104] Token SP01 was not valid. Valid tokens: ;. Cause ....
A syntax error was detected at token SP01.
What is the correct syntax / approach for SP02?
EDITED:
In ms access, I was able to create a query QUERY2 based on another query QUERY1:
SELECT * FROM QUERY1;
or even joining it like a table
SELECT * FROM TABLE1 INNER JOIN QUERY1 ON (TABLE1.FIELD1 = QUERY1.FIELD1);
I need to move all my tables and queries from mdb to AS400 and write a C# application that use those queries.
I do not see so much examples on the net, maybe my approach is wrong.
I have multiple queries to run and each one depends on another one. I thought calling one stored procedure from my C# application and this one will call to another one and so on.
Is it a correct way to run a series of queries that depends one to each other?
Or is there a way to call from my c# application to all the queries independently and from the code to build the dependency between them, look like this approach is wrong?

If you are using IBM i version 6.1 or earlier, you cannot access result sets returned by a stored procedure using a language SQL stored procedure. For version 7.1 or later, you can use the ASSOCIATE RESULT SET LOCATORS statement to retrieve the result sets. See the ASSOCIATE LOCATORS statement in the SQL Reference manual (http://www-01.ibm.com/support/knowledgecenter/ssw_ibm_i_71/db2/rbafzassocloc.htm?lang=en) for more information.
Once you have the locator, you use the ALLOCATE CURSOR statement (http://www-01.ibm.com/support/knowledgecenter/ssw_ibm_i_72/db2/rbafzalloccsr.htm?lang=en) to get a cursor from the RESULT SET LOCATOR.
Further examples can be found here: http://www.itjungle.com/fhg/fhg082510-printer02.html

Related

Use Stored procedures that uses the "EXECUTE" command in a TableAdapter

I am writing a program that needs to call a MSSQL stored procedure called dbo.getsystemnumber; this procedure generates the next pyd_number which I need to insert a new line in the paydetail table. This is what the procedure looks like:
ALTER PROCEDURE [dbo].[getsystemnumber](#p_controlid varchar(8), #p_alternateid varchar(8))
AS
DECLARE #return_number int
EXECUTE #return_number = dbo.getsystemnumber_gateway #p_controlid, #p_alternateid, 1
RETURN #return_number
I'm using the c# tableadapter to call this procedure but when I do call it and say put it on a label or listbox, it just returns a value of 0. The function still updates in SQL server to the next number when I run the program.
TMW_Test2DataSetTableAdapters.paydetailTableAdapter returnPydNumber = new TMW_Test2DataSetTableAdapters.paydetailTableAdapter();
lbPydnumber.Items.Add(Convert.ToInt32(returnPydNumber.getsystemnumber("PYDNUM", " ")));
However, when I use the preview data option in the tableadapter view I get the right number that I'm supposed to get. In SQL Server we call it like this:
declare #pyd_number int
execute #pyd_number = dbo.getsystemnumber N'PYDNUM', NULL
select #pyd_number
TableAdapters use the result of a SELECT statement for their data, not the RETURN value of a query. Under the hood, a single value TableAdapter will use ExecuteScalar(), which takes the first column in the first row of the resultset.
This blog post explains this and a workaround. Either change the store procedure to SELECT the value instead of RETURNing it, or change the generated code to look at the ReturnValue of the database call.

In MySQL, how to pass a set of objects to a stored procedure?

In my C# code, I will be populating a Dictionary.
I need to get that data into a MySQL table in the most efficient way possible.
Is it possible to pass that to a MySQL stored procedure? I guess I could pass it in some sort of string with commas, etc, so that the stored procedure could then call a function to parse the string and populate the table, but that's a pain.
Any other ideas?
Thanks!
Based on the comments so far, let my try to show the code/sudocode I'm working on.
The code that builds the dictionary will look something like this:
private void DistributeCallsToReschedule()
{
CallTimeSpacing = GetNumMinutesInNextCallWindow() / callsToReschedule.Count;
DateTime currTimeToCall = new DateTime();
foreach (int id in callsToReschedule)
{
CallIdTimeToCallMap.Add(id, currTimeToCall);
currTimeToCall.AddMinutes(CallTimeSpacing);
}
}
So, the dictionary can contain my entries.
What I HOPE I can do is to pass the dictionary to a stored procedure as shown below.
If this isn't possible, what's the most efficient way to do what the stored procedure indicates; ie,
the stored procedure wants to have a table to JOIN to, that has the data from the dictonary populated in the C# code. In other words, what's the most efficient way to get the dictionary's data into a table in MySQL? If this isn't possible, and I have to loop, what's the most efficient way to do that: Iteratively call a stored procedure? Build a prepared statement that has all the values (build via StringBuilder, I suppose)?
PARAMETERS PASSED TO STORED PROCEDURE BY C# CODE:
#CallIdTimeToCallMap
Put #CallIdTimeToCallMap into CallIdTimeToCallMapTable;
update cr
set cr.TimeToCall = map.TimeToCall
from callRequest cr
inner join CallIdTimeToCallMapTable map on
cr.id = map.id
You have to map objects to tables and columns before any relational database can do anything with them. Objects are not relations.
You don't say what the parameters are that the stored procedure is expecting.
If it's an INSERT or UPDATE that expects a large set of objects, I'd wonder if a stored procedure is the right answer. You'd have to call it repeatedly, once to write the row for each object in the set. I'd consider a prepared statement, binding variables, and batching so you can do it in one round trip.
Is the set a single unit of work? Have you thought about transactional behavior?

mysql stored procedure parameters don't seem to work with "#" (At sign)

I'm changing a MS SQL database over to MySQL.
I've rewritten one of the stored procedures which takes a parameter called #Account_Number. When I run the stored procedure in MySQL I get the following Message: Error Code: 1048 Column 'Account_Number' cannot be null.
Using the workbench I finally tinkered around and figured out that when I removed the "#" from my stored procedures and renamed them like parmAccount_Number the stored procedure would execute.
I really want to keep the stored procedure input parameters named the same, and I don't want to go back and rename my MS SQL parameters... just in case I want to flip flop Databases.
I can't find any info on what MySQL does with the "#"....
Is there a way to make it work with "#" ?
EDIT
Declaring the stored procedure
CREATE PROCEDURE `My_sp`(
`#Account_Number` varchar(8),....)
insert portion of sp
insert into
My_Table
(
Account_Number, ...
)
values
(
#Account_Number,...
)
No, you can't name MySQL procedure variables starting with the # sign.
The # sign character signifies a MySQL User-Defined Variable, which is quite different than a procedure variable.
The big differences is that user defined variable aren't declared (they don't have a datatype), and they have scope within a session (database connection), not just a procedure. It persists for the entire session. (This also means it's subject to modification anywhere in the session, any SQL statement, trigger, function or procedure can modify it, which makes it very useful, and also makes it a potential pitfall.
It's possible to use user defined variables as the actual values passed to a procedure or function. But you can't name MySQL procedure variables or parameters starting with an # sign.
I believe this is compliant with the SQL 2003 standards.
Documentation here:
http://dev.mysql.com/doc/refman/5.5/en/user-variables.html
UPDATE
Interesting.
Given that you are able to get a procedure compiled by enclosing the parameter name in backticks (as shown in the example statement you added)...
You might try enclosing the parameter name reference in the INSERT statement in backticks as well. (I've never tested that; I've never tried "back ticking" variable names before; I've never seen that done before.) But if the procedure is actually compiling, then maybe that would work.

Stored Procedure Return Type Can Not Be Detected

I am trying to drag this procedure over to the dbml in VS 2012 and I am getting the return type cannot be detected message.
I have tried these:
LINQ to SQL - Stored Procedure Return Type Error
The return types for the following stored procedures could not be detected
I tried re-writing the procedure as a CTE and also as union to remove the OR, but it is giving me the same message.
The only return type in the designer properties for the method is int32.
Here is my procedure:
ALTER PROCEDURE [dbo].[GetStringFromFiles]
#SearchWord NVARCHAR(100) = null
AS
BEGIN
SET NOCOUNT ON
SET #SearchWord = UPPER(#SearchWord);
Select
a.FileId <---Guid
, a.FileData <---Binary
, a.BaselineId <---Guid
, a.FileName <---NVARCHAR
, a.FileExtension <---NVARCHAR
, b.FileByItemId <----Guid
, b.ItemId <---Guid
From FileTable a
Inner Join
FileByItem b on a.FileId = b.FileId
WHERE CONTAINS(a.FileData,'FORMSOF(INFLECTIONAL, #SearchWord)') or FREETEXT(a.FileData, #SearchWord)
RETURN 1
END
UPDATE:
A. I can add it if I comment out the entire Where Clause -- Auto-Generated-ReturnType
B. If I take away the or and just use:
WHERE CONTAINS(a.FileData,'FORMSOF(INFLECTIONAL, #SearchWord)')
it lets me add it -- Auto-Generated-ReturnType
C. If I just use
WHERE FREETEXT(a.FileData, #SearchWord)
It throws the error so it doesnt like the FREETEXT
If I comment the where clause out and add it and let it generate the return type then alter the procedure in the db are there any issues with that?
This is somewhat related. I stumbled across the same error today but for a different reason. If your query uses a temporary table in its results then it is unable to automatically assign the return type.
I changed it to a table variable (performance was not a major concern/and was not impacted)
Hope this helps someone browsing.
The line
RETURN 1
is the culprit in both the cases. Lose it and Linq should be able to detect the types your result set.
Linq to Sql won't get the results directly from a Stored procedure.
Instead an ISingleResult will be returned. You have to enumerate
through the result set to get the values returned from the stored
procedure
If the stored procedure have any error also then this error can occur, for me its happened once since one of the table name was changed.
Another factor is to set Primary Keys and table relations if possible
A simple way to solve this issue is (December 2019)
Just making double # precede #tmp => ##tmp
Comment out DROP TABLE #tmp => --DROP TABLE #tmp
Execute stored procedure
Drag stored procedure again and That's it, It will generate return type
Last, Turn your store back to the first situation and then save.
Hope I can help.

Change returned table name from stored procedure at the SQL side

I have written a single stored procedure that returns 2 tables:
select *
from workers
select *
from orders
I call this stored procedure from my C# application and get a DataSet with two tables, and everything is working fine.
My question is how can I change the tables name at the SQL Server side so that in the C# side I will be able to access it via a name (instead of Tables[0]):
myDataSet.Tables["workers"]...
I tried to look for the answer in Google but couldn't find it. Maybe the search keywords was not sufficient.
You cannot really do anything from the server-side to influence those table names - those names only exist on the client-side, in your ADO.NET code.
What you can do is on the client-side - add table mappings - something like:
SqlDataAdapter dap = new SqlDataAdapter(YourSqlCommandHere);
dap.TableMappings.Add("Table", "workers");
dap.TableMappings.Add("Table1", "orders");
This would "rename" the Table (first result set) to workers and Table1 (second result set) to orders before you actually fill the data. So after the call to
dap.Fill(myDataSet);
you would then have myDataSet.Tables["workers"] and myDataSet.Tables["orders"] available for you to use.
The TDS Protocol documentation (Which is the protocol used to return results from SQL Server) does not mention a "resultset name". So the only way you will ever be able to access the result sets in ADO.net is by the number as mentioned in your example.

Categories