VARCHAR Leading 0's are lost when executing PLSQL procedures - oracle

I have a PL/SQL script which executes a number of procedures on an oracle DB.
The script defines:
DECLARE
productkey VARCHAR2(100);
BEGIN
productKey := '000000000070307037';
...
ProcedureName(productKey);
The procedure expects a VARCHAR2
PROCEDURE ProcedureName (
productKey VARCHAR2
)
The procedure inserts into a table:
BEGIN
Insert into Mytable
(
THIS_PRODUCT_KEY
)
Values
(productKey);
When I query that table, the product Key = 70307037, ie the leading 0's have been lost.
I saw some similar questions where TO_CHAR was suggested, I tried defining productKey in the script using TO_CHAR, and also modifiying the procedure to write using TO_CHAR:
BEGIN
Insert into Mytable
(
THIS_PRODUCT_KEY
)
Values
(TO_CHAR(productKey,'000000000000000000'));
Still coming through without the leading 0's.
There are multiple queries that join using the product key and don't work when the 0's are missing.
Why would I lose the 0's when the variable is a VARCHAR ?

I believe that "THIS_PRODUCT_KEY" column in your "Mytable" table is not a varchar2 column. I think it is number. If you change the datatype of the "THIS_PRODUCT_KEY" column to varchar2, it won't lose the 0s.

Related

Error(13,61): PL/SQL: ORA-00984: column not allowed here IN PROCEDURE WHEN PASS IN PARAMETER

CREATE OR REPLACE PROCEDURE INSEMP
(
EMPNOS IN VARCHAR2
, ENAMES IN VARCHAR2
, JOBAS IN VARCHAR2
, MGRS IN VARCHAR2
, HIREDATES IN VARCHAR2
, SALS IN VARCHAR2
, COMMISSIONS IN VARCHAR2
, DEPTNOS IN VARCHAR2
) AS
BEGIN
INSERT INTO emp VALUES (EMPNOS,ENAMES,JOBAS,MGRS,HIREDATES,SALS,COMMS,DEPTNOS);
END INSEMP;
When I execute the above, I get an error: Error(13,67): PL/SQL: ORA-00984: column not allowed here.
I know when we insert
INSERT INTO EMP VALUES ('DSFD'DSFDFD', ...)
we have to use single quotes, but how do I pass the values in via the parameters?
Your issue is that you have a parameter called COMMISSIONS but in your insert statement, you are passing in a value of COMMS.
Also, make sure your parameters have different names to the columns you're trying to insert into; this is (IMO) good practice across any PL/SQL code you're writing, as you can have unexpected results when name collisions happen.
Change your insert statement to use the right parameter name (or, alternatively, change the name of the parameter to match your insert statement) and it should start working.
One point, though: it is bad practice to not list the columns you are inserting into. In real production code, if someone added a column to the table, your code would break.
Your insert statement would be better written as:
insert into <table> (<list of columns to be inserted into>)
values (<list of values to insert into those columns>);

PLS-00103: Encountered Symbol DECLARE/EOF when trying to increment values with a sequence

I'm working on a procedure that will declare a variable, take the value from a procedure that increments, and inserts that value along with other parameters into a table. I thought I had it all worked out, but then I got hit with PLS-00103: Encountered symbol "DECLARE" and Encountered symbol "end-of-file". I feel like I'm so close, so any help would be majorly appreciated! Thank you!
create or replace procedure Order_Create(date_order string, cust_id char, total float, employ_id number)
is
DECLARE NewKey;
BEGIN
NewKey := order_auto_inc.nextval;
UPDATE Progressive_Keys set Order_Limit = NewKey;
insert into ORDERS VALUES (Progressive_Keys.Order_Limit, to_date(date_order, 'yyyy-mm-dd'), cust_id, total, employ_id);
commit;
END;
Remove the declare it's not needed in a stored procedures (as documented in the manual).
A variable declaration needs a data type.
As the parameter order_date is supposed to be a date, it should be declared with that type.
You can't access the column order_limit outside of a statement that uses the table progressive_keys so you need to use the variable in the insert statement as well.
It's also good coding practice to always list the target columns in an INSERT statement (note that I just invented some column names for the orders table you will have to adjust them to reflect the real names in your table)
create or replace procedure Order_Create(date_order date, cust_id varchar, total float, employ_id number)
is
NewKey number;
BEGIN
NewKey := order_auto_inc.nextval;
UPDATE Progressive_Keys set Order_Limit = NewKey;
insert into ORDERS (some_key, order_date, customer_id, total, employee_id)
VALUES (newkey, date_order, cust_id, total, employ_id);
commit;
END;
The UPDATE looks a bit strange as it will update all rows in the thable progressive_keys not just one row.

Adding a prefix N for a parameter in Oracle stored procedure

How can I add a prefix N for a parameter in stored procedure?
For example: in an insert/update/select statement we can do it like
insert into table xxx values (N'value')
Alter table set value = N'value1'
etc..
I want to add prefix to resolve the inverted question mark(¿) issue in the Oracle table column of type nvarchar2 for some characters like - (hyphen), TM (trade mark symbol) etc..
If I'm understanding what you're saying, you would just concatenate the string onto the value:
insert into table xxx values ('N'||value_1, value_2, value_3);
If your prefix isn't a fixed string, you could use a parameter:
prefix_1 := 'N';
insert into table xxx values (prefix_1||value_1, value_2, value_3);
Please try this, we can declare a local variable inside procedure to achieve it.
Not sure about how and if possible to include it in the IN parameter.
CREATE TABLE so_nvarchar_test (col1 NVARCHAR2(100)) ;
CREATE OR REPLACE PROCEDURE validate_nvarchar2(p_parameter NVARCHAR2)
IS
validated_param NVARCHAR2(100) := N''||p_parameter||'';
BEGIN
INSERT INTO so_nvarchar_test(col1) VALUES (validated_param);
END;
/
DECLARE
p_parameter NVARCHAR2(100) := 'Länsförsäkringar?';
BEGIN
INSERT INTO so_nvarchar_test(col1) VALUES (p_parameter);
END;
/

how to use one procedure to insert into two table

I want to insert value into EVENT table and EventCost table by using only one procedure.
The PK of event is EventID and it is the FK of EventCost table.
I tried to use SCOPE_IDENTITY() for EventID but still fail to create the procedure.
2)Do I need to declare the v_EventID in the header for two times? (One for the Event table , one for the eventCost table)
CREATE OR REPLACE PROCEDURE PRC_ADD_OVER_BUDGET_EVENT
( V_eventID IN VARCHAR
,V_EventType IN VARCHAR
,V_EventBudget IN NUMBER
,V_organizerID IN VARCHAR
,v_CostID IN VARCHAR
,v_FoodBeverage IN NUMBER
,v_wine IN NUMBER
,v_Decoration IN NUMBER
,v_rentalfee IN NUMBER
,v_facility IN NUMBER
,v_EventID IN VARCHAR)
AS
BEGIN
INSERT INTO Event
values
(next_eventid_seq,null,v_eventbudget,null,null,null,v_organizerID)
INSERT INTO EventCost
values
(next_Costid_seq,v_FoodBeverage,v_Wine,v_Decoration,v_RentalFee,v_Facility,SCOPE_IDENTITY())
End;
/
Use returning into clause:
CREATE OR REPLACE PROCEDURE PRC_ADD_OVER_BUDGET_EVENT
( V_eventID IN VARCHAR
,V_EventType IN VARCHAR
,V_EventBudget IN NUMBER
,V_organizerID IN VARCHAR
,v_CostID IN VARCHAR
,v_FoodBeverage IN NUMBER
,v_wine IN NUMBER
,v_Decoration IN NUMBER
,v_rentalfee IN NUMBER
,v_facility IN NUMBER
,v_EventID IN VARCHAR)
AS
event_ID varchar2(64);
BEGIN
INSERT INTO Event
values
(next_eventid_seq,null,v_eventbudget,null,null,null,v_organizerID) returning eventID into event_ID;
INSERT INTO EventCost
values
(next_Costid_seq,v_FoodBeverage,v_Wine,v_Decoration,v_RentalFee,v_Facility,event_ID);
End;
/
P.S. Also a few notes:
Use varchar2 datatype instead of varchar.
When inserting, provide the names of the columns you insert into: insert into Event (col1, col2, col3, ...). In case your table structure is changed, the insert statements will still work.

