Get a parameter's name - reflection

I want to get a parameter's name in plsql.
For example,
procedure sp_example(myParam in varchar2) is
paramName varchar2(30);
begin
paramName = 'myParam';
end
end procedure sp_example;
Is there a way to get the name of myParam using reflection, instead of hard coding it?

Try:
select argument_name from all_arguments where object_name = 'SP_EXAMPLE';
This view can also show you the data types, positions, etc., and you can use it in SQL or PL/SQL. Plenty of info in the various metadata views.

If you want to get the names of parameters retrieved in their respective positions, use
select argument_name from user_arguments where object_name='SAMPLE_PROC' order by position;

Related

Creating a Record using PLSQL

I have a pretty basic procedure that I am trying to create. I just need to create a record for a single row from a table. What am I missing? The error code that I am receiving is "encountered the symbol declare when expecting...."
Create or Replace Procedure Luke as
Declare
Type type_basket is record(Term_code section.term_code%type,
Subject_Code section.subject_code%type,
Course_Number section.course_number%type,
Section section.section%type);
Rec_Basket type_basket;
Begin
Select term_code, subject_code, course_number, section into Rec_basket
from Enrollment
where term_code=201201 and course_number=105;
dbms.output_put.line(rec_basket.term_code);
end;
DECLARE is only needed for anonymous blocks and subblocks, you don't use it to declare stored procedure variables:
Note:
The declarative part of a subprogram does not begin with the keyword DECLARE, as the declarative part of an anonymous block does.
So remove that line:
Create or Replace Procedure Luke as
Type type_basket is ...
Rec_Basket type_basket;
Begin
Select ...
end;
/
You could use a %rowtype variable instead of explicitly declaring a record type, and select the whole row into that, but I assume your assignment is specifically about records.

Casting a String to a Symbol in PLSQL

I've created an anonymous PLSQL block to test and I'm running into an issue with the formatting.
set serveroutput ON
BEGIN
FOR I IN (SELECT DISTINCT do.SUBOBJECT_NAME from dba_objects do WHERE do.object_name='MY_TABLE' AND do.OBJECT_TYPE='TABLE PARTITION') LOOP
dbms_output.put_line(I.subobject_name);
SELECT
t.field
INTO
some_var
FROM
MY_TABLE PARTITION(I.subobject_name) t;
END LOOP;
END;
However I get several compilation errors, which I believe are related to the fact that I.subobject_name is a string. I believe the PARTITION function wants an actual partition symbol(proper term for this?), but I can't give it in this loop.
Is there any kind of casting function that can perform what I'm looking for?
Partition IS NOT A FUNCTION. Partition is keyword
In your context your whole statement is static , thus you CANNOT pass partition name into it; partition name must be specified at compile time.
You can re-create your statement dynamically and then pass partition name in the loop -
a-la you are doing it. Just make sure you will concatenate string and not use bind variables, or your statement at run time won't be parsed and won't run.
Name for the symbol is table partition

Stored procedure - Multiple string parameters with IN clause sql

