Unable to get user input in PL in sqldeveloper - plsql

I'm trying to get user input in SQLDeveloper in a procedure. But however , I'm getting some error like "missing defines". Please help me to solve this. Thanks in advance.
DECLARE
a NUMBER(5);
BEGIN
a := :a;
DBMS_OUTPUT.PUT_LINE('We took the number as ' || a);
END;
The error looks like this.
Error starting at line : 1 in command -
DECLARE
a NUMBER(5);
BEGIN
a := :a;
DBMS_OUTPUT.PUT_LINE('We took the number as ' || a);
END;
Error report -
Missing defines
We took the number as 15
Although I'm getting the correct answer at bottom, still why this errors?

Please execute the below statement:
DECLARE
a NUMBER(5):=15;
BEGIN
a := a;
DBMS_OUTPUT.PUT_LINE('We took the number as ' || a);
END;

In order to get user input in PLSQL Block, we use &, &givenumber will get the user input at run time.
DECLARE
a NUMBER(5);
BEGIN
a := &givenumber;
DBMS_OUTPUT.PUT_LINE('We took the number as ' || a);
END;

Related

Oracle APEX: Execute immediate on collection

I have the following code:
declare
y pls_integer := 0;
v_msg varchar2(4000);
plsql varchar(4000);
begin
if not apex_collection.collection_exists(p_collection_name=>'P16_COLLECTION') then
wwv_flow.debug('No Apex collection found!');
else
for x in (select * from apex_collections where collection_name = 'P16_COLLECTION' and seq_id > 1 order by seq_id)
loop
y := y+1;
FOR i IN 1..25
LOOP
plsql := 'begin apex_collection.update_member_attribute (p_collection_name=> ''P16_COLLECTION'', p_seq=>' || TO_CHAR(x.seq_id) || ',p_attr_number =>' || TO_CHAR(i) || ',p_attr_value=>wwv_flow.g_f' || TO_CHAR(i, 'FM00') || '(' || TO_CHAR(y) || ')); end;';
wwv_flow.debug(plsql);
EXECUTE IMMEDIATE plsql;
END LOOP;
end loop;
end if;
exception when others then
v_msg := ''||sqlerrm;
wwv_flow.debug('ERR: '||v_msg);
end;
This code is very similar to the one proposed here, but I loop through 25 columns. The issue with Oracle Apex is the max number of chars PL/SQL is allowed to have, so I am unable to just write 25 update_member_attribute - calls.
But instead of a it excecuting I get an error no data found.
I triple checked that the collection P16_COLLECTION exists.
The issue with Oracle Apex is the max number of chars PL/SQL is allowed to have
I'm not sure I understood this statement. It is PL/SQL you use. You declared a local PLSQL variable as VARCHAR2(4000). Why didn't you specify its max allowed size, 32767? Would that help?
Furthermore, saying that you got NO-DATA-FOUND exception: are you sure that this piece of code raised it? Because, there's no SELECT statement in there ... the one you used in a cursor FOR loop can't raise NO-DATA-FOUND; UPDATE either. Therefore, it must be something else, I presume.
Enable DEBUG, run the page and - when you get the error - view debug results and locate the culprit.

PL/SQL accept input with single quotes.

I am trying to use the PL/SQL accept functionality to take in user input. However I want the user input to be able to accept single and or double quotes. The double quotes don't seem to be a problem, however the single quote is a problem. I have my code posted below, but I keep getting errors because it doesn't like the single quote. While I know in a practical situation, the user input would be taken in via a web front end and passed to the database, unfortunately this homework assignment is asking for PL/SQL only. Any help is greatly appreciated, thanks!
Accept p_1 prompt 'Please enter the region name (CHILD_NAME):'
DECLARE
--pragma execption_init
user_input REGION.CHILD_NAME%type := '&p_1';
v_res number :=0;
BEGIN
SYS.DBMS_OUTPUT.PUT_LINE('USER INPUT:');
SYS.DBMS_OUTPUT.PUT_LINE(user_input);
SYS.DBMS_OUTPUT.PUT_LINE('');
SYS.DBMS_OUTPUT.PUT_LINE('MY OUTPUT:');
/* select count(*)
into v_res
from REGION where upper(CHILD_NAME) like upper(user_input);
if v_res = 0 then
SYS.DBMS_OUTPUT.PUT_LINE(user_input ||' is not in the table.');
else
SYS.DBMS_OUTPUT.PUT_LINE('Need to build my logic here.');
end if;
SYS.DBMS_OUTPUT.PUT_LINE('');*/
END;
Use alternative quoting mechanism q:
set serveroutput on
accept p_1 prompt 'Say something: '
declare
v_something varchar2(32767) := q'[&p_1]';
begin
dbms_output.put_line('(v_something = ' || v_something || ')');
end;
/
Example run
SQL> #so52
Say something: 'foo [is] 'bar''
old 2: v_something varchar2(32767) := q'[&p_1]';
new 2: v_something varchar2(32767) := q'['foo [is] 'bar'']';
(v_something = 'foo [is] 'bar'')
PL/SQL procedure successfully completed.
SQL>

