CREATE OR REPLACE PACKAGE Learning_package AS
PROCEDURE add_person(name_person people.C_Name%type,
mail_person people.C_mail%type,
age_person people.C_age%TYPE);
END Learning_package;
CREATE OR REPLACE PACKAGE BODY Learning_package AS
PROCEDURE add_person(name_person people.C_Name%type,
mail_person people.C_mail%type,
age_person people.C_age%TYPE)
IS
BEGIN
INSERT INTO people (C_Name, C_mail, C_age)
VALUES (name_person, mail_person, age_person);
END add_person;
END Learning_package;
/
BEGIN
Learning_package.add_person('john', 'fffff#all.com', 20);
END;
an error appears:
package body "Learning_package" has erros PL/SQL: could not find
program unit being called "Learning_package" at line 3
Can someone help me?
Your code is fine except that you need to:
Make sure that you have a people table with the expected columns; and
Use a / statement terminator in a new line at the end of every PL/SQL statement.
Like this:
CREATE OR REPLACE PACKAGE Learning_package AS
PROCEDURE add_person(name_person people.C_Name%type,
mail_person people.C_mail%type,
age_person people.C_age%TYPE);
END Learning_package;
/
CREATE OR REPLACE PACKAGE BODY Learning_package AS
PROCEDURE add_person(name_person people.C_Name%type,
mail_person people.C_mail%type,
age_person people.C_age%TYPE)
IS
BEGIN
INSERT INTO people (C_Name, C_mail, C_age)
VALUES (name_person, mail_person, age_person);
END add_person;
END Learning_package;
/
BEGIN
Learning_package.add_person('john', 'fffff#all.com', 20);
END;
/
Note: Age is not a good thing to store as it quickly becomes out-of-date. Instead, you should store date-of-birth and when you need an age you can calculate it from the date-of-birth and today's date.
db<>fiddle here
Could you also add a block terminator after the package creation and change the AS to IS (/).
CREATE OR REPLACE PACKAGE Learning_package IS
END Learning_package;
/
Same goes for the package body.
Related
I'm writing a PL/SQL program, I've created a procedure and the syntax is correct.
Running this on DataGrip.
`
declare
create or replace procedure salutation(x OUT number) is begin
x:= x*10;
end salutation;
begin
SYS.DBMS_OUTPUT.PUT_LINE('hello');
end;
`
I get error messages when I execute the code:
BEGIN expected, got 'create'.
[2022-12-04 23:58:09] [65000][6550]
[2022-12-04 23:58:09] ORA-06550: line 1, column 7:
[2022-12-04 23:58:09] PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
[2022-12-04 23:58:09] begin function pragma procedure subtype type
[2022-12-04 23:58:09] current cursor delete
[2022-12-04 23:58:09] exists prior
I don't think there's a problem with the syntax.
Also why does the DataGrip not allow DBMS_OUTPUT.PUT_LINE without the SYS. ? even though I've enabled the DBMSOUTPUT.
You can't have static DDL statements (like create procedure) within PL/SQL (you'd need to use dynamic SQL, but it's very rarely necessary anyway).
But if you're trying to declare a local procedure within your anonymous block - not create a permanent, stored procedure, then you don't need the create part:
declare
y number := 42;
procedure salutation(x IN OUT number) is begin
x:= x*10;
end salutation;
begin
SYS.DBMS_OUTPUT.PUT_LINE('hello');
-- call salutation here if you want...
salutation(y);
dbms_output.put_line(to_char(y));
end;
/
1 rows affected
dbms_output:
hello
420
fiddle
Note that I changed the argument to IN OUT - otherwise it would always be reset to null.
If you want to create a permanent stored procedure then do that separately, before you try to run your anonymous block:
create or replace procedure salutation(x IN OUT number) is begin
x:= x*10;
end salutation;
/
declare
y number := 42;
begin
SYS.DBMS_OUTPUT.PUT_LINE('hello');
-- call salutation here if you want...
salutation(y);
dbms_output.put_line(to_char(y));
end;
/
1 rows affected
dbms_output:
hello
420
fiddle
Also why does the DataGrip not allow DBMS_OUTPUT.PUT_LINE without the SYS. ?
That suggests your database is missing a public synonym for the package; not a DataGrip thing, you'd see the same behaviour using any client. You'd need to ask your DBA why it's missing and whether it can be reinstated. (I haven't included the schema prefix in the extra calls I added, but if those don't work for you then you'll need to add it.)
I have got an SQL script stored in an .sql-file containing several statements like this:
create or replace package <schema>.custom_package is
procedure getReleaseEmployees(p_Cursor in out sys_refcursor, p_Role in string);
end custom_package;
/
create or replace package <schema>.pck_account_monitoring is
procedure checkAndLockOracleAccount;
end pck_account_monitoring;
/
<...some more packages following>
Running the script in an SqlDeveloper or PL/SQLDeveloper against my database works fine.
Now, when I'm trying to migrate via Flyway using the Java API, I'll get the following error message and Flyway's migration fails:
SQL State : 42000
Error Code : 900
Message : ORA-00900: Invalid SQL Statement
Location : migrations/sql/V0_2__migration.sql
Line : 6172
Statement : end pck_account_monitoring
at org.flywaydb.core.internal.dbsupport.SqlScript.execute(SqlScript.java:117)
at org.flywaydb.core.internal.resolver.sql.SqlMigrationExecutor.execute(SqlMigrationExecutor.java:71)
at org.flywaydb.core.internal.command.DbMigrate.doMigrate(DbMigrate.java:352)
If I try to put the first statement into a single line, i.e.
create or replace package quattro.custom_package is procedure getReleaseEmployees(p_Cursor in out sys_refcursor, p_Role in string); end custom_package;
/
<rest as before>
I'll get the same error message, but the parser now complains about the '/' symbol and the beginning of the next statement:
Error Code : 900
Message : ORA-00900: Invalid SQL Statement
...
Line : 6167
Statement : /
create or replace package quattro.pck_account_monitoring is ...
Now, if I remove that first '/' as well, the migration will run (with warnings, though).
My schema will then correctly have compiled all the other packages except for the first one - even though every other package declaration is formatted like the first one was in my initial attempt! The first package (custom_package) however is still missing.
My Java class basically looks like the sample class from the Flyway homepage.
Does anyone have any idea what's going wrong here with the Flyway parser or can maybe provide me with a workaround?
(This is too long for a comment, therefore, I'm posting it as an answer)
FWIW, I cannot reproduce this (using the Flyway 3.2.1 command line tool); running this example script:
-- PACKAGES
create or replace package flyway_demo.custom_package is
procedure getReleaseEmployees(p_Cursor in out sys_refcursor, p_Role in string);
end custom_package;
/
create or replace package flyway_demo.pck_account_monitoring is
procedure checkAndLockOracleAccount;
end pck_account_monitoring;
/
create or replace package flyway_demo.logger
authid definer
as
-- TYPES
type rec_param is record(
name varchar2(255),
val varchar2(4000));
type tab_param is table of rec_param index by binary_integer;
g_off constant number := 0;
function is_number(p_str in varchar2)
return boolean;
end logger;
/
create or replace package body flyway_demo.pck_account_monitoring is
procedure checkAndLockOracleAccount is
begin
null;
end;
end pck_account_monitoring;
/
create or replace package body flyway_demo.custom_package is
procedure getReleaseEmployees(p_Cursor in out sys_refcursor, p_Role in string)
is
begin
open p_Cursor for select * from dual;
end;
end custom_package;
/
create or replace package body flyway_demo.logger
as
function is_number(p_str in varchar2) return boolean is
begin
return true;
end;
end logger;
/
works perfectly fine. Can you please try it with this script and post your findings?
I'm stuck with the passing Dates as an array parameters from the Oracle Apex page into package. Package contains one procedure with an array of type of dates. So what I want to do is to pass a simple dates into it from the Apex page, pl/sql block. Here is my code so far:
create or replace PACKAGE PK_NAME AS
TYPE DATES_ARRAY_TYPE IS VARRAY(100) OF DATE;
PROCEDURE PASS_DATES (
DATES DATES_ARRAY_TYPE
);
END PK_NAME;
create or replace PACKAGE BODY PK_NAME AS
PROCEDURE PASS_DATES (
DATES DATES_ARRAY_TYPE
) AS
BEGIN
for i in 1..DATES.count loop
HTP.P(DATES(i));
end loop;
END;
END PASS_DATES;
END PK_NAME;
Simple as that. And I call this procedure from the Apex page pl/sql block:
PK_NAME.PASS_DATES (
DATES => '15-JAN-15', '16-JAN-15', '17-JAN-15'
);
However, it doesn't work, every time I'm trying to save it, it gives me an error:
•ORA-06550: line 3, column 25: PLS-00312: a positional parameter association may not follow a named association ORA-06550: line 2, column 1: PL/SQL: Statement ignored
What is wrong with it or what have I missed ?
https://docs.oracle.com/cd/A97630_01/appdev.920/a96624/05_colls.htm
you must init constructor DATES_ARRAY_TYPE()
i think it must look like this
create TYPE DATES_ARRAY_TYPE IS VARRAY(100) OF DATE;
create or replace procedure test_case( p_dates DATES_ARRAY_TYPE) is
begin
dbms_output.put_line(p_dates(1));
end;
declare
a DATES_ARRAY_TYPE;
begin
a := DATES_ARRAY_TYPE(sysdate, sysdate + 1,to_date('1.01.2016','dd.mm.yyyy'));
test_case(a);
end;
also if you want to use TYPE in PACKAGE PK_NAME (not global) you must use object like PK_NAME.DATES_ARRAY_TYPE in your code.
ok, lets go in your case:
1. create package and body:
https://gyazo.com/789b875ce47852e859c395c2021f9cd4
create or replace PACKAGE PCK AS
-- your type in pck
TYPE DATES_ARRAY_TYPE IS VARRAY(100) OF DATE;
procedure test_case(p_dates DATES_ARRAY_TYPE);
END PCK;
create or replace PACKAGE body PCK AS
procedure test_case(p_dates DATES_ARRAY_TYPE) IS
BEGIN
--here just raise second element in array for DEMO
raise_application_error('-20000',p_dates(2) );
END;
END PCK;
2.create page and button and after submit process:
https://gyazo.com/755f6e089db0a6a8ea058567d2b3384b
declare
asd PCK.DATES_ARRAY_TYPE := PCK.DATES_ARRAY_TYPE('31-JUL-15', '01-AUG-15', '02-AUG-13', '03-AUG-13');
begin
pck.test_case(asd);
end;
after button that submit page i get this:
https://gyazo.com/b894fc6b9b6dd28964ba2e6548244bc8
I am using oracle 10g.
While Creating Package in oracle. I am getting this error SQL Statement Ignored.
My Package Specification is :
create or replace PACKAGE PACKAGE_CHECK AS
PROCEDURE USP_PASS_EXPIRE(SP_DAYS_COUNT OUT NUMBER, SP_LOGIN_NAME IN VARCHAR2);
END PACKAGE_CHECK;
and package body is:
create or replace PACKAGE BODY PACKAGE_CHECK AS
PROCEDURE USP_PASS_EXPIRE(SP_DAYS_COUNT OUT NUMBER, SP_LOGIN_NAME IN VARCHAR2) IS
BEGIN
SELECT (SYSDATE-"LastLogin")
FROM "ApplicationUser"
WHERE "LoginName"=SP_LOGIN_NAME
AND "IsActive"='Y'
AND "IsDeleted"='N' returning (SYSDATE-"LastLogin")
into SP_DAYS_COUNT;
END USP_PASS_EXPIRE;
END PACKAGE_CHECK;
Plaese help. I don't know where am I going wrong?
The reason is that you are using returning clause with SELECT, however it can be used only with DELETE, EXECUTE IMMEDIATE, INSERT, and UPDATE statements, see
docs.oracle.com/cd/B19306_01/appdev.102/b14261/returninginto_clause.htm
Try this:
CREATE OR REPLACE PACKAGE PACKAGE_CHECK
AS
PROCEDURE USP_PASS_EXPIRE(
SP_DAYS_COUNT OUT NUMBER,
SP_LOGIN_NAME IN VARCHAR2);
END PACKAGE_CHECK;
/
CREATE OR REPLACE PACKAGE BODY PACKAGE_CHECK
AS
PROCEDURE USP_PASS_EXPIRE(
SP_DAYS_COUNT OUT NUMBER,
SP_LOGIN_NAME IN VARCHAR2)
BEGIN
SELECT (SYSDATE-"LastLogin")
INTO SP_DAYS_COUNT
FROM "ApplicationUser"
WHERE "LoginName"=SP_LOGIN_NAME
AND "IsActive" ='Y'
AND "IsDeleted" ='N';
END USP_PASS_EXPIRE;
END PACKAGE_CHECK;
I am trying to lay the foundation for a package but am having trouble even getting started. I have successfully created a basic package spec and want to just test the package body but I'm having trouble getting it to compile. The spec code is:
CREATE OR REPLACE PACKAGE synchronize_my_data
AS
PROCEDURE synchronize_data(p_run_date IN date);
END synchronize_my_data;
and here is the package body code:
CREATE OR REPLACE PACKAGE BODY synchronize_my_data
IS
PROCEDURE synchronize_data(p_run_date IN date) IS
PROCEDURE process_deletes(p_run_date IN date) IS
BEGIN
dbms_output.put_line('Run Date: ' || to_char(p_run_date, 'MM/DD/YYYY'));
END process_deletes;
BEGIN
process_deletes(p_run_date);
END synchronize_data;
END synchronize_my_data;
I keep getting a compilation error but can't figure out what's wrong with the code. It seems like basic code, am I just missing something obvious?
That code seems to compile for me. What error are you getting?
SQL> CREATE OR REPLACE PACKAGE synchronize_my_data
2 AS
3 PROCEDURE synchronize_data(p_run_date IN date);
4 END synchronize_my_data;
5 /
Package created.
SQL> CREATE OR REPLACE PACKAGE BODY synchronize_my_data
2 IS
3 PROCEDURE synchronize_data(p_run_date IN date) IS
4 PROCEDURE process_deletes(p_run_date IN date) IS
5 BEGIN
6 dbms_output.put_line('Run Date: ' || to_char(p_run_date, 'MM/DD/YYYY'));
7 END process_deletes;
8 BEGIN
9 process_deletes(p_run_date);
10 END synchronize_data;
11
12 END synchronize_my_data;
13 /
Package body created.
From a general stylistic standpoint, it generally makes very little sense to define a procedure within another procedure in a package body. One of the benefits of using packages is that you can have both public and private procedures. You can create the process_deletes procedure as a private procedure simply by defining it in the body without defining it in the spec.
CREATE OR REPLACE PACKAGE BODY synchronize_my_data
IS
PROCEDURE process_deletes(p_run_date IN date)
IS
BEGIN
dbms_output.put_line('Run Date: ' || to_char(p_run_date, 'MM/DD/YYYY'));
END process_deletes;
PROCEDURE synchronize_data(p_run_date IN date)
IS
BEGIN
process_deletes(p_run_date);
END synchronize_data;
END synchronize_my_data;
That shouldn't have anything to do with whatever error you're getting. But it should make your code easier to deal with.