i want to filter the rows using Stored procedure. below is my query
Create PROCEDURE [dbo].[Test]
#SearchTerm VARCHAR(100)
AS
BEGIN
Select * from master where name in (#SearchTerm)
END
In code behind,
cmd.Parameters.AddWithValue("#SearchTerm", "peter")
when i run with above parameter, it's work fine.
but when i pass like this
cmd.Parameters.AddWithValue("#SearchTerm", "'peter','rahul'")
this time no rows fetching.
i tried manually then also it's not working.
exec Test ''peter','rahul''
Please help me, how to pass muliple string Using IN clause?
One method is
Create PROCEDURE [dbo].[Test]
#SearchTerm VARCHAR(100)
AS
BEGIN
Select * from master where ','+#SearchTerm+',' like '%,'+name+',%'
You can find more methods at http://www.sommarskog.se/arrays-in-sql-2008.html

Stored procedure to return a list of sequence IDs

I need a little stored procedure to do the following logic?
procedure_name(seq_name IN varchar2(50), block_count IN int, return_ids OUT)
loop from 1 to block_count
return_ids := select 'seq_name'||.nextVal from dual;
end loop
return return_ids
Basically what I want to do is have a stored procedure that lets me pass in a sequence name, how many IDs I need and return to me the generated listed of IDs that I can use in JAVA. The reason to do this for me is to return a list of IDs that I can use in JAVA and no one else is using those sequence IDs. Where they will be used in some other bulk inserts later down the line. In essence, reserve a block of sequence IDs.
Here is one way to return an array from PL/SQL procedure.
Create a collection type of numbers, initialize it in your procedure and populate it with numbers to return. For example:
create or replace type narray as table of number;
create or replace procedure get_seq_ids(seq_name in varchar2,
block_count in number, return_ids out narray)
as
begin
return_ids := narray();
return_ids.extend(block_count);
for i in 1 .. block_count
loop
execute immediate 'select ' || seq_name || '.nextval from dual'
into return_ids(i);
end loop;
end;
/
I'd be concerned over the logic that requires IDs to be generated before records are inserted into the database.
Alternatively you may want to consider inserting rows first, selecting the ids from the rows, and then using an update statement to do your bulk operation. This however is still not as preferable as having the Java code not depend on ids until after the actual information is ready to be inserted.
You can push your information into XML (or any other data format your database can understand) and then call a stored procedure to do the bulk inserts.
Another option may be to use the RETURNING clause to return the sequence values automatically after the insert.
IMHO, the best thing you can do is just referencing sequence_name.nextval right in your INSERT INTO, in the VALUES clause.
You said you want to avoid others using the same IDs. Referencing this site:
The sequence (or Oracle, for that matter) ensures that no other session or other call to nextval within the same session gets the same number from the sequence.
So, the uniqueness of a sequence' numbers are guaranteed in Oracle.
Here's what I do for the Java application I support (which also uses bulk inserts into deeply hierarchical tables)
PROCEDURE get_nextvals
(
p_values OUT SYS_REFCURSOR,
p_count IN PLS_INTEGER
)
IS
-- return the next p_count values from the PK sequence
BEGIN
OPEN p_values FOR
SELECT
<schema>.<sequence>.nextval
FROM
dual
CONNECT BY
LEVEL <= p_count
;
END;
It was easier to just pass a cursor out to java than having the app use a table type defined in the DB.

How to retrieve stored procedure return values from a TableAdapter

I cannot find an elegant way to get the return value from a stored procedure when using TableAdapters.
It appears the TableAdapter does not support SQL stored procedure return values when using a non-scalar stored procedure call. You'd expect the return value from the auto-generated function would be the return value from the stored procedure but it isn't (it is actually the number of rows affected). Although possible to use 'out' parameters and pass a variable as a ref to the auto generated functions it isn't a very clean solution.
I have seen some ugly hacks on the web to solve this, but no decent solution. Any help would be appreciated.
http://blogs.msdn.com/smartclientdata/archive/2006/08/09/693113.aspx
The way to get the return value is to use a SqlParameter on the SqlCommand object which has its Direction set to ParameterDirection.ReturnValue. You should check the SelectCommand property of the TableAdapter after calling Fill.
NOTE: The way to go is using a SqlParameter where the Direction = ParameterDirection.ReturnValue
With that said, as someone already mentioned SqlParameters, here is a dynamic method alternate using a DataSet. (if thats how you ride):
Example SQL statement and C# as fallows:
string sql = #"DECLARE #ret int
EXEC #ret = SP_DoStuff 'parm1', 'parm2'
SELECT #ret as ret";
DataSet ds = GetDatasetFromSQL(sql); //your sql to dataset code here...
int resultCode = -1;
int.TryParse(ds.Tables[ds.Tables.Count-1].Rows[0][0].ToString(), out resultCode);
The stored procedure results are loaded into a DataSet and will have as many DataTables as return select statements in the stored procedure.
The last DataTable in the DataSet will have 1 row and 1 column that will contain the stored procedure return value.
I cannot say for certain because I have do not use TableAdapters, but you might need to look at your stored procedure and include the following around your procedure.
SET ROWCOUNT OFF
BEGIN
<Procedure Content>
END
SET ROWCOUNT ON
Closing this question as it appears return values aren't supported and there is no elegant workaround!
Actually, all you need to do is to return your final value from the stored procedure using a SELECT statement, not a RETURN statement. The result of the SELECT will be the return value. For example, if you simply make your sp exit statement "SELECT 1" then you'll get back a 1. Now just SELECT the actual scalar you want returned.

Resources