Z-ORA-01745: invalid host/bind variable name (PLSQL) - plsql

I kind of new on dynamic variables in plsql.
I am getting an error "invalid host/bind variable name" on EXECUTE IMMEDIATE
statement. Thanks in advance.
CREATE OR REPLACE PROCEDURE MY_CLASS_CONFIG_DML (pBuCode VARCHAR2,
pMyPKId VARCHAR2,
pMyName VARCHAR2,
pMyId VARCHAR2,
pRemarks VARCHAR2,
pUserId VARCHAR2)
AS
v_table VARCHAR2 (50);
v_lastdate DATE;
--bindable var.
v_pkey VARCHAR2 (12) := pMyPKId;
v_myname VARCHAR2 (30) := pMyName;
v_bucode VARCHAR2 (4) := pBuCode;
v_myid VARCHAR2 (12) := pMyId;
v_remarks VARCHAR2 (50) := pRemarks;
v_lastid VARCHAR2 (8) := pUserId;
BEGIN
v_lastdate := SYSDATE;
v_table := v_bucode || '_WORKSHEET_CONFIG';
--Error happens on this part
EXECUTE IMMEDIATE
'insert into '
|| v_table
|| '(pk_id,my_name,my_id,remarks,last_user,last_date)
values(:pkey,:myname,:myid,:remarks,:user,:lastdate)'
USING v_pkey,
v_myname,
v_myid,
v_remarks,
v_lastid,
v_lastdate;
--end comment
COMMIT;
RETURN;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
END MY_CLASS_CONFIG_DML;

Replace :user by another keyword: :myuser or :lastid. The colon should make it possible to use the reserved keyword "user", but this is the only problem i see.

Related

How to execute the procedure

How to call the procedure and function from the package?
PROCEDURE P_INSERT_PER_LG(IN_DATA DATE,
IN_CHECK VARCHAR2,
IN_PSE VARCHAR2,
IN_TP_CHECK VARCHAR2,
IN_STATUS NUMBER,
IN_MSG VARCHAR2,
OUT_ERR_MSG OUT VARCHAR2);
FUNCTION F_GT_COD_PTH(IN_CODE IN VARCHAR2)RETURN C_GT_COD_OBJ;
A small sample package:
CREATE OR REPLACE
PACKAGE TEST_PKG AS
FUNCTION Get_Squere(p_num NUMBER) RETURN NUMBER;
PROCEDURE Put_Line(p_Text VARCHAR2);
END TEST_PKG;
-- .. and package body
CREATE OR REPLACE
PACKAGE BODY TEST_PKG AS
FUNCTION Get_Squere(p_num NUMBER) RETURN NUMBER AS
BEGIN
RETURN p_num * p_num;
END Get_Squere;
PROCEDURE Put_Line(p_Text VARCHAR2) AS
BEGIN
DBMS_OUTPUT.PUT_LINE(p_Text);
END Put_Line;
END TEST_PKG;
And plsql block calling procedure/function from the package
SET SERVEROUTPUT ON
DECLARE
m_number NUMBER(9);
m_text VARCHAR2(100) := 'Test - printed out by packaged Procedure...';
BEGIN
TEST_PKG.Put_Line(m_text); -- calling pacakaged procedure
m_number := TEST_PKG.Get_Squere(5); -- calling pakaged function
TEST_PKG.Put_Line(m_number || ' squered is ' || TEST_PKG.Get_Squere(m_number)); -- calling procedure with the value returned by function
END;
/
Result:
anonymous block completed
Test - printed out by packaged Procedure...
25 squered is 625

Merging varchars into one CLOB