How to programmatically set table name in PL/SQL?

I created the following simple PL/SQL stored procedure example to ask a specific question. This procedure inserts an employee name and id number into a table called employees_???. The ??? is explained below.
PROCEDURE hire_employee (emp_id IN INTEGER, name IN VARCHAR2, country IN VARCHAR2)
AS
BEGIN
INSERT INTO employees_??? VALUES (emp_id, name, 1000);
END hire_employee;
What I need is to set the table name based on the IN variable country. For example,
If country = 'usa', I want the INSERT line to read:
INSERT INTO employees_usa VALUES (emp_id, name, 1000);
If country = 'germany', I want the INSERT line to read:
INSERT INTO employees_germany VALUES (emp_id, name, 1000);
If country = 'france', I want the INSERT line to read:
INSERT INTO employees_france VALUES (emp_id, name, 1000);
etc...
Is there a way to do this in PL/SQL by substituting something in place of employee_??? so only one line of code for INSERT is used? Or is using a case or if/then/else statement the best way?
To answer your question, you have to use execute immediate and create your statement dynamically.
create or replace procedure hire_employee (
emp_id IN INTEGER
, name IN VARCHAR2
, country IN VARCHAR2 ) is
-- maximum length of an object name in Oracle is 30
l_table_name varchar2(30) := 'employees_' || country;
begin
execute immediate 'insert into ' || l_table_name
|| ' values (:1, :2, 1000)'
using emp_id, name;
end hire_employee;
However, this is a massively over-complicated way of storing the data. If you want to select all data you have to union large numbers of tables.
It would be far better to normalise the database properly and add country to an employees table.
Something like the following:
create table employees (
emp_id number(16)
, country varchar2(3) -- ISO codes
, name varchar2(4000) -- maximum who knows what name people might have
, < other_columns >
, constraint pk_employees primary key ( emp_id )
);
Your procedure then becomes a very simple insert statement:
create or replace procedure hire_employee (
emp_id in integer
, name in varchar2
, country in varchar2 ) is
insert into employees
values ( emp_id, country, name, 1000 );
end hire_employee;
You can use dynamic SQL and the EXECUTE IMMEDIATE construct. In this, you construct the query as a string and then execute it. A good example is at http://docs.oracle.com/cd/B10500_01/appdev.920/a96590/adg09dyn.htm

Resources