ORA-00984 column not allowed here - sql

I am getting error
"Execute-984 ORA-00984: column not allowed here"
while I am inserting values in my table Registred_Customer using Pro*C
Registred_Customer is defined as
CREATE TABLE Registred_Customer (
Cust_id NUMBER(6) PRIMARY KEY,
Name VARCHAR2(20) NOT NULL,
Age NUMBER,
Sex CHAR,
Addr VARCHAR2(50),
Contact NUMBER(10)
);
Inserting values using a pro*c method
addCustomer(i, name,age, gender, address,contectNo);
in Pro*C method I use following code to insert
EXEC SQL INSERT INTO REGISTRED_CUSTOMER VALUES
(cust_id, cust_name, age, sex, addr, contact);
here cust_name and addr are char *; and sex is char rest as int;
It reports error while using variable but works fine using direct values
like EXEC SQL INSERT INTO REGISTRED_CUSTOMER VALUES (10, 'Pankaj', 23, 'M', 'asdfs', 45875);
I tried changing few lines but in vain.
Thanks in advance.

Your Pro*C code is basically missing the colons (assuming that your formal parameters are called cust_id, cust_name, age etc.):
EXEC SQL INSERT INTO REGISTRED_CUSTOMER VALUES
(:cust_id, :cust_name, :age, :sex, :addr, :contact);
And it would be more robust to explicitly specify the columns name. Otherwise a change to the table schema can result in difficult to find bugs:
EXEC SQL INSERT INTO REGISTRED_CUSTOMER (Cust_Id, Name, Ag, Sex, Addr, Contact)
VALUES (:cust_id, :cust_name, :age, :sex, :addr, :contact);

If im seeing correct you are trying to insert into the columns, the columns??
"EXEC SQL INSERT INTO REGISTRED_CUSTOMER VALUES (cust_id, cust_name, age, sex, addr, contact);"??
it would be more helpful if you post your procedure complete.
Regards

As Mr. mentioned, you are trying to use the columns as input values. When you provide actual values it works. Are you perhaps meaning to use PL/SQL variables or the procedure arguments? In this case, whatever your procedure parameters are called is what you should put in the values section.
i.e if addCustomer looks like
PROCEDURE addCustomer (pId NUMBER, pName VARCHAR2, pAge NUMBER, pGender CHAR, pAddress VARCHAR2, pContact NUMBER)
Then you'd do something like
INSERT INTO registered_customer (cust_id, name, age, sex, addr, contact) VALUES (pId, pName, pAge, pGender, pAddress, pContact);
But if you are inserting into all columns you can leave out the column definition and just provide values

I also got this error message in a stored procedure doing an insert. I misspelled a parameter name in the values clause and the oracle interpreter saw the misspelled name as a column name and issued the 00984.

Related

Insert Data Into Table with Stored Procedure in Oracle SQL

