Oracle Bind Variable giving error - oracle

SET SERVEROUTPUT ON
VARIABLE dept_id NUMBER
DECLARE
max_deptno NUMBER(3);
dept_name departments.department_name%TYPE :='Education';
BEGIN
SELECT MAX(department_id)
INTO max_deptno
FROM departments;
DBMS_OUTPUT.PUT_LINE ('The maximum department no is : ' || max_deptno);
:dept_id:=(max_deptno+10);
INSERT INTO departments (department_name, department_id,location_id)
VALUES(dept_name, :dept_id, NULL);
DBMS_OUTPUT.PUT_LINE ('The number of rows affected : ' || SQL%ROWCOUNT);
END;
/
Error report:
ORA-01400: cannot insert NULL into ("SYSTEM"."DEPARTMENTS"."DEPARTMENT_ID")
ORA-06512: at line 10
01400. 00000 - "cannot insert NULL into (%s)"
*Cause:
*Action:
The maximum department no is : 190
I am getting this error while trying to execute the bind variable in oracle statment. But if i put some value instead of bind variable, i get this insert statement right. What am I doing wrong here?

I think the value of the bind variable is only set when the pl/sql block is finished. And it probably has to terminate normally.
One solution is to use max_deptno+10 in the insert insead of :dept_if. A better solution is to create another pl/sql variable and use that in the insert statement.
new_dept_id := max_deptno+10;
:dept_id := new_dept_id;
You also have to change the INSERT statement:
INSERT INTO departments (department_name,department_id,location_id)
VALUES(dept_name, new_dept_id, NULL);

I think this error is obtained because you use bind variable without using set autoprint on in start program.

Related

Create Table in a Loop inside Stored Procedure Oracle SQL

