I need to write a reference cursor in Oracle SQL developer and I have no clue how its written. I just know basic queries.
I have written following cursor to best of my knowledge after looking up into various example. I am getting an compile error "Missing or Invalid option".
Can anyone help me out?
Step 1: I created a new procedure in Oracle sql developer version 4.
Step 2: I wrote the following cursor
DECLARE
routeid VARCHAR2(10);
cursor c1 IS
SELECT shipment_id FROM SHIPMENT
WHERE shipment_id = 20;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO routeid;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(routeid);
END LOOP;
END;
/
Thank you in advance for the help.
Better way to do simple cursor
CREATE OR REPLACE PROCEDURE Test_cursor (Out_Pid OUT VARCHAR2) AS
cursor c1 IS
SELECT shipment_id,p_id FROM test
WHERE shipment_id = 99;
c1_rec c1%rowtype;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO c1_rec;
EXIT WHEN c1%NOTFOUND;
Out_Pid := c1_rec.p_id;
DBMS_OUTPUT.PUT_LINE('Result from query '||c1_rec.p_id );
DBMS_OUTPUT.PUT_LINE('Result from out parameter '||Out_Pid );
END LOOP;
END Test_cursor;
While executing a simple stored procedure getting a warning compiled but compilation error how to see.
Below is the query:
create procedure spgetdat
as
begin
select empis empname, empadd from tb1employees;
end;
While executing above query getting an error. Pls suggest what needs to be corrected.
Regards
Jitendra
Your Select statement inside the procedure is not correct. There should be into clause in the select statement inside the PL/SQL block.
It can be like below. You have to put a where condition for selection of one record or for best practice you can use cursor to fetch more then one record also.
create procedure spgetdat
as
v_empis tab1employees.empis%type;
v_empadd tab1employees.empadd%type;
begin
select empis empname ,empadd into v_empis,v_empadd from tb1employees where empis = 'given name' ;
end;
show errors;
In this link IBM they explain how to use an Oracle stored procedure with COGNOS.
They are doing :
create or replace package body project_pk as
procedure project_sp (tproj IN numeric, result1 in out project_type1) is
begin
open result1 for
select projects.projectid, projects.projecttype
from projects
where projects.projecttype=tproj;
end;
end;
/
With open result1 for they are opening the cursor explicitly. But, they do not seem to close it. Why is this?
You must return resuly set to Cognos. If you close the cursor then there are nor reuslts, right?
It's Cognos responsibility to close the cursor, once it finishes to pull the data from the SP.
In order to make you 100% sure that this is the case look at this link (totaly unrelated to Cognos):
Returning result Sets from SQL Server and Oracle
However, the sample you gave in your link, looks quite complex. Here is what I am using:
CREATE OR REPLACE PROCEDURE "COGNOS_SP" (
case_id in numeric,
po_refcur out sys_refcursor) is
BEGIN
open po_refcur for
select * FROM CASES WHERE CASE_ID = case_id;
END COGNOS_SP;
I am working on Delphi application which deals with stored procedures.I created stored procedure for insert statement and it works fine for my application.
Now,I wanted to create the same for select statement.
CREATE TYPE list_all_firstname AS ( first_name character varying);
CREATE FUNCTION select_sp()
RETURNS SETOF list_all_firstname AS
$$
DECLARE
rec record;
BEGIN
FOR rec IN (SELECT first_name FROM person) LOOP
RETURN NEXT rec;
END LOOP;
END;
$$ LANGUAGE plpgsql;
The call is:
SELECT * FROM select_sp();
Till this everything is fine in postgres.I wanted to access this stored procedure in my delphi application.
My code is:
with StoredProc2 do begin
StoredProcName :='select_sp';
ExecProc;
Edit5.Text:=ParamByName('list_all_firstname').AsString ;
end;
But i gets the error saying "Could not find object".How do i access return values of stored procedure in delphi??
I got the answer..could not find object is BDE error...
Next thing is accessing values,no need to use stored procedure component.We can use TQuery as below...:
Query1.SQL.Clear;
Query1.SQL.Add('SELECT * FROM select_sp()');
Query1.Active := True;
for i:=0 to Query1.RowsAffected-1 do
begin
sval:=Query1.FieldByName('first_name').AsString;
ShowMessage(sval);
Query1.Next;
end;
I have a firebird 2.x database with Generator and a trigger to generate the key field.
I need to get the returned value from below query.
INSERT INTO XXXX (vdate,description) values ('"+ VDate +"','"+ Description +"') returning vno INTO :ParamVoucherNo
I tried several versions of below code but it dont wrok and I get
Dynamic sql error sql error code = -104
Is it really possible to get the return value in delphi using TIBQuery ?
Query1->SQL->Clear();
Query1->SQL->Add("INSERT INTO XXXX (vodate,description) values ('"+ VDate +"','"+ Description +"') returning vno INTO :ParamVoucherNo");
Query1->Params->ParamByName("ParamVoucherno")->ParamType = ptResult;
Query1->Params->ParamByName("ParamVoucherno")->DataType = ftInteger;
Query1->Params->ParamByName("ParamVoucherno")->Value = "";
Query1->Prepare();
Query1->ExecSQL();
Any suggestions?
From Firebird README.returning:
The INTO part (i.e. the variable list) is allowed in PSQL only (to
assign local variables) and rejected in DSQL.
As IBX uses DSQL, you should exclude INTO part from your query.
INSERT ... RETURNING for DSQL looks the same as a call of a stored procedure, which returns result set. So, you have to use Open instead of ExecSQL.
Your mixing of dynamic SQL with parameters is just confusing.
Do this instead:
Query1->SQL->Clear();
Query1->SQL->Add("INSERT INTO table1 (vodate,description) VALUES"+
"(:VoDate,:Description) RETURNING vno INTO :VoucherNo ");
Query1->Params->ParamByName("VoDate")->Value = VDate;
Query1->Params->ParamByName("description")->Value = Description;
Query1->Prepare();
Query1->ExecSQL();
VoucherNo = Query1->Params->ParamByName("VoucherNo")->AsInteger;
Using Delphi 6 I have the ID returning successfully using an EXECUTE BLOCK statement:
EXECUTE BLOCK
RETURNS ( DeptKey INT )
AS
BEGIN
INSERT INTO DEPARTMENT
( COMPANY_KEY, DEPARTMENT_NAME )
VALUES ( 1, 'TEST1' ) RETURNING DEPARTMENT_KEY INTO :DeptKey;
SUSPEND;
END;
From Delphi you can do the folliowing:
FQuery.SQL.Text := '<Execute Block Statement>';
FQuery.Open();
ANewKey := FQuery.Fields[0].AsInteger;
IBX is not Firebird ready
you can take a look at FIBPLUS who support Firebird features
FIBPlus also supports FB2.0 insert ... into ... returning. Now you
should not bother about getting generator values from the client but
leave them in the trigger. You can also use RDB$DB_KEY. New possible
variants of work with insert returning and RDB$DB_KEY are shown in the
example “FB2InsertReturning”.
Why not get the next value for VoucherNo first, followed by
"INSERT INTO table1 (vno, vodate,description) VALUES (:VoucherNo,:VoDate,:Description)");
?
Your trigger can then either be dispensed with (which is nice), or modified to detect null (or <= zero can be useful too) and only then populate the vno field.
create trigger bi_mytable
active before insert position 1
on mytable
as
begin
if (new.vno is null)
then new.vno = next value for gen_VoucherNos;
end
Client-side you can :
select gen_id(gen_VoucherNos, 1) from rdb$database;
By modifying the trigger in this manner you save yourself a headache later on if/when you want to insert blocks of records
I wonder if that INSERT can be wrapped into EXECUTE BLOCK command.
Would IBX manage EXECUTE BLOCK then?
http://www.firebirdsql.org/refdocs/langrefupd20-execblock.html
http://firebirdsql.su/doku.php?id=execute_block
Hope to try it in both IBX and Unified Interbase in XE2
PS: Even if it does not, I found the library, that tells to work on top of IBX of Delphi XE2 (both x86 and x64) and to add EXECUTE BLOCK support: http://www.loginovprojects.ru/index.php?page=ibxfbutils#eb.
As I know there should be some changes to IBX made. Internally INSERT ... RETURNING should be treated the same way as a selectable procedure with returning parameters.
i know this question was answered a long time ago, but i must write this as clear as possible, for those who need this as i was.
i too, needed the "INSERT..RETURNING" thing.
the Delphi drove me crazy for a long time, until i changed my Data access components.
i even moved from Delphi XE2, to XE5 only because of that...
conclusion : IBX does NOT support RETURNING!
FireDAC is PERFECT for what i need with Firebird.
just move to FireDAC and you'll be able to do everything you need, and with high performance.
If you have a table with this 2 Fields: GRP_NO and GROUPNAME and you want to get the new GRP_NO you have to use RET_ as prefix, see example:
procedure TFormDatenbank.Button1Click(Sender: TObject);
var
q: Uni.TUniQuery;
ID: Integer;
GroupName: String;
begin
GroupName := 'MyGroupName';
q := TUniQuery.Create(nil);
try
q.Connection := Datenmodul.UniConnection;
q.ParamCheck := true; // the default value of ParamCheck is true.
q.SQL.Clear;
q.SQL.Add('SELECT GRP_NO, GROUPNAME FROM GROUPDATA WHERE GROUPNAME = :GROUPNAME');
q.ParamByName('GROUPNAME').AsString := GroupName;
q.Open;
if q.RecordCount > 0 then
ID := q.FieldByName('GRP_NO').AsInteger
else
begin
// there exist no group with this name, so insert this new name
q.SQL.Clear;
q.SQL.Add('INSERT INTO GROUPDATA');
q.SQL.Add('(GROUPNAME)');
q.SQL.Add('VALUES');
q.SQL.Add('(:GROUPNAME)');
q.SQL.Add('RETURNING GRP_NO;');
q.ParamByName('GROUPNAME').AsString := GroupName;
q.Execute;
ID := q.ParamByName('RET_GRP_NO').AsInteger;
end;
finally
q.Free;
end;
end;
From the IBx2 sources, you can do it like this:
//Uses IBSql;
//var Cur: IResults;
IBSQL1.SQL.Text := 'delete from tbl_document where id = 120 returning id;';
IBSQL1.Prepare;
if IBSQL1.Prepared then
begin
Cur := IBSQL1.Statement.Execute(IBTransaction1.TransactionIntf);
WriteLn(Cur.Data[cou].AsString);
Cur.GetTransaction.Commit(True);
end;
IResults interface Code:
IResults = interface
function getCount: integer;
function GetTransaction: ITransaction;
function ByName(Idx: String): ISQLData;
function getSQLData(index: integer): ISQLData;
procedure GetData(index: integer; var IsNull:boolean; var len: short; var data: PChar);
procedure SetRetainInterfaces(aValue: boolean);
property Data[index: integer]: ISQLData read getSQLData; default;
property Count: integer read getCount;
end;
Test enviroment:
Arch Linux X86
Firebird 3
Lazarus 1.9
FPC 3.0.4
Quick note: This works on new Firebird API in the IBX, But I didn't test it in Legacy Firebird API with the IBX.