Assign value to a field of rowtype where `field name` is a string

I want to assign a value to a rowtype's field but I don't know how to do it.
Suppose that I have a table X inside my database.
Suppose also that I have the following variables
a ( X%ROWTYPE ), representing a row of the table X
b ( VARCHAR2 ), containing a column name of the table X
c ( VARCHAR2 ), containing what I want to store inside a.b
What I want to do : something like a.b := c.
I've come up with something like this :
EXECUTE IMMEDIATE 'SELECT '|| c || ' INTO a.' || b || ' FROM DUAL';
Apparently, this isn't the right way to go. I get a ORA-0095: missing keyword error.
Can anyone help me with this ?
Here is the complete code :
DECLARE
tRow MyTable%ROWTYPE;
col_name VARCHAR(10) := 'Length';
nValue NUMBER(12,4) := 0.001;
dynamic_request VARCHAR(300);
BEGIN
dynamic_request := 'SELECT '|| nValue || ' INTO tRow.' || col_name || ' FROM DUAL';
EXECUTE IMMEDIATE dynamic_request;
END;
Ok, I solved it !
Short answer : Using a global variable does the trick
Answer Development
Let us consider two facts about dynamic PL/SQL blocks (i.e., PL/SQL blocks written as strings, to be executed trough an EXECUTE IMMEDIATE statement)
[1] There is no such thing as variable scope when you create a dynamic PLSQL block. What I mean by that is, if you do something like this :
CREATE OR REPLACE PROCEDURE DynamicVariableAssignment(
theString IN VARCHAR2
)
IS
BEGIN
EXECUTE IMMEDIATE 'BEGIN theString := ''test''; END; ';
END;
it will simply not work because the scope of theString is not transfered to the dynamic PL/SQL block. In other words, the dynamic PL/SQL block doesn't "inherit" of any variable, wherever it is executed.
[2] You might say "OK, no panic, I can give input/output arguments to my dynamic PL/SQL block, right ?". Sure you can, but guess what : you can only give SQL types as in/out ! True PL/SQL types on the other hand, such as a myTable%rowtype, are not accepted as an input for a dynamic PL/SQL block. So the answer of hmmftg won't work either :
-- I've reduced the code to the interesting part
dynamic_request := 'BEGIN :t_row.' || col_name || ':= 0.001; END;';
EXECUTE IMMEDIATE dynamic_request USING IN OUT tRow;
-- (where tRow is of type myTable%ROWTYPE)
since tRow is of MyTable%ROWTYPE, it is not a valid SQL type and is therefore not valid as an input to the dynamic PL/SQL block.
The Solution Who would have thought that global variables would come and save the day ? As we said in [1], we have no reference to any variable outside the dynamic PL/SQL block. BUT we can still access global variables defined in package headers !
Let us assume that I have a package kingPackage in which I define the following :
tempVariable myTable%ROWTYPE;
Then I can do this :
FINAL CODE (body only)
-- Copy tRow into temp variable
kingPackage.tempVariable := tRow;
-- We modify the column of the temp variable
vString := 'BEGIN kingPackage.tempVariable.' || col_val || ' := ' || TO_CHAR(vNumber) ||'; END;';
EXECUTE IMMEDIATE vString;
-- The column value has been updated \o/
tRow := kingPackage.tempVariable;
There you go, fellas !
Have a nice day
try this:
CREATE OR REPLACE PROCEDURE ROW_CHANGER(
tRow IN MyTable%ROWTYPE,
col_name IN VARCHAR,
nValue IN NUMBER)
AS
dynamic_request VARCHAR(300);
BEGIN
dynamic_request := 'BEGIN :t_row.'||COL_NAME ||':= :n_value; END;';
EXECUTE IMMEDIATE dynamic_request
USING IN OUT TROW, IN nValue;
END;
this is because in your EXECUTE IMMEDIATE the tRow MyTable%ROWTYPE is not defined,
so we defined it with using statement.

how would I enter this function into toad to run?