I am working through a homework assignment and am stuck on a problem with stored procedures.
I have the following tables:
create table Restaurant(rID int, name varchar2(100), address varchar2(100), cuisine varchar2(100));
create table Reviewer(vID int, name varchar2(100));
create table Rating(rID int, vID int, stars int, ratingDate date);
For my stored procedure I need to create, I get an input of a restaurant name (unique), reviewer name(unique), star rating, and review date. I need to update the Rating table with the proper information, and add a new reviewer to the Review table if they have not previously existed in the table.
In order to start my stored procedure, I wanted to start with just creating a new table called newReview to get the inputs stored in a new table, before re-writting to update the existing tables.
Here is the newReview Table
CREATE TABLE newReview(
RestaurantName VARCHAR(100),
UserName VARCHAR(100),
Stars Int,
RatingDate Date
)
This is my AddNewReview procedure, which compiles with success:
CREATE OR REPLACE PROCEDURE AddNewReview(
RESTAURANTNAME IN VARCHAR2 (100)
, USERNAME IN VARCHAR2 (100)
, Stars IN NUMBER
, RATINGDATE IN DATE
) AS
BEGIN
INSERT INTO newReview VALUES (RestaurantName, UserName, Stars, RatingDate);
END AddNewReview;
;
However, when I run the stored procedure with inputs as such,
BEGIN
AddNewReview ('Rangoli', 'Sarah M.', 4, '2020-11-21');
END;
I get the following error:
Error starting at line : 20 in command -
BEGIN
AddNewReview ('Rangoli', 'Sarah M.', 4, '2020-11-21');
END;
Error report -
ORA-06550: line 2, column 5:
PLS-00905: object TOCONN22.ADDNEWREVIEW is invalid
ORA-06550: line 2, column 5:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I have tried defining the date input as DATE '2020-11-21' and also switching the single quote to double. Where am I going wrong, as this is the first stored procedure I am writing.
Try to change Stars data type from NUMBER to Int
AS:
CREATE OR REPLACE PROCEDURE AddNewReview(
RESTAURANTNAME IN VARCHAR2 (100)
, USERNAME IN VARCHAR2 (100)
, Stars IN NUMBER
, RATINGDATE IN DATE
) AS
BEGIN
INSERT INTO newReview VALUES (RestaurantName, UserName, Stars, RatingDate);
END AddNewReview;
;
to
CREATE OR REPLACE PROCEDURE AddNewReview(
RESTAURANTNAME IN VARCHAR2 (100)
, USERNAME IN VARCHAR2 (100)
, Stars IN Int
, RATINGDATE IN DATE
) AS
BEGIN
INSERT INTO newReview VALUES (RestaurantName, UserName, Stars, RatingDate);
END AddNewReview;
;
You need to look up the ids for the insertion:
CREATE OR REPLACE PROCEDURE AddNewReview (
in_RESTAURANTNAME IN VARCHAR2(100),
in_USERNAME IN VARCHAR2(100),
in_Stars IN NUMBER,
in_RATINGDATE IN DATE
) AS
BEGIN
INSERT INTO newReview (rid, vid, stars, RatingDate)
SELECT r.id, rr.id, in_stars, in_RatingDate
FROM restaurant r JOIN
reviewer rr
ON r.name = in_RestaurantName AND
rr.name = in_UserName
END AddNewReview;
This joins to the reference tables to get the ids you need. It will not insert the review if either name does not match. Your question doesn't specify what to do in that case, so that seems like reasonable behavior.
Note that the parameters are named so they don't conflict with column names. And this has listed all columns for the insert -- both are best practices.
Parameters are defined only by name and data type, they do not contain size specification. So your procedure needs:
create or replace procedure addnewreview(
restaurantname in varchar2
, username in varchar2
, stars in int
, ratingdate in date
...
You need to use To_Date function while calling the stored procedure, like below
BEGIN
AddNewReview ('Rangoli', 'Sarah M.', 4, TO_DATE('2020-11-21','YYYY-MM-DD'));
END;

SQL get user input and further use it

I've got this task of inserting a new record into table EMPLOYEES. I know how to do it by asking the user to type in a value, for instance:
INSERT INTO EMPLOYEES (first_name, last_name, email, hire_date, job_id)
VALUES ('&first_name', '&last_name', '&email' ,'&hire_date', 'SA_REP' );
However, I'd like not to ask the user about the email but rather insert it automatically by taking the first letter of the first_name input concatenated with the last_name of the person whose data is being added to the table. In order to do this, I think I have to store the inserted values temporarily or at least get some reference to the first_name and last_name. I tried searching online but really got nowhere. Could you provide me with the simplest solution to this task? I'm using Oracle SQL Developer.
You may wrap it inside a PL/SQL block to use appropriate variables with right datatypes. This will also ensure that values for date variable is entered correctly, in the right format expected.
DECLARE
v_first_name employees.first_name%type := '&first_name';
v_last_name employees.last_name%type := '&last_name';
v_hire_date employees.hire_date%type := TO_DATE('&hire_date_YYYYMMDD','YYYYMMDD');
BEGIN
INSERT INTO EMPLOYEES (first_name, last_name, email, hire_date, job_id)
VALUES (v_first_name, v_last_name,
substr(v_first_name,1,1)||'.'||v_last_name , v_hire_date, 'SA_REP' );
--first letter of the first_name with last name
END;
/
Result
Enter value for first_name: John
Enter value for last_name: Doe
Enter value for hire_date_YYYYMMDD: 20190521
..
..
PL/SQL procedure successfully completed.
You should be able to do this:
INSERT INTO EMPLOYEES (first_name, last_name, email, hire_date, job_id)
VALUES ('&first_name', '&last_name', '&first_name' || '.' || '&last_name' ,'&hire_date', 'SA_REP' );

PL/SQL how to skip execution of script if similar value if found in the Table?

I want to create an Oracle PL/SQL insert script. This is just one time insert statement, and if the script gets executed multiple times and if similar values are available in Table it should skip the execution.
Now if the script gets executed again, I want it to complete successfully. However, I do not want to enter duplicate data if the similar record is available in the table.
Here is my script:
Set SERVEROUTPUT ON
BEGIN
INSERT INTO TableA
(First,
Last,
Address,
City,
State,
Zip
)
VALUES
('Alex',
'Roark',
'25 El Camino Real',
'San Roman',
'CA',
'94008'
);
INSERT INTO TableA
(First,
Last,
Address,
City,
State,
Zip
)
VALUES
('William',
'Chan',
'3700 Baltimore Ave',
'Detroit',
'MI',
'21003'
);
INSERT INTO TableA
(First,
Last,
Address,
City,
State,
Zip
)
VALUES
('Petty',
'Garg',
'1980 Fernando Ct',
'Austin',
'TX',
'85002'
);
INSERT INTO TableA
(First,
Last,
Address,
City,
State,
Zip
)
VALUES
('Thomas',
'Gregory',
'56 E Washington Blvd',
'Philadelphia',
'PA',
'19803'
);
DBMS_OUTPUT.PUT_LINE('Insert Completed Successfully');
COMMIT;
EXCEPTION
WHEN dup_val_on_index
THEN ROLLBACK;
END;
/
Set serveroutput off;
your question is not understandable as the code you are providing will not work in such case.
In your code, as soon as you get exception your whole process will go to end and rest of the insert statements will be left without process.
You Should follow some steps here -
1) Create PK or Unique key on the table so that you can differentiate between rows on some basis.
2) While inserting any value, do check on that column value if the value you are going to insert already exists in the table or not and then proceed.
Try to change using steps above. Please Share if you feel any problem then.

