Error calling stored procedure from PHP - oracle

I have a problem with this code in Oracle:
create or replace procedure InsertarEntertNotica (IDSUBTOPIC out varchar,
TEXT out varchar,IMAGE out varchar,STADE out varchar,TITT out varchar)
is
idS varchar2(3) := IDSUBTOPIC;
txt varchar2(4000) := TEXT;
img varchar2(100) := IMAGE;
st varchar2(2) := STADE;
fech varchar2(30);
tit varchar2(300) := TITT;
hor date;
begin
SELECT TO_CHAR(SYSDATE,'DD/MM/YY') into fech FROM DUAL;
SELECT SYSDATE into hor FROM DUAL;
insert into ENTERTAIMENT (IDSUBTEMA,TEXTO,IMAGEN,ESTADO,FECHA,TITULO,HORA)
values (idS,txt,img,st,fech,tit,hor);
end;
When I create this SP, I have not problem, but when I execute it I have this problem
Error starting at line : 377 in command -
execute InsertarEntertNotica('ET','Texto de la Noticia Proc','','No','Noticia con Procedimiento')
Error report -
ORA-06550: line 1, column 28:
PLS-00363: expression 'ET' cannot be used as an assignment target
ORA-06550: line 1, column 33:
PLS-00363: expression 'Texto de la Noticia Proc' cannot be used as an assignment target
ORA-06550: line 1, column 60:
PLS-00363: expression '<null>' cannot be used as an assignment target
ORA-06550: line 1, column 63:
PLS-00363: expression 'No' cannot be used as an assignment target
ORA-06550: line 1, column 68:
PLS-00363: expression 'Noticia con Procedimiento' cannot be used as an assignment target
ORA-06550: line 1, column 7:

You've declared all your formal parameters as OUT, which means when you call the procedure you must pass updatable variables, not fixed string values. The documentation shows how IN/OUT works.
You can just change them to IN. You also don't need any of the local variables:
create or replace procedure InsertarEntertNotica (IDSUBTOPIC in varchar,
TEXT in varchar,IMAGE in varchar,STADE in varchar,TITT in varchar)
is
begin
insert into ENTERTAIMENT (IDSUBTEMA, TEXTO, IMAGEN, ESTADO, FECHA, TITULO, HORA)
values (IDSUBTOPIC, TEXT, IMAGE, STADE, TO_CHAR(SYSDATE,'DD/MM/YY'),
TITT, SYSDATE);
end;
If you are going to have local variables then names that distinguish from the parameter names would be good. It's common to use a prefix to distinguish, e.g. p_text for the parameter and l_text for the local variable.
Using TO_CHAR(SYSDATE,'DD/MM/YY') looks wrong for a couple of reasons. Two digit years can cause unexpected results, as well as the infamous Y2K problems. If FECHA is a DATE column rather than VARCHAR2(8), as it should be, then you are implicitly converting that string back to a date using the session NLS settings - which is dangerous, and will only work at all if the session happens to also be DD/MM/YY. If you're really trying to store today's date with the time as midnight then you should use TRUNC(SYSDATE) instead. Although not sure why you'd store that as a separate column to HORA anyway.

Related

Exception PL/SQL