I am attempting to create a Oracle stored procedure which creates partitioned tables based off of a table containing the table names and the column to be partitioned with. A separate PL/SQL block iterates through the table and calls the procedure with the table name and the column name.
Procedure:
create or replace PROCEDURE exec_multiple_table_create (
table_name IN VARCHAR2,
column_name IN VARCHAR2
) IS
stmt VARCHAR2(5000);
tablename VARCHAR2(50);
columnname VARCHAR2(50);
BEGIN
tablename := table_name;
columnname := column_name;
-- DBMS_OUTPUT.PUT_LINE(tablename);
-- DBMS_OUTPUT.PUT_LINE(columnname);
stmt := 'create table '
|| TABLENAME
|| '_temp as (select * from '
|| COLUMNNAME
|| ' where 1=2)';
EXECUTE IMMEDIATE stmt
USING IN table_name, column_name;
stmt := 'alter table '
|| tablename
|| '_temp modify partition by range('
|| columnname
|| ')
(PARTITION observations_past VALUES LESS THAN (TO_DATE(''20000101'',''YYYYMMDD'')),
PARTITION observations_CY_2000 VALUES LESS THAN (TO_DATE(''20010101'',''YYYYMMDD'')),
PARTITION observations_CY_2001 VALUES LESS THAN (TO_DATE(''20020101'',''YYYYMMDD'')),
PARTITION observations_CY_2002 VALUES LESS THAN (TO_DATE(''20030101'',''YYYYMMDD'')),
PARTITION observations_CY_2003 VALUES LESS THAN (TO_DATE(''20040101'',''YYYYMMDD'')),
PARTITION observations_CY_2004 VALUES LESS THAN (TO_DATE(''20050101'',''YYYYMMDD'')),
PARTITION observations_CY_2005 VALUES LESS THAN (TO_DATE(''20060101'',''YYYYMMDD'')),
PARTITION observations_CY_2006 VALUES LESS THAN (TO_DATE(''20070101'',''YYYYMMDD'')),
PARTITION observations_CY_2007 VALUES LESS THAN (TO_DATE(''20080101'',''YYYYMMDD'')),
PARTITION observations_CY_2008 VALUES LESS THAN (TO_DATE(''20090101'',''YYYYMMDD'')),
PARTITION observations_CY_2009 VALUES LESS THAN (TO_DATE(''20100101'',''YYYYMMDD'')),
PARTITION observations_CY_2010 VALUES LESS THAN (TO_DATE(''20110101'',''YYYYMMDD'')),
PARTITION observations_FUTURE VALUES LESS THAN ( MAXVALUE ) )';
EXECUTE IMMEDIATE stmt
USING IN table_name, column_name;
RETURN;
END exec_multiple_table_create;
The PL/SQL block which is using the stored proc is:
BEGIN
FOR partition_item IN (
SELECT
table_name,
partition_column
FROM
partition_table
) LOOP
exec_multiple_table_create(partition_item.table_name, partition_item.partition_column);
END LOOP;
END;
Now, when I try executing the thing, this is what I am seeing:
Error report -
ORA-06550: line 9, column 9:
PLS-00905: object SCG_MYACCT_CUSTOMPC.EXEC_MULTIPLE_TABLE_CREATE is invalid
ORA-06550: line 9, column 9:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I have a feeling that I am missing something. Please let me know what it is. The table containing the reference data exists and contains data.
I have tried refreshing the table, rewriting and modifying the pl/sql block & the procedure code. Nothing seems to be working.
Thanks in advance.
UPDATE 1:
There was a glitch in the stored procedure where I needed to refer to the tablename rather than the columnname in the code above. However, I am getting a different error right now.
Error report -
ORA-06546: DDL statement is executed in an illegal context
ORA-06512: at "SCG_MYACCT_CUSTOMPC.EXEC_MULTIPLE_TABLE_CREATE", line 18
ORA-06512: at line 9
ORA-06512: at line 9
06546. 00000 - "DDL statement is executed in an illegal context"
*Cause: DDL statement is executed dynamically in illegal PL/SQL context.
- Dynamic OPEN cursor for a DDL in PL/SQL
- Bind variable's used in USING clause to EXECUTE IMMEDIATE a DDL
- Define variable's used in INTO clause to EXECUTE IMMEDIATE a DDL
*Action: Use EXECUTE IMMEDIATE without USING and INTO clauses to execute
the DDL statement.
Please help me out with this as well.
UPDATE 2:
I removed the USING part of the EXECUTE IMMEDIATE statement. That seemed to take care of the error I posted. Getting a different error with versions now:
Error starting at line : 1 in command -
BEGIN
FOR partition_item IN (
SELECT
table_name,
partition_column
FROM
partition_table
) LOOP
exec_multiple_table_create(partition_item.table_name, partition_item.partition_column);
END LOOP;
END;
Error report -
ORA-00406: COMPATIBLE parameter needs to be 12.2.0.0.0 or greater
ORA-00722: Feature "Conversion into partitioned table"
ORA-06512: at "SCG_MYACCT_CUSTOMPC.EXEC_MULTIPLE_TABLE_CREATE", line 37
ORA-06512: at line 9
ORA-06512: at line 9
00406. 00000 - "COMPATIBLE parameter needs to be %s or greater"
*Cause: The COMPATIBLE initialization parameter is not high
enough to allow the operation. Allowing the command would make
the database incompatible with the release specified by the
current COMPATIBLE parameter.
*Action: Shutdown and startup with a higher compatibility setting.

Oracle: Using EXECUTE IMMEDIATE with RETURNING INTO

