i'm trying to CALL a very simple PLSQL function and i can't guess what i'm doing wrong:
CREATE OR REPLACE PACKAGE BODY KYC_OWN.KYCK_TEMP IS
FUNCTION PrintHelloWorld RETURN VARCHAR2 IS
BEGIN
RETURN 'Hello World';
END printHelloWorld;
END KYCK_TEMP;
Then i call the function like this:
call KYC_OWN.KYCK_TEMP.PrintHelloWorld() INTO :x;
I guess i need to declare the x variable somewhere, but how?
Thanks in advance
You can try this:
CREATE OR REPLACE PACKAGE BODY KYC_OWN.KYCK_TEMP IS
FUNCTION PrintHelloWorld RETURN VARCHAR2 IS
BEGIN
RETURN ('Hello World');
END printHelloWorld;
END KYCK_TEMP;
or create a variable like below and return g_helloworld
create or replace package constants as
g_helloworld constant varchar2(11) := 'Hello World';
function get_helloworld return varchar2;
end constants;
/
create or replace package body constants as
function get_helloworld return varchar2
is
begin
return g_helloworld;
end get_helloworld;
end constants;
/
If you're in SQL*Plus, you could create a variable and then use that to hold the function return variable, e.g.:
VARIABLE x varchar2(30)
call KYC_OWN.KYCK_TEMP.PrintHelloWorld() INTO :x;
print x
or you could simply use an anonymous block, along with dbms_output to display the number:
set serveroutput on -- assuming you're in SQL*Plus
declare
v_val varchar2(30);
begin
v_val := KYC_OWN.KYCK_TEMP.PrintHelloWorld;
dbms_output.put_line('return val = '||v_val);
end;
Related
I hope that you can advise me. I'm trying to use ADA 95's Object Oriented Features for the first time, and I want two derived classes, cyclicgroup and polyggroup, to call the put() method belonging to their base class,
abstractGroup. But instead of tracing up the class hierarchy as I expected, the compiler just tells me that I have a type mismatch in the call to put(). How do I tell the compiler to recognize the connection between the objects?
Here are the 5 files, with all the extraneous stuff removed, and the attempted compile:
grpdriver2.adb:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Command_Line; use Ada.Command_Line;
with groupstuff2;
with subgrphandler2;
procedure grpdriver2 is
cycg: groupStuff2.cyclicgroup;
polyg: groupStuff2.polygonGroup;
begin
cycg := groupstuff2.createCyclicGroup( 10);
subgrphandler2.put(cycg); -- line 13
------------------------------------------------------------------------------------------------------------------
polyg := groupstuff2.createPolygonGroup( 10);
subgrphandler2.put(polyg); -- line 18
end grpdriver2;
.................................................................................................................
groupstuff2.ads:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Command_Line; use Ada.Command_Line;
package groupstuff2 is
type abstractGroup is tagged record
x: integer;
end record;
type cyclicGroup is new abstractGroup with record
y: integer;
end record;
function createCyclicGroup( size: in integer) return cyclicGroup ;
----------------------------------------
type polygonGroup is new abstractGroup with record
null;
end record;
function createPolygonGroup( size: in integer) return polygonGroup ;
end groupstuff2;
.......................................................................................
groupstuff2.adb:
package body groupstuff2 is
procedure put( g: in abstractGroup) is
x: integer;
begin
x := 1;
end put;
function createCyclicGroup( size: in integer) return cyclicGroup is
cycg: cyclicGroup;
begin
cycg.x := size;
return cycg;
end createCyclicGroup;
function createPolygonGroup( size: in integer) return polygonGroup is
polyg: polygonGroup;
begin
polyg.x := size;
return polyg;
end createPolygonGroup;
end groupstuff2;
..............................................................................
subgrphandler2.ads:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Command_Line; use Ada.Command_Line;
with groupstuff2;
package subgrphandler2 is
procedure put( g: in groupStuff2.abstractGroup);
end subgrphandler2;
...........................................................................................
subgrphandler2.adb:
package body subgrphandler2 is
procedure put( g: in groupStuff2.AbstractGroup) is
begin
put("THIS IS A PUT STATMENT");
end put;
end subgrphandler2;
COMPILE ATTEMPT:
C:\GNAT\2018\bin\ceblang>gnatmake grpdriver2
gcc -c grpdriver2.adb
grpdriver2.adb:13:36: expected type "abstractGroup" defined at groupstuff2.ads:7
grpdriver2.adb:13:36: found type "cyclicGroup" defined at groupstuff2.ads:16
grpdriver2.adb:18:36: expected type "abstractGroup" defined at groupstuff2.ads:7
grpdriver2.adb:18:36: found type "polygonGroup" defined at groupstuff2.ads:25
gnatmake: "grpdriver2.adb" compilation error
I cannot compile Ada95 code as I'm using GNAT CE 2018 (which only supports Ada 2012), but it seems that you need to add the Class attribute to the type of the argument of put in subgrphandler2 to make it accept a class wide type (i.e. groupStuff2.AbstractGroup, and all of its extensions (inherited types)).
You also might want to make groupStuff2.AbstractGroup actually abstract by adding the abstract keyword to its definition (see below).
This (reformatted code) compiles on GNAT CE 2018 in Ada 2012 mode:
group_driver_2.adb
with Group_Stuff_2;
with Sub_Group_Handler_2;
procedure Group_Driver_2 is
Cycg : Group_Stuff_2.Cyclic_Group;
Polyg : Group_Stuff_2.Polygon_Group;
begin
Cycg := Group_Stuff_2.Create_Cyclic_Group (10);
Sub_Group_Handler_2.Put (Cycg);
Polyg := Group_Stuff_2.Create_Polygon_Group (10);
Sub_Group_Handler_2.Put (Polyg);
end Group_Driver_2;
group_stuff_2.ads
package Group_Stuff_2 is
type Abstract_Group is abstract tagged
record
X: Integer;
end record;
-- Cyclic_Group
type Cyclic_Group is new Abstract_Group with
record
Y: Integer;
end record;
function Create_Cyclic_Group
(Size: in Integer) return Cyclic_Group;
-- Polygon_Group
type Polygon_Group is new Abstract_Group with null record;
function Create_Polygon_Group
(Size: in Integer) return Polygon_Group ;
end Group_Stuff_2;
group_stuff_2.adb
package body Group_Stuff_2 is
-------------------------
-- Create_Cyclic_Group --
-------------------------
function Create_Cyclic_Group
(Size : in Integer) return Cyclic_Group
is
Cycg : Cyclic_Group;
begin
Cycg.X := Size;
return Cycg;
end Create_Cyclic_Group;
--------------------------
-- Create_Polygon_Group --
--------------------------
function Create_Polygon_Group
(Size : in Integer) return Polygon_Group
is
Polyg: Polygon_Group;
begin
Polyg.X := Size;
return Polyg;
end Create_Polygon_Group;
end Group_Stuff_2;
sub_group_handler_2.ads
with Group_Stuff_2;
package Sub_Group_Handler_2 is
procedure Put (G : in Group_Stuff_2.Abstract_Group'Class);
end Sub_Group_Handler_2;
sub_group_handler_2.adb
with Ada.Text_IO; use Ada.Text_IO;
package body Sub_Group_Handler_2 is
procedure Put (G: in Group_Stuff_2.Abstract_Group'Class) is
begin
Put_Line ("Value of X is" & Integer'Image (G.X));
end Put;
end Sub_Group_Handler_2;
I don't fully understand the purpose of procedures for PL/SQL object types. From reading online, the impression I got was that functions should not modify the data and should only return a value, instead procedures should be used, however it appears that for object types, changes in a procedure don't propagate outside the local context:
CREATE OR REPLACE TYPE TestType FORCE
AS OBJECT
(
TestValue NUMBER
, CONSTRUCTOR FUNCTION TestType
RETURN SELF AS RESULT
, MEMBER PROCEDURE IncrementValueAsProcedure
, MEMBER FUNCTION IncrementValueAsFunction
RETURN TestType
)
/
CREATE OR REPLACE TYPE BODY TestType
AS
CONSTRUCTOR FUNCTION TestType
RETURN SELF AS RESULT
IS
BEGIN
SELF.TestValue := 0;
RETURN;
END;
MEMBER PROCEDURE IncrementValueAsProcedure
IS
MyType TestType := SELF;
BEGIN
MyType.TestValue := TestValue + 1;
END;
MEMBER FUNCTION IncrementValueAsFunction
RETURN TestType
IS
MyType TestType := SELF;
BEGIN
MyType.TestValue := TestValue + 1;
RETURN MyType;
END;
END;
/
DECLARE
MyTest TestType;
BEGIN
MyTest := TestType();
DBMS_OUTPUT.PUT_LINE(MyTest.TestValue);
MyTest.IncrementValueAsProcedure();
DBMS_OUTPUT.PUT_LINE(MyTest.TestValue);
MyTest := MyTest.IncrementValueAsFunction();
DBMS_OUTPUT.PUT_LINE(MyTest.TestValue);
END;
This gives the output:
0
0
1
So the change in the update procedure hasn't been picked up. What am I doing wrong?
Oh, worked this out.
MEMBER PROCEDURE IncrementValueAsProcedure
IS
MyType TestType := SELF;
BEGIN
MyType.TestValue := TestValue + 1;
END;
This creates a copy of the current object and updates it. The following works as expected:
MEMBER PROCEDURE IncrementValueAsProcedure
IS
BEGIN
TestValue := TestValue + 1;
END;
I need help with functions in a package. The problem is that i got
two functions. The first function we can call it "function_a". The result from this function, how can I send it over in the function_b? What are the command to pass the result over to function_b?
The code is below:
CREATE OR REPLACE PACKAGE BODY test_PKG AS
FUNCTION F_a (F_h NUMBER, F_r NUMBER ) RETURN NUMBER
AS
V_PI NUMBER := 3.14;
V_BOTTEN NUMBER := F_r * F_r * V_PI;
V_VOLYM NUMBER;
BEGIN
V_VOLYM := F_h * V_BOTTEN;
RETURN V_VOLYM;
END F_a;
FUNCTION_B
.....
....
....
How can i get the result from v_volym in function_a to function_B?
Something like this:
CREATE OR REPLACE PACKAGE BODY test_PKG AS
FUNCTION F_a (F_h NUMBER, F_r NUMBER ) RETURN NUMBER
AS
V_PI NUMBER := 3.14;
V_BOTTEN NUMBER := F_r * F_r * V_PI;
V_VOLYM NUMBER;
BEGIN
V_VOLYM := F_h * V_BOTTEN;
RETURN V_VOLYM;
END F_a;
FUNCTION F_b RETURN NUMBER
AS
F_A_RESULT NUMBER;
BEGIN
F_A_RESULT := F_A(1,2);
RETURN F_A_RESULT;
END F_B;
PROCEDURE P_b (RESULT OUT NUMBER)
AS
BEGIN
RESULT := F_A(1,2);
END F_B;
....
Use Package variables. They will have scope across the package.
Lets say i have a package with three functions in it. then i create a stored procedure in PL/SQL. How can i call the package "test_pkg" from this procedure and represent the result from the functions?
here's how I'd do it.
CREATE OR REPLACE PACKAGE test_pack IS
FUNCTION foobar RETURN varchar2;
FUNCTION foo RETURN varchar2;
FUNCTION bar RETURN varchar2;
END test_pack;
CREATE OR REPLACE PACKAGE BODY test_pack IS
FUNCTION foobar RETURN varchar2 IS
BEGIN
return 'star';
END foobar;
FUNCTION foo RETURN varchar2 IS
BEGIN
return 'foo';
END foo;
FUNCTION bar RETURN varchar2 IS
BEGIN
return 'bar';
END bar;
END test_pack;
CREATE OR REPLACE PROCEDURE test_the_pack IS
BEGIN
DBMS_OUTPUT.PUT_LINE('foobar returns: ' || test_pack.foobar());
DBMS_OUTPUT.PUT_LINE('foo returns: ' || test_pack.foo());
DBMS_OUTPUT.PUT_LINE('bar returns: ' || test_pack.bar());
END test_the_pack;
trying to check whether the file I want to read exists or not.
Here are another approaches:
Using BFILE and fileexists function of dbms_lob package:
create or replace function FileExists(
p_DirName in varchar2, -- schema object name
p_FileName in varchar2
) return number
is
l_file_loc bfile;
begin
l_file_loc := bfilename(upper(p_DirName), p_FileName);
return dbms_lob.fileexists(l_file_loc); -- 1 exists; 0 - not exists
end;
Using fgetattr function of utl_file package:
create or replace function FileExists(
p_DirName in varchar2, -- schema object name
p_FileName in varchar2
) return number
is
l_fexists boolean;
l_flen number;
l_bsize number;
l_res number(1);
begin
l_res := 0;
utl_file.fgetattr(upper(p_DirName), p_FileName, l_fexists, l_flen, l_bsize);
if l_fexists
then
l_res := 1;
end if;
return l_res;
end;
Use UTL_FILE.FGETATTR function.
This function is designed specifically for this purpose.
Syntax:
UTL_FILE.FGETATTR(
location IN VARCHAR2,
filename IN VARCHAR2,
fexists OUT BOOLEAN,
file_length OUT NUMBER,
block_size OUT BINARY_INTEGER);
Example:
DECLARE
fexists BOOLEAN;
file_length NUMBER;
block_size BINARY_INTEGER;
BEGIN
UTL_FILE.FGETATTR('MY_ORA_DIRECTORY', 'my_file_name.csv', fexists, file_length, block_size);
IF fexists THEN
-- Do something
-- ...
END IF;
END IF;
Oracle documentation:
https://docs.oracle.com/database/121/ARPLS/u_file.htm#ARPLS70915
One more useful link:
https://www.foxinfotech.in/2018/09/how-to-check-if-file-exists-in-pl-sql.html
Creating a function that checks if a file exists is fairly easy by just trying to open it and catching any exceptions (this example function taken from AskTom)
CREATE OR REPLACE FUNCTION file_exists(p_fname IN VARCHAR2) RETURN BOOLEAN
AS
l_file UTL_FILE.FILE_TYPE;
BEGIN
l_file := UTL_FILE.FOPEN(SUBSTR( p_fname, 1, instr(p_fname,'/',-1) ),
SUBSTR( p_fname, instr( p_fname, '/', -1)+1 ), 'r' );
UTL_FILE.FCLOSE( l_file );
RETURN TRUE;
EXCEPTION
WHEN UTL_FILE.INVALID_PATH THEN RETURN FALSE;
WHEN UTL_FILE.INVALID_OPERATION THEN RETURN FALSE;
END;
/
Then you can just use;
IF ( file_exists( 'MED_LIST_19_OCT_12.csv' ) )
...