Oracle SQL insert query - into parent and child tables

for an assignment I had something similar to the following (simplified for brevity):
STUDENT(StudentID, Fname. Lname) StudentID PK
UNIT(UnitID, UnitName) UnitID PK
STUDENT_UNIT((StudentID, UnitID) StudentID PK/FK UnitID PK/FK
Needed to insert info about a student and the units that he/she had completed.
As it is only beginner level SQL the following was accepted
INSERT INTO STUDENT
VALUES(seqStudID.NextVal, 'Bob', 'Brown');
INSERT INTO STUDENT_UNIT(seqStudID.CurrVal, 111);
INSERT INTO STUDENT_UNIT(seqStudID.CurrVal, 222);
INSERT INTO STUDENT_UNIT(seqStudID.CurrVal, 333);
But I was wondering what would be the real way to enter this data, would it be a procedure with a loop? If so what sort of loop (so that it could handle any amount of units).
Thanks in advance
One of the best approach to do this is by using stored procedure. The below procedure will do everything for you.
CREATE OR REPLACE
PROCEDURE set_stud_unit(
i_fname IN VARCHAR2,
i_lname IN VARCHAR2,
i_unitid IN VARCHAR2)
IS
l_studentid student.studentid%TYPE;
BEGIN
INSERT INTO student(studentid, fname, lname)
VALUES(seqstudid.NEXTVAL, i_fname, i_lname)
RETURNING studentid INTO l_studentid;
INSERT INTO student_unit (studentid, unitid)
(SELECT l_studentid, (COLUMN_VALUE).getNumberVal() vid FROM xmltable(i_unitid));
COMMIT;
END;
/
You can pass the unitid as comma separated as below,
EXECUTE set_stud_unit('Bob', 'Brown', '111,222,333');
you can use select in your insert:
INSERT INTO STUDENT_UNIT select t1.StudentID ,t2.UnitID from STUDENT t1 ,UNIT t2;
and you can use where to limit this selection ;-)
Probably what you need is a procedure that accept:
First Name
Last Name
an array of Units
The procedure will:
Insert into STUDENT (I suggest you to use a trigger to populate StudentID, maybe you are already doing it),
Loop over the array and insert into STUDENT_UNIT each of the element of the array and the StudentID for First Name and Last Name, but without using the sequence. My pseudo code:
FOR i IN 1..input_array.count LOOP
INSERT INTO STUDENT_UNIT
SELECT StudentID, input_array(i)
FROM STUDENT
WHERE Fname = FirstNameParam
AND Lname = LastNameParam;
END LOOP;
I suggest you to query the student table to get the actual ID to avoid problems in case of concurrency. An optimization would be to query the STUDENT table only once and save the StudentID in a variable.
You can find more info about passing an array to an Oracle procedure here:
Passing an array of data as an input parameter to an Oracle procedure

SQL Stored Procedure did not insert result

I have created below stored procedure under a package (retrieve_user) in the SQL database to retrieve information from another table to insert it into the global temp table (global_temp_tableB).
procedure Load_BTable (NumID IN NUMBER) AS
begin
insert into global_temp_tableB (name, age, address, country, year)
select name, age, address, country, year
from table(prepare_tableB.find_User(NumID));
commit;
end Load_LFTable;
But when I tried to test and call the procedure from a SQL window using:
begin
retrieve_user.Load_BTable(numid => 739);
end;
the global_temp_tableB is still empty but when I use the actual INSERT statement instead of calling stored procedure:
begin
insert into global_temp_tableB (name, age, address, country, year)
select name, age, address, country, year
from table(prepare_tableB.find_User(739));
end;
it can return me with the result desired. So I believe that the INSERT statement in the stored procedure is working.
But why it is that when I call the stored procedure, it does not return me with the desired result?
Thank you very much for all your time and attention.
IF OBJECT_ID(N'Load_BTable',N'P') IS NOT NULL
DROP PROCEDURE Load_BTable
GO
CREATE PROCEDURE Load_BTable
(
#NumID INT
)
WITH ENCRYPTION
AS
BEGIN
SET NOCOUNT ON
insert into global_temp_tableB (name, age, address, country, year)
select name, age, address, country, year
from prepare_tableB WHERE NumId=>#NumID
SET NOCOUNT OFF
END
GO
and try this
exec Load_BTable 739