Caution my english is horrible.
No one answers in the spanish forum.
doubts :
¿How can I control the exception of a empty entry? (Explanation following)
¿What value is saved in the variable if there's an empty entry?
I created this variable:
DECLARE
v_input NUMBER(8) := &entry;
I don't give a value, I mean in the pop up I accept directly without writing anything.
POPUP IMG
when I read the error code ( that I will leave at the end), I came across this line.
PLS-00103: Encountered the symbol ' ; ' when expecting one of the following :
So I guess the variable default value if you do a empty entry is -> ;
then I thought of controling the exception creating a IF, this if compares my variable (with empty entry/value) to ' ; ' you can see below.
BEGIN
DBMS_OUTPUT.PUT_LINE(v_codigo);
IF(v_codigo = ';')THEN
RAISE v_excepcion;
END IF;
EXCEPTION
when v_excepcion then
DBMS_OUTPUT.PUTLINE('No has insertado un valor válido');
END;
ERROR CODE
Informe de error -
ORA-06550: línea 2, columna 32:
PLS-00103: Se ha encontrado el símbolo ";" cuando se esperaba uno de los siguientes:
( - + case mod new not null <an identifier>
<a double-quoted delimited-identifier> <a bind variable>
continue avg count current exists max min prior sql stddev
sum variance execute forall merge time timestamp interval
date <a string literal with character set specification>
<a number> <a single-quoted SQL string> pipe
<an alternatively-quoted string literal with character set specification>
<an al
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
sorry for my grammar mistakes, If it does not clear I will follow the post for give you more information.
thx
Exception handlers are for exceptions (errors) encountered during execution of your function or procedure or anonymous block. They don't handle syntax errors - where the function or procedure won't even compile.
You are using a substitution variable - one that is "substituted" (replaced) by your editor BEFORE the code is ever presented to the PL/SQL parser. THAT kind of error can't be anticipated and handled in the code - if you return nothing (an empty string) when prompted, the code itself will receive "nothing" in that place, and the syntax of your function or procedure will be incorrect, so you will get the syntax error you received. Your code looks exactly like this after the substitution:
v_input NUMBER(8) := ;
resulting exactly in the syntax error you have seen.
The correct way to pass in a value at run time is to use parameters (for functions or procedures), or bind variables in an anonymous block. The variable must be declared and initialized before executing the block (in a command line environment like SQL*Plus); or, in a GUI like Toad or SQL Developer, you will be prompted for a value for the bind variable. If you press Enter without giving a value, that is interpreted as NULL, which is perfectly valid. (Whether it is what you want or not, that's a different question.)
The code would have to look something like this:
declare
v_input number(8) := :entry; -- notice the leading colon :
begin
dbms_output.put_line(v_input);
end;
/
If you want to handle the case of NULL input, you would do it in code:
declare
v_input number(8) := :entry;
begin
if v_input is null then
-- handle it here
else
dbms_output.put_line(v_input); -- or whatever else you need to do
end if;
end;
/
You don't need exception to handle that; you could dbms_output.put_line (note that you used putline, which is wrong) within IF, or even raise_application_error if you want to stop execution. For example (valid value first):
SQL> declare
2 v_codigo varchar2(20) := '&entry';
3 begin
4 if v_codigo = ';' or v_codigo is null then
5 raise_application_Error(-20000, 'Invalid value');
6 else
7 dbms_output.put_line('You entered ' || v_codigo);
8 end if;
9 end;
10 /
Enter value for entry: Littlefoot
You entered Littlefoot
PL/SQL procedure successfully completed.
Invalid values: empty string and ;;
SQL> /
Enter value for entry:
declare
*
ERROR at line 1:
ORA-20000: Invalid value
ORA-06512: at line 5
SQL> /
Enter value for entry: ;
declare
*
ERROR at line 1:
ORA-20000: Invalid value
ORA-06512: at line 5
SQL>
Or, to reuse your own code: declare the exception first (line #3), then use it:
SQL> declare
2 v_codigo varchar2(20) := '&entry';
3 v_excepcion exception;
4 BEGIN
5 DBMS_OUTPUT.PUT_LINE(v_codigo);
6 IF(v_codigo = ';' or v_codigo is null) THEN
7 RAISE v_excepcion;
8 END IF;
9
10 EXCEPTION
11 when v_excepcion then
12 DBMS_OUTPUT.PUT_LINE('No has insertado un valor válido');
13 END;
14 /
Enter value for entry: Littlefoot
Littlefoot
PL/SQL procedure successfully completed.
SQL> /
Enter value for entry:
No has insertado un valor válido
PL/SQL procedure successfully completed.
SQL> /
Enter value for entry: ;
;
No has insertado un valor válido
PL/SQL procedure successfully completed.
SQL>

Can I use INSERT ALL with multiple recordtype variables?

Given a PL/SQL block where I have access to 2 recordtype variables, I want to insert these 2 records into the same table in a single statement, but my attempts to use INSERT ALL have failed thus far. Is it possible to use INSERT ALL with record variables at all?
Here is some code that works, using dedicated inserts:
DECLARE
mProperty1 MyTable%ROWTYPE;
mProperty2 MyTable%ROWTYPE;
...
BEGIN
...
INSERT INTO MyTable VALUES mProperty1;
INSERT INTO MyTable VALUES mProperty2;
...
END;
If I try to convert the statement to a INSERT ALL though, it fails with an error message:
DECLARE
mProperty1 MyTable%ROWTYPE;
mProperty2 MyTable%ROWTYPE;
...
BEGIN
...
INSERT ALL
INTO MyTable VALUES mProperty1
INTO MyTable VALUES mProperty2
SELECT 1 FROM DUAL;
...
END;
ORA-06550: line 14, column 60:
PLS-00382: expression is of wrong type
ORA-06550: line 13, column 60:
PLS-00382: expression is of wrong type
ORA-06550: line 13, column 60:
PL/SQL: ORA-00904: : invalid identifier
ORA-06550: line 12, column 7:
PL/SQL: SQL Statement ignored
Am I missing something obvious? Is there a way to make this statement work?
I have tried using different methods but succeeded with the only following:
Method 1:
Using particular record names from %ROWTYPE field
DECLARE
mProperty1 MyTable%ROWTYPE;
mProperty2 MyTable%ROWTYPE;
BEGIN
mProperty1.COL1 := 1;
mProperty2.COL1 := 2;
INSERT ALL
INTO MyTable VALUES (mProperty1.col1)
INTO MyTable VALUES (mProperty2.col1)
SELECT 1 FROM DUAL;
END;
/
-- may be bad choice but you can use like this
Method 2:
If you are concerned about performance then you can also use this method:
DECLARE
TYPE mProperty_TYPE IS TABLE OF MyTable%ROWTYPE;
mProperty mProperty_TYPE;
BEGIN
mProperty := mProperty_TYPE();
mProperty.EXTEND(2);
mProperty(1).COL1 := 3;
mProperty(2).COL1 := 4;
FORALL I IN 1..mProperty.COUNT
INSERT INTO MyTable VALUES mProperty(I);
END;
/
db<>fiddle demo

Calculate the substitution variable length in oracle plsql

I have simple plsql program, basically what I would like to do is to calculate the length of the name which is dynamic input to plsql and then loop based on the length.
When I give pre-defined value like v_name = 'Dex' it works but when I give v_name = &name it throws an error message saying Dex must be declared.
Appreciate if any one can shed light on this issue. Please find error and program details below:
Error report:
ORA-06550: line 6, column 13:
PLS-00201: identifier 'DEX' must be declared
ORA-06550: line 6, column 3:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
PLsql Program:
declare
v_name varchar2(30);
v_loop_count number;
v_len number;
begin
v_name := &name;
v_loop_count := 0;
v_len := length(v_name);
for v_loop_count in 0 .. v_len-1
loop
dbms_output.put_line('Entered Name is :: '||v_name);
end loop;
end;
In SQL Developer (and in sqlplus), you can define substitution variables such as you're doing that start with &. But these substitution variables are unlike variables or literals in your code. These substitution variables will only be replaced textually, before the code gets parsed and executed.
If you have
v_name := &name;
Then the textual replacement will yield this code:
v_name := Dex;
Because you don't have a variable named DEX, you get the error you mentioned.
As mentioned in the comments, placing single-quotes around the substitution variable is the answer.
v_name := '&name';
This will get replaced with
v_name := 'Dex';
which is what you wanted -- the string value 'Dex'.

SQLDeveloper : Not enough arguments

I'm writing an APEX application which utilises spatial for proximity searching via Googlemaps API, I've built the function and it compiles fine, however whenever I try to run it in SQLDeveloper I get the error not enough arguments.
The function I created to set the new lat/long point takes one input of postcode from my stores table, it then uses the Google map API to return the long lat co-ords for that postcode, which on return builds an SDO_GEOMETRY object, which is returned and set in a location column in the stores table.
Function code:
CREATE OR REPLACE FUNCTION set_spatial_point
(
-- Only accept postcodes from the store table
p_postcode stores.postcode%TYPE
)
RETURN MDSYS.SDO_GEOMETRY
IS
-- Build local variables
l_lng VARCHAR2(100);
l_lat VARCHAR2(100);
n_spatial_object MDSYS.SDO_GEOMETRY;
BEGIN
-- Populate long and lat parameters
POSTCODE_TO_LAT_LNG_GM_API(p_postcode, l_lat, l_lng);
-- Populate the new spatial object
n_spatial_object := MDSYS.SDO_GEOMETRY
(
-- use 01 as we wish to add the point to the map
2001,
-- SRID for WGS84 longitutde/latitude format
8307,
-- Set the information of the point ( we don't need a Z co-ord )
SDO_POINT_TYPE
(
l_lng,
l_lat,
null
),
null, -- We have no SDO_ELEM_INFO_ARRAY
null -- We have no SDO_ORDINATE_ARRAY
);
-- Return the new spatial object
dbms_output.put_line('sdo_gtype='||n_spatial_object.sdo_gtype);
dbms_output.put_line('first element from sdo_ordinates='||n_spatial_object.sdo_ordinates(1));
RETURN n_spatial_object;
END set_spatial_point;
Why am I getting the not enough arguments error, even when I call it with a valid stores.postcode%TYPE, ( I have tried changing to VARCHAR2 but that doesn't make any difference.)
EDIT:
After creating the function, I run a call to the method:
DECLARE
my_object MDSYS.SDO_GEOMETRY;
BEGIN
my_object := set_spatial_value('MK80PB');
END;
I now get the following error:
Error starting at line : 1 in command -
DECLARE
my_object MDSYS.SDO_GEOMETRY;
BEGIN
my_object := set_spatial_value('MK80PB');
END;
Error report -
ORA-06550: line 4, column 14:
PLS-00201: identifier 'SET_SPATIAL_VALUE' must be declared
ORA-06550: line 4, column 1:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The error you get is obvious: you create the function as SET_SPATIAL_POINT() but you call SET_SPATIAL_VALUE() and that obviously fails since it does not exist.
Now, let's try this out. I had to replace some of your code since I don't have your declarations of the STORES table or the Google call, so I hard-coded the results from that call:
CREATE OR REPLACE FUNCTION set_spatial_point
(
-- Only accept postcodes from the store table
p_postcode varchar2
)
RETURN SDO_GEOMETRY
IS
-- Build local variables
l_lng VARCHAR2(100);
l_lat VARCHAR2(100);
n_spatial_object SDO_GEOMETRY;
BEGIN
-- Populate long and lat parameters
-- POSTCODE_TO_LAT_LNG_GM_API(p_postcode, l_lat, l_lng);
l_lat:=45.3;
l_lng:= 3.7;
-- Populate the new spatial object
n_spatial_object := SDO_GEOMETRY
(
-- use 01 as we wish to add the point to the map
2001,
-- SRID for WGS84 longitutde/latitude format
8307,
-- Set the information of the point ( we don't need a Z co-ord )
SDO_POINT_TYPE
(
l_lng,
l_lat,
null
),
null, -- We have no SDO_ELEM_INFO_ARRAY
null -- We have no SDO_ORDINATE_ARRAY
);
-- Return the new spatial object
dbms_output.put_line('sdo_gtype='||n_spatial_object.sdo_gtype);
dbms_output.put_line('first element from sdo_ordinates='||n_spatial_object.sdo_ordinates(1));
RETURN n_spatial_object;
END set_spatial_point;
/
show errors
That works fine.
Let's try it out:
SQL> select set_spatial_point('XXXX') from dual;
ERROR at line 1:
ORA-06531: Reference to uninitialized collection
ORA-06512: at "SCOTT.SET_SPATIAL_POINT", line 38
Again, this is obvious. The error is on line 38:
dbms_output.put_line('first element from sdo_ordinates='||n_spatial_object.sdo_ordinates(1));
That fails (obviously again) since n_spatial_object.sdo_ordinates() is null (like you wrote on line 32.
Let's remove those debugging lines and redefine the function. Then let's try it out. It now works as expected:
SQL> select set_spatial_point('XXXX') from dual;
SET_SPATIAL_POINT('XXXX')(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INF
-------------------------------------------------------------------------------
SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(3.7, 45.3, NULL), NULL, NULL)
1 row selected.

Oracle procedure with default and to_date shows error

I am using 11g
I have table
CREATE TABLE Agency
(
AgencyID int not null PRIMARY KEY,
AgencyName VARCHAR2(30) not null,
AgencyLtrCode VARCHAR2(10) not null,
IsActive VARCHAR2(3) DEFAULT 'yes'NOT NULL,
LastListSentData DATE DEFAULT SYSDATE ,
LetterSendDate DATE DEFAULT SYSDATE ,
CertificationDate DATE DEFAULT SYSDATE ,
CeresNo int,
AgencyAreaID int not null,
CONSTRAINT fk_Agency FOREIGN KEY (AgencyAreaID) REFERENCES AgencyArea(AriaID)
);
I use procedure to insert new records in it
create or replace PROCEDURE insert_AGENCY_Procedure(
AGENCYID IN AGENCY.AGENCYID%TYPE,
AGENCYNAME IN AGENCY.AGENCYNAME%TYPE,
AGENCYLTRCODE IN AGENCY.AGENCYLTRCODE%TYPE,
ISACTIVE IN AGENCY.ISACTIVE%TYPE DEFAULT 'yes',
LASTLISTSENTDATA IN AGENCY.LASTLISTSENTDATA%TYPE DEFAULT SYSDATE,
LETTERSENDDATE IN AGENCY.LETTERSENDDATE%TYPE DEFAULT SYSDATE,
CERTIFICATIONDATE IN AGENCY.CERTIFICATIONDATE%TYPE DEFAULT SYSDATE,
CERESNO IN AGENCY.CERESNO%TYPE,
AGENCYAREAID IN AGENCY.AGENCYAREAID%TYPE)
IS BEGIN
INSERT INTO AGENCY("AGENCYID", "AGENCYNAME","AGENCYLTRCODE","ISACTIVE","LASTLISTSENTDATA","LETTERSENDDATE","CERTIFICATIONDATE","CERESNO","AGENCYAREAID")
VALUES (AGENCYID, AGENCYNAME,AGENCYLTRCODE,ISACTIVE,LASTLISTSENTDATA,LETTERSENDDATE,CERTIFICATIONDATE,CERESNO,AGENCYAREAID);
COMMIT;
END;​​
right now it throw error "Error at line 17: PLS-00103: Encountered the symbol "" "
line 17 had only END; on it
when I submit inserting which looks like
BEGIN
insert_AGENCY_Procedure(9003,'Some Other Church', 'SomOTCh','no',10-10-2011,10/10/2011,10/10/2011,17,2 );
END;
it throws error
ORA-06550: line 2, column 4:
PLS-00306: wrong number or types of arguments in call to 'INSERT_AGENCY_PROCEDURE'
ORA-06550: line 2, column 4:
PL/SQL: Statement ignored
or other insert like
BEGIN
insert_AGENCY_Procedure(9003,'Some Other Church',SomOTCh',DEFAULT,DEFAULT,DEFAULT,DEFAULT,17,2 );
END;
it throws error
ORA-06550: line 2, column 64:
PLS-00103: Encountered the symbol "DEFAULT" when expecting one of the following:
( - + case mod new not null
The question is what is wrong with my procedure? I was trying to resolve this problem but stuck :(
First off, the INSERT_AGENCY_PROCEDURE procedure is defined to take 8 parameters but you are trying to pass in 9 parameters. It appears that you are trying to pass in an AgencyLtrCode but the procedure does not take an AgencyLtrCode as a parameter. You would either have to stop trying to pass in the AgencyLtrCode or you would need to modify the procedure to accept that parameter.
Second, you need to pass dates to the procedure given the declaration. Your actual procedure call will error out because what you are passing in for the date parameters are not dates (and cannot be implicitly converted to dates). Assuming that we eliminate the third parameter (which is what appears to be the AgencyLtrCode discussed above), you would want something like
BEGIN
insert_AGENCY_Procedure(9003,
'Some Other Church',
'no',
to_date('10-10-2011', 'DD-MM-YYYY'),
to_date('10/10/2011', 'DD/MM/YYYY'),
to_date('10/10/2011','DD/MM/YYYY'),
17,
2 );
END;
Third, your procedure is incorrect. The parameters LASTLISTSENTDATA, LETTERSENDDATE, and CERTIFICATIONDATE are defined as dates so you should not call to_date on them. If you do, you force Oracle to implicitly convert the date to a string using the session's NLS_DATE_FORMAT, then convert the string back to a date using the explicit format mask. That will fail if the session's NLS_DATE_FORMAT is not what you expect.
Finally, declaring optional parameters in the middle of a procedure declaration is rarely correct. If you want to use positional binding and you want the ability to omit parameters, the optional parameters need to be at the end of the parameter list. You can define optional parameters in the middle of the parameter list and then use named binds (as DazzaL demonstrates) but that is seldom what you want to force future developers to use.
In your updated procedure, the declaration of the AgencyLtrCode parameter appears to be incorrect
AGENCYLTRCODE IN AGENCYLTRCODE%TYPE
needs to be
AGENCYLTRCODE IN AGENCY.AGENCYLTRCODE%TYPE
You are missing the name of the table.
You're passing ninevalues, but the procedure is only expecting eight. From the table definition you seem to be missingAgencyLtrCode in the procedure.
In the first call you're passing dates as 10-10-2011 or 10/10/2011, which will be evaluated as (different) numbers not dates. You need to at least enclose them in single quotes, but really ought to specify the date mask, as to_date('10/10/2011', 'DD/MM/YYYY') rather than relying on implicit conversions.
In general, if you want to use the defaults, just leave those parameters out, do not pass DEFAULT; that isn't valid in that context. But because you have values to pass after the defaults, you need to name the parameters, i.e.
insert_agency_procedure(agency_id=>9003, ...);
there is no DEFAULT keyword, you just omit the defaults.
in your case you have the defaults in the middle of the API though, so you'd have to use NAMED notation:
begin
insert_agency_procedure(agencyid => 9003,
agencyname => 'Some Other Church',
isactive => 'SomOTCh',
ceresno => 17,
agencyareaid => 2 );
end;
/
or mixed:
begin
insert_agency_procedure(9003, 'Some Other Church',
'SomOTCh',
ceresno => 17,
agencyareaid => 2 );
end;
/
and in the first exmaple you gave:
BEGIN
insert_AGENCY_Procedure(9003,'Some Other Church', 'SomOTCh','no',10-10-2011,10/10/2011,10/10/2011,17,2 );
END;
you cant just type dates like that. Firstly quote them. Secondly always always use a format mask.
BEGIN
insert_AGENCY_Procedure(9003,'Some Other Church', 'SomOTCh','no',
to_date('10-10-2011', 'dd-mm-yyyy'),
to_date('10-10-2011', 'dd-mm-yyyy'),
to_date('10-10-2011', 'dd-mm-yyyy'),17,2 );
END;
I think you need to enclose your date string in single quotes (if you supply a date, considering you have default values for those parameters):
BEGIN
insert_AGENCY_Procedure(9003,'Some Other Church', 'SomOTCh','no','10-10-2011','10/10/2011','10/10/2011',17,2 );
END;

Resources