Here is the code
vResult VARCHAR2(200);
BEGIN
fvData:=TRIM(fvData);
IF SUBSTR(fvData,LENGTH(fvData)-1,1)<>'*' THEN
fvData:=fvData||'**';
END IF;
vResult:=SUBSTR(fvData,1,InStr(fvData,'^^') - 1);
fvData:=SUBSTR(fvData,InStr(fvData,'^^') + 3);
RETURN vResult;
END StringExtract;
/
I have tried entering different ways, with fvdata=365 but nothing happens, I have try entering small SQL like
select InStr(367,'^^^^') - 1
from dual;
but I can't figure out how to do this big function.
In an attempt to help you get this working take a look at the following code. I have left out the detail of your function so we don't complicate things but you should be able to just plug that back in.
DECLARE
inputValue VARCHAR2(200) := :inputValue; -- << this bind variable allows you to provide different input each you run the code
FUNCTION stringExtract(fvData varchar2) RETURN varchar2
IS
vResult VARCHAR2(200);
BEGIN
vResult := TRIM(fvData);
RETURN vResult;
END stringExtract;
BEGIN
DBMS_OUTPUT.PUT_LINE(LENGTH(inputValue));
DBMS_OUTPUT.PUT_LINE(LENGTH(stringExtract(inputValue)));
END;
Hopefully you can take that as a template and adapt to get your program running.

Getting 'Invalid Argument' error in PL/SQL block

The following PL/SQL will not execute and simply returns 'Invalid Argument' as an error. I've gone as far as commenting out eavery line one by one and I can vary the error I receive but I cannot get the proc to run as I cannot identify where the error lies and it may well lie in permissions or the executing user but any help will be received gratefully. Here's the proc
DECLARE
ind NUMBER; -- Loop index
h1 NUMBER; -- Data Pump job handle
percent_done NUMBER; -- Percentage of job complete
job_state VARCHAR2(30); -- To keep track of job state
le ku$_LogEntry; -- For WIP and error messages
js ku$_JobStatus; -- The job status from get_status
jd ku$_JobDesc; -- The job description from get_status
sts ku$_Status; -- The status object returned by get_status
BEGIN
h1 := DBMS_DATAPUMP.OPEN('EXPORT','SCHEMA',NULL,'SQL_INSTALLER_01152009_1014','LATEST');
DBMS_DATAPUMP.ADD_FILE(h1,'SQL_INSTALLER_01152009_1014.dmp','ORACLE_SCRIPT_RUNNER_BACKUP',NULL,1);
DBMS_DATAPUMP.ADD_FILE(h1,'SQL_INSTALLER_01152009_1014.log','ORACLE_SCRIPT_RUNNER_BACKUP',NULL,3);
DBMS_DATAPUMP.METADATA_FILTER(h1, 'SCHEMA_LIST','''speccs_web_test''', NULL, NULL);
DBMS_DATAPUMP.START_JOB(h1);
percent_done := 0;
job_state := 'UNDEFINED';
while (job_state != 'COMPLETED') and (job_state != 'STOPPED') loop
dbms_datapump.get_status(
h1,
dbms_datapump.ku$_status_job_error +
dbms_datapump.ku$_status_job_status +
dbms_datapump.ku$_status_wip,
-1,
job_state,
sts);
js := sts.job_status;
if js.percent_done != percent_done then
percent_done := js.percent_done;
end if;
if (bitand(sts.mask,dbms_datapump.ku$_status_wip) != 0) then
le := sts.wip;
else
if (bitand(sts.mask,dbms_datapump.ku$_status_job_error) != 0) then
le := sts.error;
else
le := null;
end if;
end if;
if le is not null then
ind := le.FIRST;
while ind is not null loop
ind := le.NEXT(ind);
end loop;
end if;
end loop;
dbms_datapump.detach(h1);
END;
I found something:
See here: http://petermag.blogspot.com/2008/01/export-datapump-how-to-do-via-plsql.html
You get an invalid argument error error when the dump file already exists.
You can download SQL Developer and use its debugger (it is free).
See here: http://www.oracle.com/technology/software/products/sql/index.html
Thanks there chap. I have continued debugging and have nailed it down to one line..
DBMS_DATAPUMP.METADATA_FILTER(h1, 'SCHEMA_LIST','''speccs_web_test''', NULL, NULL);
This is the one. Comment it out and all is swell. The error is indicating one of these values is not valid and I would hazard a guess it's the odd looking '''speccs_web_test''' but searches seem to indicate this is correct, this is because that parameter is a list and haven can be '(''name'', ''name''); which translates to ('name', 'name') a valid format for an IN list.
I'll probably sort it in a minute or two but you think i'd of nailed it hours ago :)
For this particular problem it is because the schema_name speccs_web_test is not in upper case. SPECCS_WEB_TEST is fine and the proc is now running ;)

Resources