I have the following procedure for merging 10 varchar variables of length 4000 characters into one CLOB:
procedure insert_iec_by_parts(p_header_id in number,
p_contents_part1 in varchar2,
p_contents_part2 in varchar2,
p_contents_part3 in varchar2,
p_contents_part4 in varchar2,
p_contents_part5 in varchar2,
p_contents_part6 in varchar2,
p_contents_part7 in varchar2,
p_contents_part8 in varchar2,
p_contents_part9 in varchar2,
p_contents_part10 in varchar2,
o_cur_results out sys_refcursor,
result_code out number) is
l_clob clob;
begin
l_clob:=p_contents_part1||p_contents_part2||p_contents_part3||p_contents_part4||p_contents_part5||
p_contents_part6||p_contents_part7||p_contents_part8||p_contents_part9||p_contents_part10;
insert_iec(p_header_id, l_clob, o_cur_results, result_code );
end;
procedure insert_iec(p_header_id in number,
p_contents in clob,
o_cur_results out sys_refcursor,
result_code out number) is
id_temp number;
l_id number;
procedure SetError(pErrCode number) is
-- A centralised sub proc could allow for a quick change to raise_application_error at any time.
begin
result_code := pErrCode;
end;
begin
select count(*) into l_id from log_sync_calls_headers
where log_sync_calls_headers.id =p_header_id;
case
when (p_header_id is null) or (l_id <= 0) then SetError(9804);
when p_contents is null then SetError(9805);
else
-- fetch sequence number
id_temp := iec_seq.nextval;
result_code:=0;
open o_cur_results for
select id_temp as id
from dual;
insert into log_sync_calls_iecs
(id, header_id, contents)
values
(id_temp, p_header_id, p_contents );
commit;
end case;
exception when others then
result_code :=9701;
rollback;
pkg_common.insert_log_record(p_source => 'insert_iec',
p_type => 'Er',
p_message => sqlerrm);
end;
Procedure works fine when merging 10 varchar variables of 4000 characters each. However, I want to extend it to 20 varchar variables of length 4000 characters.
When I try that, it gives me the following error:
ORA 06502: character string buffer too small.
Could someone show me how to be able to extend this procedure to 20 varchar variables of length 4000 characters?
Use DBMS_LOB.APPEND function like in this question (or just search for DBMS_LOB.APPEND in SO): how to insert long string oracle clob or blob
you should use the DBMS_LOB package.
first you should create a clob object otherwise you variable is not initialized
dbms_lob.createtemporary(l_clob ,true);
now you can use append procedure
dbms_lob.append(l_clob, p_contents_part1 );
after you are finished , don't forget to release a clob Memory and destroy you clob object
dbms_lob.freetemporary(l_clob);

Alter Object type body [PL/SQL]

i´m triying to alter a body type of an object. Here is my code:
ALTER TYPE Profesor ADD CONSTRUCTOR FUNCTION Profesor(codigo INTEGER, nombre
VARCHAR2,
primerApellido VARCHAR2, segundoApellido VARCHAR2, especialidad VARCHAR2)
RETURN SELF AS RESULT CASCADE;
/
CREATE OR REPLACE TYPE BODY Profesor AS CONSTRUCTOR FUNCTION Profesor(codigo
INTEGER, nombre VARCHAR2,
primerApellido VARCHAR2, segundoApellido VARCHAR2, especialidad VARCHAR2)
RETURN SELF AS RESULT IS
BEGIN
SELF.codigo := codigo;
SELF.nombre := nombre;
SELF.apellidos := primerApellido||' '||segundoApellido;
SELF.especialidad := especialidad;
RETURN;
END;
END;
/
I´ve created the Object and then i altered it adding a constructor and creating a type body.
The code doesn´t show errors but if i try to add a new method it lets me add the method but not de code:
ALTER TYPE Profesor ADD MEMBER FUNCTION getNombreCompleto RETURN VARCHAR2
CASCADE;
/
ALTER TYPE BODY Profesor ADD MEMBER FUNCTION getNombreCompleto RETURN
VARCHAR2
CASCADE
IS
BEGIN
RETURN SELF.nombre;
END getNombreCompleto;
END;
And that´s the question, how can i alter the body type of an object?
Thanks!
This solution should work. Alter type member function\ constructor works only for type specification. For body you have to recreate body.
ALTER TYPE Profesor ADD CONSTRUCTOR FUNCTION Profesor(codigo INTEGER, nombre
VARCHAR2,
primerApellido VARCHAR2, segundoApellido VARCHAR2, especialidad VARCHAR2)
RETURN SELF AS RESULT CASCADE;
/
ALTER TYPE Profesor ADD MEMBER FUNCTION getNombreCompleto RETURN VARCHAR2
CASCADE;
/
CREATE OR REPLACE TYPE BODY Profesor AS
CONSTRUCTOR FUNCTION Profesor(codigo
INTEGER, nombre VARCHAR2,
primerApellido VARCHAR2, segundoApellido VARCHAR2, especialidad VARCHAR2)
RETURN SELF AS RESULT IS
BEGIN
SELF.codigo := codigo;
SELF.nombre := nombre;
SELF.apellidos := primerApellido||' '||segundoApellido;
SELF.especialidad := especialidad;
RETURN;
END;
MEMBER FUNCTION getNombreCompleto RETURN
VARCHAR2
CASCADE
IS
BEGIN
RETURN SELF.nombre;
END getNombreCompleto;
END;
END;
/