I have a procedure that does a validation and inserts a record in a table. The procedure is breaking right after the INSERT statement when I try the following code:
EXECUTE IMMEDIATE V_SOME_STRNG || ' returning SOME_ID into :NEW_ID' returning into V_TRGT_ID;
I am trying to execute my INSERT statement which is stored in V_SOME_STRNG and assign the new record's ID to V_TRGT_ID. However, I am running into the following error:
ORA-00933: SQL command not properly ended
Any thoughts?
You don't need to repeat the returning into part, you need a using clause for your bind variable:
EXECUTE IMMEDIATE V_SOME_STRNG || ' returning SOME_ID into :NEW_ID' using out V_TRGT_ID;
Demo using a basic trigger to provide the ID:
create table t42 (some_id number, dummy varchar2(1));
create sequence s42 start with 42;
create trigger tr42 before insert on t42 for each row
begin
:new.some_id := s42.nextval;
end;
/
set serveroutput on
declare
v_some_strng varchar2(200) := 'insert into t42 (dummy) values (''X'')';
v_trgt_id number;
begin
EXECUTE IMMEDIATE V_SOME_STRNG || ' returning SOME_ID into :NEW_ID' using out V_TRGT_ID;
dbms_output.put_line('Returned ID: ' || v_trgt_id);
end;
/
which shows:
Returned ID: 42
PL/SQL procedure successfully completed.
You can only use returning into with the insert .. values ... pattern, not with insert ... select ...; so for instance changing the code above to use;
v_some_strng varchar2(200) := 'insert into t42 (dummy) select ''X'' from dual';
will get the error you originally reported:
ORA-00933: SQL command not properly ended
ORA-06512: at line 6
While you don't need to use returning into part, the OP problem most likely results from an error in the not shown content of the V_SOME_STRNG variable. Because you definitely can use returning into with execute immediate. Here is an example strait from the documentation:
sql_stmt := 'UPDATE emp SET sal = 2000 WHERE empno = :1 RETURNING sal INTO :2';
EXECUTE IMMEDIATE sql_stmt USING emp_id RETURNING INTO salary;
I stress the point again: it works. So if you have any troubles here check you dynamically generated SQL statement more thoroughly.
My test_queries table consist of 2 columns:fid and query_text.I want insert new row. And I return fid I inserted because I use it next question. But the code give me error .
select max(a.fid) into max_fid from test_queries a;
execute immediate 'insert into test_queries values (:1,:2) returning fid into :a' using max_fid+1,query_text,c;

Call Procedure Unexpected error

