Question is : Function: Create a Function named 'find_credit_card' which takes card_no as input and returns the holder name of type varchar.
Function name: find_credit_card
Input Parameter: card_no with data type as varchar
Output variable : holder_name with data type as varchar(30)
Hint: Add '/' after the end statement
Refer to the schema.
My code :-
CREATE OR REPLACE FUNCTION find_credit_card(card_no IN VARCHAR2(255))
RETURN VARCHAR
IS
holder_name VARCHAR(255)
BEGIN
SELECT name
INTO holder_name
from credit_card
where card_number = card_no;
RETURN(holder_name);
END;
/
Warning : Function created with compilation errors.
Error(s) you got can be reviewed in SQL*Plus by running show err:
Warning: Function created with compilation errors.
SQL> show err
Errors for FUNCTION FIND_CREDIT_CARD:
LINE/COL ERROR
-------- -----------------------------------------------------------------
1/46 PLS-00103: Encountered the symbol "(" when expecting one of the
following:
:= . ) , # % default character
The symbol ":=" was substituted for "(" to continue.
5/1 PLS-00103: Encountered the symbol "BEGIN" when expecting one of
the following:
:= ; not null default character
SQL>
Alternatively, query user_errors:
select line, position, text
from user_errors
where name = 'FIND_CREDIT_CARD';
Oracle says that there are two errors:
first one means that function's parameter shouldn't have size, so - not card_no in varchar2(255) but only card_no in varchar2
another one means that you forgot to terminate line where local variable was declared (missing semi-colon at the end of that line):
holder_name VARCHAR(255);
However, consider inheriting datatype from column description. If it is ever changed, you wouldn't have to modify your code.
Furthermore, it would be good if you distinguish parameters and local variables from column names. How? Use prefixes, e.g. par_ for parameters, l_ or v_ for local variables.
Also, Oracle recommends us to use varchar2, not varchar.
Finally, that function might look like this:
SQL> CREATE OR REPLACE FUNCTION find_credit_card
2 (par_card_number IN credit_card.card_number%TYPE)
3 RETURN credit_card.name%type
4 IS
5 l_holder_name credit_card.name%TYPE;
6 BEGIN
7 SELECT name
8 INTO l_holder_name
9 FROM credit_card
10 WHERE card_number = par_card_number;
11
12 RETURN l_holder_name;
13 END;
14 /
Function created.
SQL> select find_credit_card('HR123456789') holder from dual;
HOLDER
---------------------------------------------------------------------
Littlefoot
SQL>
I tried to right a procedure to return a table.
that procedure should return a list with an employee info when emp_num parameter equal SSN otherwise return list with all employees info.
First I create a record as below:
CREATE OR REPLACE TYPE emp_record IS OBJECT(emp_lname VARCHAR2(30),
emp_ssn CHAR(9),
emp_sal NUMBER(6));
Then I create table of type emp_record as below:
CREATE OR REPLACE TYPE emp_table IS TABLE OF emp_record;
Then I create a procedure get_employee with two parameters:
CREATE OR REPLACE PROCEDURE get_employee(emp_num IN NUMBER , output_emp OUT emp_table) AS
CURSOR emp_cur IS
SELECT LNAME,SSN,SALARY
FROM EMPLOYEE
WHERE NVL((emp_num = SSN),(SSN = SSN));
BEGIN
IF NOT (emp_cur%ISOPEN) THEN
OPEN emp_cur;
END IF;
LOOP
FETCH emp_cur BULK COLLECT INTO output_emp;
EXIT WHEN output_emp.count=0;
CLOSE emp_cur;
END LOOP;
END;
And when I run that code the below error has appear:
[Warning] ORA-24344: success with compilation error
6/20 PL/SQL: ORA-00907: missing right parenthesis
4/1 PL/SQL: SQL Statement ignored
(1: 0): Warning: compiled but with compilation errors
You have used the alien code here, There is a syntax error:
WHERE
NVL(
(EMP_NUM = SSN),
(SSN = SSN)
);
NVL can take two columns/constants as an input parameter, not a boolean.
You want a WHERE condition - either EMP_NUM is full or if it is not null then it is equal to SSN then You need to use something like this:
WHERE
NVL(EMP_NUM,SSN) = SSN;
or better to use OR condition as follows:
WHERE EMP_NUM IS NULL OR EMP_NUM = SSN;
Please refer Oracle Documentation for NVL syntax. Based on similarity of syntax I feel you probably want to use DECODE instead. If so CASE is the way to go.
I am trying to process an array of string values (single column) called from C++ code, and iterate over it using PL/SQL in a stored procedure.
For that I have created a new type:
CREATE OR REPLACE TYPE "DEVICELIST_OBJTYP" AS OBJECT
(DEVICE VARCHAR2(46 BYTE))
/
CREATE OR REPLACE TYPE devicelist_coltyp AS
TABLE OF devicelist_objtyp;
/
The PL/SQL procedure looks as follows (with seemingly irrelevant logic removed):
PROCEDURE pr_MyProc
( p_UserId IN USERSTAB.USRID%TYPE,
p_DeviceList IN DEVICELIST_OBJTYP,
p_ResCode OUT NUMBER,
p_ResMsg OUT VARCHAR2)
IS
BEGIN
...
FOR i IN 1 .. p_DeviceList.COUNT LOOP
dbms_output.put_line(i);
--more code to follow..
END LOOP;
...
END;
/
When I try to compile the procedure, I fail with:
Warning: Package Body created with compilation errors.
Errors for PACKAGE BODY PA_HANDLE_ASSETS:
LINE/COL ERROR
-------- -----------------------------------------------------------------
135/17 PL/SQL: Statement ignored
135/44 PLS-00302: component 'COUNT' must be declared
BEGIN
*
ERROR at line 1:
ORA-20002:
ORA-06512: at line 4
How should I iterate over the nested table object without providing the .COUNT attribute? When I tried without the .COUNT, I errored out with something in the line of ~"p_DeviceList is not a cursor".
Should I convert the p_DeviceList object to another type of data?
I'm executing PL/SQL code to display the Currency Code from the Failed Reservation table. Object type and Nested Table collections are used.
When the PL/SQL code is run, the following error is generated. The corresponding line is highlighted in the PL/SQL code section.
Error report:
ORA-06550: line 27, column 11:
PL/SQL: ORA-00932: inconsistent datatypes: expected UDT got NUMBER
ORA-06550: line 27, column 4:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The code is pasted below:
DDL - Table creation:
CREATE TABLE FAILEDRESERVATION
(
FAILEDRESERVATIONID NUMBER(18,0),
FK_TRANSACTIONID NUMBER(18,0),
DEBITRESERVATIONID NUMBER(18,0),
RESERVATIONTIME DATE,
RESERVATIONAMOUNT NUMBER(18,5),
CURRENCYCODE CHAR(3 BYTE),
AVAILABLEAMOUNT NUMBER(18,5)
);
ALTER TABLE FAILEDRESERVATION
ADD CONSTRAINT "PK_FAILEDRESERVATION" PRIMARY KEY ("FAILEDRESERVATIONID");
Object Type:
CREATE OR REPLACE TYPE TYPE type_failedreservation AS OBJECT
(
FK_TRANSACTIONID NUMBER(18),
DEBITRESERVATIONID NUMBER(18),
RESERVATIONTIME DATE,
RESERVATIONAMOUNT NUMBER(18,5),
CURRENCYCODE CHAR(3),
AVAILABLEAMOUNT NUMBER(18,5)
);
DML:
INSERT INTO FAILEDRESERVATION (FAILEDRESERVATIONID,FK_TRANSACTIONID,DEBITRESERVATIONID,RESERVATIONTIME,RESERVATIONAMOUNT,CURRENCYCODE,AVAILABLEAMOUNT)
VALUES (289,2,1,to_date('07-MAR-16','DD-MON-RR'),20000,'USD',10000);
INSERT INTO FAILEDRESERVATION (FAILEDRESERVATIONID,FK_TRANSACTIONID,DEBITRESERVATIONID,RESERVATIONTIME,RESERVATIONAMOUNT,CURRENCYCODE,AVAILABLEAMOUNT)
VALUES (288,1,1,to_date('01-MAR-16','DD-MON-RR'),10000,'NOK',10000);
Nested Tables:
CREATE OR REPLACE TYPE type_failedreservation_coll as TABLE OF type_failedreservation;
CREATE OR REPLACE TYPE type_dbtrsid_coll AS TABLE OF NUMBER;
PL/SQL Code:
DECLARE
P_FAILEDRESERVATION APPDATA.TYPE_FAILEDRESERVATION_COLL;
vdbtid_coll type_dbtrsid_coll := type_dbtrsid_coll();
BEGIN
SELECT TYPE_FAILEDRESERVATION(fk_transactionid,debitreservationid,reservationtime,reservationamount,currencycode,availableamount)
BULK COLLECT
INTO p_failedreservation
FROM failedreservation;
-- This is line 27
SELECT frs.debitreservationid
INTO vdbtid_coll
FROM TABLE(p_failedreservation) frs;
FOR v_iterate IN vdbtid_coll.FIRST..vdbtid_coll.LAST
LOOP
dbms_output.put_line('The currency code is: '||v_iterate);
END LOOP;
END;
Why is the code generating this error ?
You've declared vdbtid_coll as a collection type, so you need to bulk collect into that too:
SELECT frs.debitreservationid
BULK COLLECT INTO vdbtid_coll
FROM TABLE(p_failedreservation) frs;
With that change:
PL/SQL procedure successfully completed.
The currency code is: 1
The currency code is: 2
That's just giving you the index number in the collection though, so I don't think it's what you really want. You may want:
FOR v_iterate IN vdbtid_coll.FIRST..vdbtid_coll.LAST
LOOP
dbms_output.put_line('The currency code is: '
|| p_failedreservation(v_iterate).currencycode);
END LOOP;
which gets:
PL/SQL procedure successfully completed.
The currency code is: USD
The currency code is: NOK
You don't really need the second select/collection at all though, you can do:
FOR v_iterate IN 1..p_failedreservation.COUNT
LOOP
dbms_output.put_line('The currency code is: '
|| p_failedreservation(v_iterate).currencycode);
END LOOP;
... for the same result. Although I'm not sure what the relevance of the debitreservationid is in that second query, as it is the same value (1) in both rows.
You are trying to select multiple rows into a collection. You need to use BULK COLLECT INTO rather than just INTO.
Change
SELECT frs.debitreservationid
INTO vdbtid_coll
FROM TABLE(p_failedreservation) frs;
To
SELECT frs.debitreservationid
BULK COLLECT INTO vdbtid_coll
FROM TABLE(p_failedreservation) frs;
and you probably want the output to be:
FOR v_iterate IN vdbtid_coll.FIRST..vdbtid_coll.LAST LOOP
dbms_output.put_line('The currency code is: '|| vdbtid_coll(v_iterate) );
END LOOP;
However, you could simplify it all to:
DECLARE
P_FAILEDRESERVATION APPDATA.TYPE_FAILEDRESERVATION_COLL;
BEGIN
SELECT TYPE_FAILEDRESERVATION(
fk_transactionid,
debitreservationid,
reservationtime,
reservationamount,
currencycode,
availableamount
)
BULK COLLECT INTO p_failedreservation
FROM failedreservation;
FOR v_iterate IN p_failedreservation.FIRST .. p_failedreservation.LAST LOOP
dbms_output.put_line(
'The currency code is: '|| p_failedreservation(v_iterate).currencycode
);
END LOOP;
END;
Try casting the type array to its type as follows
SELECT frs.debitreservationid
BULK COLLECT INTO vdbtid_coll
FROM TABLE(CAST(p_failedreservation as APPDATA.TYPE_FAILEDRESERVATION_COLL)) frs;
PL/SQL: ORA-00932: inconsistent datatypes: expected UDT got CHAR
You may get this error in case you write type table in place of type object when
using BULK COLLECT INTO, i faced this error coz i did so.
FOR EXAMPLE:
CREATE OR REPLACE TYPE OBJ_TYPE AS OBJECT (NAME VARCHAR2(20));
/
CREATE OR REPLACE TYPE TBL_TYPE IS TABLE OF OBJ_TYPE;
/
CREATE OR REPLACE FUNCTION FUNC1 RETURN TBL_TYPE AS
TBL_TEXT TBL_TYPE := TBL_TYPE();
BEGIN
SELECT ***OBJ_TYPE*** (NAME) BULK COLLECT INTO ***TBL_TEXT*** FROM <table-name> ;
RETURN ***TBL_TEXT***;
END;
/
Care should be taken when using object type and table type in the function.
I want to update the following procedure in the Oracle table, but it is throwing the error:
CREATE OR REPLACE PROCEDURE update_keywords (aKEYWORD IN VARCHAR2, aCOUNT IN NUMBER)
AS BEGIN
update searchable_keywords
set KEYWORD =:new.aKEYWORD or COUNT =:new.aCOUNT
where KEUWORD_ID = : old.KEYWORD_ID;
END;
This is my procedure. I want to update the keyword & count in the searchable_keywords table with keyword_id (primary key) but it is throwing an error as follows:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/4 PL/SQL: SQL Statement ignored
4/17 PLS-00049: bad bind variable 'NEW.AKEYWORD'
4/31 PL/SQL: ORA-00933: SQL command not properly ended
4/41 PLS-00049: bad bind variable 'NEW.ACOUNT'
Can you please help me solve this problem?
This looks like a trigger... You don't need the ":new" for acount/akeyword, and you need to pass in the ID you want update. Eg.
CREATE OR REPLACE
PROCEDURE UPDATE_KEYWORDS(
AKEYWORD IN VARCHAR2,
ACOUNT IN NUMBER,
AKEYWORD_ID IN NUMBER)
AS
BEGIN
UPDATE
SEARCHABLE_KEYWORDS
SET
KEYWORD = AKEYWORD
, "COUNT" = ACOUNT
WHERE
KEYWORD_ID = AKEYWORD_ID
END;
I'm not sure why you would have a column named "COUNT".. unless you are trying to do something different in that update, its obviously wrong with that "or" in there..