I created a procedure with dynamic sql,but cannot run it successfully.
create or replace procedure getdata(string par1, results out cursor)
as
declare sqlBase varchar2(100);
begin
sqlBase := 'open '||results|| ' for select * from studetns';
end;
After running, the following error message pops up:
PLS-00306, wrong number or types of arguments in call to '||'
I just need to filter data by some parameters ,but some parameters may be null or empty,
so I need to filter dynamic. like if(par1 is not null) then ........
so here I need to use dynamic sql. in C# programe, use cursor to return result.
like here ,I use cursor type to open select statements.
but in sql editor, I get right sql statement.
Can Somebody help me with this?
Your syntax is a little bit wrong. Try with this:
create or replace procedure getdata(par1 varchar2, par2 varchar2, results out sys_refcursor)
as
begin
open results for
select *
from students
where name = nvl(par1, name)
and surname = nvl(par2, surname);
end;
Why do you need parameter par1? Better to use PL/SQL type varchar2, not string. They work the same, but varchar2 is a base data type, while string is a subtype of it.
Depending on what you want to achieve, I would try something like that:
create or replace procedure getdata(par1 varchar2, results out sys_refcursor)
as
sqlBase varchar2(100);
begin
sqlBase := 'begin open :X for select * from students;end;';
execute immediate sqlbase USING IN OUT results;
end;
You can't concatenate a cursor into a string as you tried it, that's where your error came from.
But if you could clearify your question we could help you better.
Related
Devs,
I've searched everywhere I can, but I could not find solution to this simple problem.
Situation:
I need to write a procedure where it takes a column name as the input and return all the distinct values present in that column as output. And then I have to use this procedure in some c# code.
In MS server, it is very easy as it will directly give the set of results unlike in PL/SQL.
Script I could write (which is not giving me the result I need):
CREATE OR REPLACE
PROCEDURE GetCol(PARAM IN STRING, recordset OUT sys_refcursor)
AS
BEGIN
OPEN recordset FOR
SELECT DISTINCT(PARAM)
FROM my_table;
END
;
When I try to check the data in the recordset using this code:
DECLARE
l_cursor SYS_REFCURSOR;
l_sname VARCHAR2(50);
BEGIN
GetCol('col_name',l_cursor);
LOOP
FETCH l_cursor INTO l_sname;
EXIT WHEN l_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(l_sname);
END LOOP;
CLOSE
Can someone help me with this code please.
You can also open a ref_cursor for a string value. Please take a look at this:
CREATE OR REPLACE PROCEDURE GetCol(PARAM IN VARCHAR2, recordset OUT sys_refcursor)
AS
QRY varchar2(100);
BEGIN
QRY := 'SELECT DISTINCT '||PARAM||' FROM my_table';
OPEN recordset FOR QRY;
END;
Then:
DECLARE
l_cursor SYS_REFCURSOR;
l_sname VARCHAR2(50);
BEGIN
GetCol('col_name',l_cursor);
LOOP
FETCH l_cursor INTO l_sname;
EXIT WHEN l_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(l_sname);
END LOOP;
END;
Your problem is caused by ambiguity about what PARAM is in the procedure's SELECT statement:
CREATE OR REPLACE
PROCEDURE GetCol(PARAM IN STRING, recordset OUT sys_refcursor)
AS
BEGIN
OPEN recordset FOR
SELECT DISTINCT(PARAM) -- Ambiguity here
FROM my_table;
END;
Does PARAM refer to the table column or to the first parameter of the procedure? Oracle has assumed the parameter. You can explicitly say which like this:
SELECT DISTINCT(my_table.PARAM)
FROM my_table;
You could if appropriate (it probably isn't here) specify the procedure parameter instead:
SELECT DISTINCT(GetCol.PARAM)
FROM my_table;
Generally this is best avoided by:
always using table aliases in column references select statements, and
having a standard for parameter names that makes them less likely to clash e.g. P_PARAM.
I am new to Oracle and Stored Procedures. I just would like to know if its possible, like in SQL Server, to return a recordset with Field Names to an extern program. I read some documentations but I'm not sure if I'm on the right track. When I use Sys_Refcursor I can only return one Field and not as many as I would like to.
I need to return multiple Field Names and I have one input parameter.
In the documentation of the program, i have an example for SQL Server and I would like to have the same for my Oracle Stored Procedure:
Use
Go
Set Ansi_Nulls ON
Go
Alter Procedure
#InputLocation Varchar(255)
As
Begin
Set Nocount On;
select FirstName as '#FirstName', Company as '#Company' from dbo.company where Location = #InputLocation
End
Are there any suggestions how I can do that? If you need some additional informations just let me know. Thanks.
/edit:
My sample Code (without using the Input Parameter in the first step, just for generating Output to see if it works):
create or replace
PROCEDURE TEST_PROZEDUR1 (
Input_Location IN Varchar2,
First_Name OUT SYS_Refcursor,
Company OUT Sys_Refcursor) IS
BEGIN
open First_Name For Select FirstName from dbo.company;
open Company For Select Company from dbo.company;
END TEST_PROZEDUR1;
The programming models used for PL/SQL and TSQL are different. Where you might return a recordset in TSQL, in PL/SQL you would return a cursor. A cursor is just a pointer to an SQL statement which is opened and can be read. It is not limited to returning a single column. Roughly, the PL/SQL equivalent of your TSQL procedure above would be something like:
CREATE OR REPLACE FUNCTION GET_INPUT_LOCATION(pinInput_location IN VARCHAR2(255))
RETURN SYS_REFCURSOR
IS
cCursor SYS_REFCURSOR;
BEGIN
OPEN cCursor FOR
SELECT FIRSTNAME,
COMPANY
FROM COMPANY
WHERE LOCATION = pinInput_location;
RETURN cCursor;
END GET_INPUT_LOCATION;
The caller would then invoke this function as:
DECLARE
cCursor SYS_REFCURSOR;
strFirstname COMPANY.FIRSTNAME%TYPE;
strCompany COMPANY.COMPANY%TYPE;
BEGIN
cCursor := GET_INPUT_LOCATION('SOMEWHERE OVER THE RAINBOW, INC.');
FETCH cCursor
INTO strFirstname,
strCompany;
CLOSE cCursor;
END;
However, I probably wouldn't code it this way. If COMPANY.LOCATION is unique then you're going to a lot of trouble to return a cursor which the caller will need to remember to close when they're done with it, which they may forget to do. Instead, I'd just return the FIRSTNAME and COMPANY fields using output parameters; e.g.
CREATE OR REPLACE PROCEDURE GET_INPUT_LOCATION
(pinInput_location IN VARCHAR2(255),
poutFirst_name OUT COMPANY.FIRSTNAME%TYPE,
poutCompany OUT COMPANY.COMPANY%TYPE)
IS
cCursor SYS_REFCURSOR;
BEGIN
SELECT FIRSTNAME,
COMPANY
INTO poutFirst_name,
poutCompany
FROM COMPANY
WHERE LOCATION = pinInput_location;
END GET_INPUT_LOCATION;
Share and enjoy.
I am having sample Procedure as Below
CREATE OR REPLACE PROCEDURE proc_Table1
BEGIN
SELECT 'Sample UserName' AS UserName
FROM Dual;
END;
Now I want to run this Proc in PLSQL developer.I tried the below but its generating error
begin
proc_Table1;
end;
Its Displaying
Thanks for the Help.
Any Idea why this Happens.
When you created the procedure, you should have been alerted to the fact that you had syntax errors. If you're going to run a SELECT statement, you need to do something with the results-- either populate a local variable or open a cursor or something else. The code you've posted is also missing the IS/AS keyword
CREATE OR REPLACE PROCEDURE proc_Table1
AS
l_username VARCHAR2(30);
BEGIN
SELECT 'Sample UserName' AS UserName
INTO l_username
FROM Dual;
END;
will be syntactically valid. It doesn't appear, however, to be particularly useful-- you procedure isn't modifying the database and has no way to communicate with the caller so it isn't doing anything meaningful. As a general principal, you would also generally want to use a simple PL/SQL assignment operator to populate a local variable rather than selecting from dual, i.e.
l_username := 'Sample UserName';
Try this, it should work:
CREATE OR REPLACE PROCEDURE proc_Table1(UserName OUT VARCHAR2)
AS
BEGIN
SELECT 'Sample UserName' INTO UserName
FROM Dual;
dbms_output.put_line(UserName);
END PROC_TABLE1;
-------------------------------
How to Execute
-------------------------------
declare
name varchar2(50);
result varchar2(100);
begin
proc_table1(name);
end;
I have a defined a new stored procedure but get a error while calling it,
CREATE OR REPLACE PROCEDURE SCOTT.getempsal(
p_emp_id IN NUMBER,
p_emp_month IN CHAR,
p_emp_sal OUT INTEGER)
AS
BEGIN
SELECT EMP_SAL
INTO p_emp_sal
FROM EMPLOYEE_SAL
WHERE EMP_ID = p_emp_id
AND EMP_MONTH = p_emp_month;
END getempsal;
And trying to call it:
getempsal(1,'JAN',OUT) --Invalid sql statement.
Your procedure contains an out parameter, so you need to call it in block like:
declare
a number;
begin
getempsal(1,'JAN',a);
dbms_output.put_line(a);
end;
A simple procedure (let's say with a number parameter) can be called with
exec proc(1);
or
begin
proc(1);
end;
Just write EXECUTE procedure_name('provide_the_valueof_IN parameter','value of in parameter', :k) ;
Run this statement a popup will come set the parameters as in out and the datatype too. U will see the output in another popup window.
I have a stored procedure which returns a ref cursor as follows:
CREATE OR REPLACE PROCEDURE AIRS.GET_LAB_REPORT (ReportCurTyp OUT sys_refcursor)
AS
v_report_cursor sys_refcursor;
report_record v_lab_report%ROWTYPE;
l_sql VARCHAR2 (2000);
BEGIN
l_sql := 'SELECT * FROM V_LAB_REPORT';
OPEN v_report_cursor FOR l_sql;
LOOP
FETCH v_report_cursor INTO report_record;
EXIT WHEN v_report_cursor%NOTFOUND;
END LOOP;
CLOSE v_report_cursor;
END;
I want to use the output from this stored procedure in another select statement like:
SELECT * FROM GET_LAB_REPORT()
but I can't seem to get my head around the syntax.
Any ideas?
Whenever I've had to do this; I've used the Oracle TYPE and CAST features.
Something like:
SELECT *
FROM TABLE(CAST(F$get_Cassette_Tracking('8029241') AS cass_tracking_tab_type))
You need to setup the TYPE and all the columns you need and have them use:
pipe ROW(out_obj)
to capture your data. There are many ways to do this and if I can dig out a better example I will but this might give you an idea.
See this SO for a working example: Oracle Parameters with IN statement?