error in pl/sql package body

I am having this error:
Error(42,22): PLS-00103: Encountered the symbol ")" when expecting one of the following: current
I have written a package with few functions and procedures.
here is my package:
-- specification --
CREATE OR REPLACE PACKAGE SUPERHERO_PACKAGE AS
FUNCTION GET_FULL_SUPERHERONAME(V_SUPERHERONAME IN VARCHAR2)
RETURN VARCHAR2;
PROCEDURE GET_SUPERHEROS(V_CITY IN VARCHAR2);
PROCEDURE GET_ALL_VILLANS;
FUNCTION GET_MAX_XP
RETURN NUMBER;
FUNCTION GET_STRONGEST_SUPERHERO
RETURN VARCHAR2;
END SUPERHERO_PACKAGE;
-- body --
CREATE OR REPLACE PACKAGE BODY SUPERHERO_PACKAGE AS
FUNCTION GET_FULL_SUPERHERONAME(V_SUPERHERONAME IN VARCHAR2)
RETURN VARCHAR2 AS
BEGIN
SELECT FIRST_NAME, LAST_NAME
INTO V_FNAME, V_LNAME
FROM SUPERHERO
WHERE SUPERHERO_NAME = V_SUPERHERONAME;
RETURN (V_FNAME || " " || V_LNAME);
END;
PROCEDURE GET_SUPERHEROS(V_CITY IN VARCHAR2) IS
CURSOR JUSTICE_LEAGUE IS
SELECT SUPERHERO_NAME FROM SUPERHERO WHERE CITY = V_CITY;
LEAGUE_MEMBER JUSTICE_LEAGUE % ROWTYPE;
BEGIN
OPEN JUSTICE_LEAGUE;
LOOP
FETCH JUSTICE_LEAGUE INTO LEAGUE_MEMBER;
EXIT WHEN (JUSTICE_LEAGUE % NOTFOUND);
DBMS_OUTPUT.PUT_LINE(LEAGUE_MEMBER.NAME);
END LOOP;
CLOSE JUSTICE_LEAGUE;
END;
PROCEDURE GET_ALL_VILLANS IS
CURSOR DARK_FORCE IS
SELECT VILLAN FROM SUPERHERO;
FORCE_MEMBER DARK_FORCE % ROWTYPE;
BEGIN
OPEN DARK_FORCE;
LOOP
FETCH DARK_FORCE INTO FORCE_MEMBER;
EXIT WHEN (DARK_FORCE % NOTFOUND);
DBMS_OUTPUT.PUT_LINE(FORCE_MEMBER.VILLAN);
END LOOP;
CLOSE DARK_FORCE;
END;
FUNCTION GET_MAX_XP()
RETURN NUMBER AS
DECLARE
N_XP := 0;
BEGIN
SELECT MAX(XP) INTO N_XP FROM SUPERHERO;
RETURN N_XP;
END;
FUNCTION GET_STRONGEST_SUPERHERO()
RETURN VARCHAR2 AS
DECLARE
V_NAME := 'DNA';
V_FNAME := 'SWAYAM';
V_LNAME := 'RAINA';
BEGIN
SELECT SUPERHERO_NAME, FIRST_NAME, LAST_NAME
INTO V_NAME, V_FNAME, V_LNAME
FROM SUPERHERO
WHERE XP = GET_MAX_XP();
RETURN (V_FNAME || " " || V_LNAME || " AKA " || V_NAME);
END;
END SUPERHERO_PACKAGE;
You code is full of mistakes. Please check below the corrections.
CREATE OR REPLACE PACKAGE SUPERHERO_PACKAGE
AS
FUNCTION GET_FULL_SUPERHERONAME (V_SUPERHERONAME IN VARCHAR2) RETURN VARCHAR2;
PROCEDURE GET_SUPERHEROS (V_CITY IN VARCHAR2);
PROCEDURE GET_ALL_VILLANS;
FUNCTION GET_MAX_XP RETURN NUMBER;
FUNCTION GET_STRONGEST_SUPERHERO RETURN VARCHAR2;
END SUPERHERO_PACKAGE;
-- body --
CREATE OR REPLACE PACKAGE BODY SUPERHERO_PACKAGE
AS
FUNCTION GET_FULL_SUPERHERONAME (V_SUPERHERONAME IN VARCHAR2)
RETURN VARCHAR2 AS
V_FNAME varchar2(1000);
V_LNAME varchar2(1000);
BEGIN
SELECT FIRST_NAME, LAST_NAME
INTO V_FNAME, V_LNAME
FROM SUPERHERO
WHERE SUPERHERO_NAME = V_SUPERHERONAME;
RETURN(V_FNAME||'--'||V_LNAME);
END;
PROCEDURE GET_SUPERHEROS (V_CITY IN VARCHAR2)
IS
CURSOR JUSTICE_LEAGUE(vr_city VARCHAR2) --- parameterized Query
IS
SELECT SUPERHERO_NAME
FROM SUPERHERO
WHERE CITY = vr_city;
LEAGUE_MEMBER JUSTICE_LEAGUE%ROWTYPE;
BEGIN
OPEN JUSTICE_LEAGUE(V_CITY); --This is the way to call.
LOOP
FETCH JUSTICE_LEAGUE INTO LEAGUE_MEMBER;
EXIT WHEN JUSTICE_LEAGUE%NOTFOUND; -- No brackets needed
DBMS_OUTPUT.PUT_LINE(LEAGUE_MEMBER.SUPERHERO_NAME);
END LOOP;
CLOSE JUSTICE_LEAGUE;
END;
PROCEDURE GET_ALL_VILLANS
IS
CURSOR DARK_FORCE
IS
SELECT VILLAN
FROM SUPERHERO;
FORCE_MEMBER DARK_FORCE%ROWTYPE;
BEGIN
OPEN DARK_FORCE;
LOOP
FETCH DARK_FORCE INTO FORCE_MEMBER;
EXIT WHEN DARK_FORCE%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (FORCE_MEMBER.VILLAN);
END LOOP;
CLOSE DARK_FORCE;
END;
FUNCTION GET_MAX_XP
RETURN NUMBER
AS
N_XP number:= 0; --Never use declare here
BEGIN
SELECT MAX (XP) INTO N_XP FROM SUPERHERO;
RETURN N_XP;
END;
FUNCTION GET_STRONGEST_SUPERHERO
RETURN VARCHAR2
AS
V_NAME varchar2(1000) := 'DNA'; --------Declaration Missing
V_FNAME varchar2(1000) := 'SWAYAM';
V_LNAME varchar2(1000) := 'RAINA';
BEGIN
SELECT SUPERHERO_NAME, FIRST_NAME, LAST_NAME
INTO V_NAME, V_FNAME, V_LNAME
FROM SUPERHERO
WHERE XP = (SELECT GET_MAX_XP() from dual); ----general practrice to call a function in where clause
RETURN (V_FNAME||' '||V_LNAME||'AKA'||V_NAME); --no double quotes
END;
END SUPERHERO_PACKAGE;