I'm coding a DML package, and I would like create a simple procedure within package to updated commission_pct value. I don't receive any syntax error when I execute the package body but when I call the procedure I receive a unexpected error. Thanks.
PROCEDURE update_commission_pct(
p_empid employees.employee_id%TYPE,
p_new_comm employees.commission_pct%TYPE
)
IS
rec_confirm employees%ROWTYPE;
v_valid_empid BOOLEAN;
BEGIN
-- Simple boolean function to check employee existence
v_valid_empid := dml_employees_pkg.check_employee_id(p_empid);
IF
v_valid_empid = TRUE
AND LENGTH(p_new_comm) <=5 THEN
UPDATE employees
SET commission_pct = p_new_comm
WHERE employee_id = p_empid
RETURNING employee_id, commission_pct
INTO rec_confirm.employee_id, rec_confirm.commission_pct;
DBMS_OUTPUT.PUT_LINE('Comission updated successfully.');
DBMS_OUTPUT.PUT_LINE('Employee ID number ' ||
rec_confirm.employee_id || ' new comm is' ||
rec_confirm.commission_pct);
ELSE
RAISE_APPLICATION_ERROR(-20042, 'Employee ID ' ||
p_empid || ' Employee doesn't exist.');
END IF;
END update_commission_pct;
Call procedure in a simple PL/SQL block:
SET SERVEROUTPUT ON
BEGIN
dml_employees_pkg.update_commission_pct(550, 10);
END;
Oracle ERROR:
Informe de error -
ORA-01438: value larger than specified precision allowed for this column
ORA-06512: at "HR.DML_EMPLOYEES_PKG", line 118
ORA-06512: at line 2
01438. 00000 - "value larger than specified precision allowed for this column"
*Cause: When inserting or updating records, a numeric value was entered
that exceeded the precision defined for the column.
*Action: Enter a value that complies with the numeric column's precision,
or use the MODIFY option with the ALTER TABLE command to expand
the precision.
The commission_pct column in the employees table (in the default HR schema) is defined as number(2, 2).
The meaning of the precision and scale is explained inthe documentation, but essentially here it means the column can only accept values from 0.00 to 0.99. You're trying to insert 10, which - as the error says - exceeds the allowed precision.
If you want to store 10% you can either pass 0.1 as the second argument in your procedure call; or stick with passing 10 but then divide by 100 as part of the update statement:
SET commission_pct = p_new_comm/100
You may want to validate the passed value in some way other than checking its length. And at the moment if the LENGTH(p_new_comm) <=5 check fails, the raised exception doesn't make that clear - it only refers to the employee ID which may actually be valid. The length check doesn't really sense anyway though.

Oracle PL/SQL Cursor in Trigger

I got this trigger, seems to be alright but i got the error :
Trigger :
CREATE OR REPLACE TRIGGER TRG_TABLE_BI
BEFORE INSERT
ON TABLE
FOR EACH ROW
DECLARE
CURSOR cur_list IS
SELECT emp, name, day, salary, id,phone
FROM TABLE NATURAL JOIN OTHERTABLE
WHERE emp = :NEW.emp AND name = :NEW.name AND id = :NEW.id;
curChoice cur_list%ROWTYPE;
BEGIN
OPEN cur_list;
LOOP
FETCH cur_list INTO curChoice;
EXIT WHEN cur_list%NOTFOUND;
dbms_output.put_line(curchoice.id);
dbms_output.put_line(curChoice.emp);
dbms_output.put_line(curchoice.name);
END LOOP;
CLOSE cur_list;
END;
/
I got those error :
PLS-00049: bad bind variable 'NEW.emp'
If i remove the ':' in the cursor declaration in my WHERE clause, i got a lot more error
Thank you.
Ok, i found the error, in my cursor declaration in the WEHRE clause, i had to remove
emp = :NEW.emp AND name = :NEW.name
because there's no such column in the table that im currently inserting.
Thank !

Oracle : Stored procedure how to to_char expression in string variable

I am trying to create table dynamically in Oracle stored procedure.
I have created create table sql in the string variable.
Below is the sql snapshot and error.
Procedure is getting compiled without any issue. But when trying to execute the procedure, I am getting runtime error. I am getting the issue because of to_char expression.
CREATE OR REPLACE PROCEDURE TESTPROC12(P_TMP_Table IN VARCHAR2) AUTHID CURRENT_USER IS
V_SQL_STMT1 varchar2(1000);
V_TMP_Table varchar2(100);
BEGIN
V_TMP_Table := concat('TMP', to_char(sysdate,'MMDDYYYYHH24MISSSSS'));
V_SQL_STMT1 := 'CREATE TABLE '|| V_TMP_Table||' AS
SELECT * from TMP_STMTSENT2 where rowid in (select min(rowid) from '|| P_TMP_Table||'
group by CUSTOMER_RELATIONSHIP_ID, to_char(''STATEMENT_PROCESSED_DATE'',''MM/DD/YYYY''))';
EXECUTE IMMEDIATE V_SQL_STMT1;
END;
Procedure - I need to use to_char.
EXEC TESTPROC12('TMP_STMTSENT2')
Error starting at line 20 in command:
EXEC TESTPROC12('TMP_STMTSENT2')
Error report:
ORA-01722: invalid number
ORA-06512: at "EDLVY.TESTPROC12", line 15
ORA-06512: at line 1
01722. 00000 - "invalid number"
*Cause:
*Action:
The generated and executed statement could look like the following:
CREATE TABLE 10222013023309188 AS SELECT * from TMP_STMTSENT2 where rowid in (select min(rowid) from qeoiwqeoiwq group by CUSTOMER_RELATIONSHIP_ID, to_char('STATEMENT_PROCESSED_DATE','MM/DD/YYYY'))
The problem could be with 'STATEMENT_PROCESSED_DATE', which is not a date. Try sysdate instead and see if it works.
Take a look at the docs. You are passing the string 'STATEMENT_PROCESSED_DATE' to to_char(). Maybe you want to pass the column or value STATEMENT_PROCESSED_DATE instead?
A good way to do what you are pusuing is using Oracle Temporary Tables
http://docs.oracle.com/cd/B28359_01/server.111/b28310/tables003.htm#i1006400
http://www.dba-oracle.com/t_temporary_tables_sql.htm
http://www.oracle-base.com/articles/misc/temporary-tables.php

Resources