How to solve ORA-01006 in procedure? - database

I need to have a procedure to calculate count of something and insert it into another table but get error
ORA-01006:bind variable does not exist.
Here is my code:
Insert part is not be executed and jumps to exception instead.

Your dynamic SQL call is
EXECUTE IMMEDIATE v_sql USING v_result;
This is the syntax for passing a parameter into the dynamic statement. But your code doesn't take any parameters, because you have concatenated them in the string. Therefore, the code hurls ORA-01006.
What you need to do instead is provide a variable for the result set to be return into. So the call should be
EXECUTE IMMEDIATE v_sql INTO v_result;
The syntax for EXECUTE IMMEDIATE is comprehensively covered in the PL/SQL guide. You should bookmark the Oracle documentation for future reference.

Related

How to call database package in ODI? The db package contains list of functions and out of those I want to call only one function in ODI

There's a database package and it contains list of functions. Out of the list, I want to call one function in ODI12c. I tried to create an ODI procedure and within that called the db package using .(return variable);
However, when I execute this ODI procedure, it fails with error saying " is not a procedure or is undefined.
Any help is appreciated.
Thanks
I tried to create an ODI procedure and within that called the db package using .(return variable);
Error: is not a procedure or is undefined.
If your goal is to store the value returned by that function into a ODI variable, you can use something like this as the refresh query for that variable :
select <SCHEMA_NAME>.<PACKAGE_NAME>.<FUNCTION_NAME>(<PARAMETERS>) from DUAL;
You can then refresh that variable in a package or a load plan.
If you don't need to store the result of the function but just execute it, the easiest is to use a PL/SQL block in your ODI Procedure. So make sure you set the technology to Oracle for that procedure step. Then use something like this :
BEGIN
<SCHEMA_NAME>.<PACKAGE_NAME>.<FUNCTION_NAME>(<PARAMETERS>);
END;
A nicer way to do it would be to avoid hardcoding the schema name and get it from the topology instead. As it can be a different schema through different contexts we need to use the substitution API that will replace it at runtime. Here would be the result for a variable :
select <%=odiRef.getSchemaName("<LOGICAL_SCHEMA_NAME>", "D")%>.<PACKAGE_NAME>.<FUNCTION_NAME>(<PARAMETERS>) from DUAL;
And for a procedure :
BEGIN
<%=odiRef.getSchemaName("<LOGICAL_SCHEMA_NAME>", "D")%>.<PACKAGE_NAME>.<FUNCTION_NAME>(<PARAMETERS>);
END;
As this is a call to function, there has to be a variable created in ODI procedure to which the function returns the value.
So I did a small change and it worked.
DECLARE
var1 varchar2(1000);
v_ret Boolean;
BEGIN
v_ret := <Function Call>;
END;

How to check if nested stored procedure was executed in tsqlt

I have stored procedure which conditionally execute nested stored procedure.
In unit test, I need to check if this nested stored procedure was executed.
I tried tSQLt.SpyProcedure, but it doesnt seems to work the way i want.
content of my unit test
-- Assembly
exec tSQLt.SpyProcedure 'procedureName', 'raiserror(''procedureName was fired'',16,1)'
-- Assert
exec tSQLt.ExpectException 'procedureName was fired'
-- Action
exec masterProcedureName -- triggers procedureName
but tsqlt.run 'unitestName' returns
failed: (Failure) Expected an error to be raised.
Do you have any idea ?
While, as you mentioned, your approach works, I suggest you use the ..._spyprocedurelog table instead. It’ll allow you to catch multiple executions as well as the parameters passed each time. And if you at some point add error handling to the outer procedure, this will still work.
Check out the example in the SpyProcedure documentation.
My apologies, following code does work i had mistake somewhere else.

Get current stored procedure name?

Inside my stored procedures, I always have a comment line to test my stored procedure:
/*
EXEC [schema].[uspNameOfSP]
*/
I want to simplify this a bit, so that I can copy paste it to other stored procedures without having to change the name everytime. I want to do something like this:
/*
EXEC #thisStoredProceduresName
*/
Is something like that possible?
You can't.
The reason is when you execute it to test you are only selecting and executing that single line of code so it's not part of or in a stored procedure when it executes.
I think this is a bad idea, but it sort of accomplishes what you're looking for.
USE some_db;
GO
CREATE PROCEDURE /*EXECUTE */ usp_Proc AS
BEGIN
SELECT 1;
END
I was dubious, but I ran the CREATE statement, then scripted out the proc and the commented EXECUTE statement stuck.

Can a dynamic table be returned by a function or stored procedure in SQL Server?

I would like to call a stored procedure or user-defined function that returns a dynamic table that is created via a pivot expression. I don't know the number of columns up front.
Is this possible? (I am not interested in temporary tables)
You can do that via stored procedure as it can return any kind of table, question is what are you trying to achieve and what will you do with data that you have no idea about?
This cannot be done with functions (as the returned table structure must be pre-defined), but it can be done with a stored proceed. Some psuedo-code:
CREATE PROCEDURE Foo
As
DECLARE #Command
SET #Command = 'SELECT * from MyTable'
-- For debugging, work in an optional PRINT #Command statement
EXECUTE (#Command)
RETURN 0
When you run stored procedure Foo, it builds your query as a string in #Command, and then dynamically executes it without knowing anything about what is being queried or returned, and the data set returned by that EXECUTE statement is "passed back" to the process that called the procedures.
Build your query with care, this stuff can be really hard to debug. Depending on your implementation, it might be a source of SQL injection attacks (remember, the stored procedure really doesn't know what that dynamic query is going to do). For quick stuff, EXECUTE() works fine, but for safer and more useful (if elaborate) solutions, look into sp_ExecuteSQL.
Yes, you can do this from a Stored Procedure, but not from a user-defined Function. It is worth looking into the Table Value Function, I believe you can also return a dynamic table from there, but I have not used that myself.

Execute stored procedure for all the result set without using cursor

If I want to execute stored procedure using the values returned from result set of a select statement. So number of times SP should get executed is equal to the number of result set from the select statement.
Is there any other way than using a cursor to do the above?
UPDATE
Can anyone please give sample code with While loop at least?
In T-SQL there are only 2 ways for iteration. While loop or cursors. If you don't want to use cursors, you had to use while loop as James Wiseman said.
ANother way to accomplish this situation is SQL CLR. If you are using SQL CLR, you can use all C# (or VB.Net) iterations to reach your goal.
I would convert the proc to use a table variable and pass the data set in using that. The beauty of this is that once you have made the change, you can use the same proc for either single row inserts or mulitple and do it in sets not row-by-row.
You need SQL Server 2008 for this one.
You'll have to convert your proc to a Multi-Statement Tabled Value UDF..
create function dbo.udf_Whatever_That_Proc_Did(
#SameOldParam as int
)
AS Begin
Declare --same variables here
/*same code in your proc that does not
- invoke nondeterministic built-in function
- change state of database
- return messages to caller
*/
Return
End
To utilize function:
Select *
from dbo.udf_Whatever_That_Proc_Did(9999)
An alternative to a cursor is a while loop, which is sometimes recommended as an alternative to SQL Cursors.
Is the problem that you want to avoid using the cursor, or is it that you are wating to avoid iteration altogether?
Maybe this could help you, create a UDF and then call the stored proc from within that UDF. Since you can call UDF in a select query, it should execute the stored proc as many times as you have results in select query.

Resources