PLS-00103 ERROR, what is wrong in the code

CREATE OR REPLACE PROCEDURE proc2_del_rows
(v_tname VARCHAR2,
v_condition VARCHAR2 DEFAULT NULL)
AS
sql_stmt VARCHAR2(500);
where_clause VARCHAR2(200) := 'WHERE'||' '||v_condition;
BEGIN
IF v_condition IS NULL THEN
where_clause := NULL;
END IF;
sql_stmt := 'DELETE FROM :1'||' '||where_clause;
EXECUTE IMMEDIATE sql_stmt USING v_tname;
COMMIT;
END;
/
The table name can't be a bind variable. Do a DBMS_ASSERT on the input table name parameter and make sure it is a valid table name literal, and then directly concatenate it to the delete statement. This will at least protect you against sql injection.
I'd like to know the reason behind doing a delete using a procedure and granting execute on this procedure to individual users, rather than granting a delete on the table to a user directly, which would somewhat be easier to control/restrict. I don't see how this is better in terms on security if that is what you are going for.
CREATE or replace PROCEDURE proc2_del_rows
(v_tname VARCHAR2,
v_condition VARCHAR2 DEFAULT NULL)
AS
sql_stmt VARCHAR2(500);
where_clause VARCHAR2(200) := 'WHERE'||' '||v_condition;
BEGIN
IF v_condition IS NULL THEN
where_clause := NULL;
END IF;
sql_stmt := 'DELETE FROM '||v_tname||' '||where_clause;
EXECUTE IMMEDIATE sql_stmt;
END;
/
To include a single-quote character within a string literal you need to double up the single quotes, as in proc2_del_rows('EMP', 'JOB=''CLERK''').
Documentation here

Resources