ORA-00933 Error for to_char formatting PLSQL - sql

I have the following codes:
IF nvl(p_value, 0) >= 0 THEN
l_currency_prefix := 'scc.currency_prefix_pos';
l_currency_suffix := 'scc.currency_suffix_pos';
ELSE
l_currency_prefix := 'scc.currency_prefix_neg';
l_currency_suffix := 'scc.currency_suffix_neg';
END IF;
l_query := 'SELECT nvl('||l_currency_prefix||', '')'
||'trim(to_char('||p_value||
',scc.currency_format
,'||'NLS_NUMERIC_CHARACTERS=' || 'scc.decimal_group_separator'||'))'
||'nvl('||l_currency_suffix||', '')
FROM gss.gss_currency_locale scc
WHERE scc.country_code =' ||p_country_code||
'AND scc.currency_code ='|| p_currency_code||
'AND rownum=1';
and here is the dbms output for l_query:
SELECT nvl(scc.currency_prefix_pos, ')trim(to_char(10000,scc.currency_format
,NLS_NUMERIC_CHARACTERS=scc.decimal_group_separator))nvl(scc.currency_suffix_pos, ')
FROM gss.gss_currency_locale scc
WHERE scc.country_code =USAND scc.currency_code =USDAND rownum=1
However, it keep showing an ORA-00933 errors.
I debug these piece of code for few hours and could not find where is the errors.
Could some one please provide some advice on this?

Now some of the problems are obvious. You need something like this:
l_query := 'SELECT nvl('||l_currency_prefix||',
||'trim(to_char('||p_value||
',scc.currency_format || ')' ||
FROM gss.gss_currency_locale scc
WHERE scc.country_code = ''' ||p_country_code|| '''' ||
' AND scc.currency_code = '''|| p_currency_code|| '''' ||
' AND rownum=1';
(I'm not sure if that is 100 percent correct.)
Usually, when creating queries this way, I use replace() instead of direct substitution. Something like:
l_query := 'select nvl(#currency_prefix, trim(#p_value, #currency_format))
from . . . ';
l_query := replace(l_query, '#currency_prefix', l_currency_prefix);
l_query := replace(l_query, '#p_value', p_value);
. . .
I find that this approach makes it much easier to maintain the code and to see what it is doing.

Related

Oracle APEX 4.2 Custom search in classic report

I am using Oracle APEX 4.2. I want to implement a search function in my classic report. I have a working code that retrieve data and the search function works perfectly. But when I want to use an order by clause inside that code I get "no data found" how can I implement an order by clause into this code so my report will be sorted correctly and the search function will still work correctly.
Here is the working code below that allows you to search the classic report:
declare
a_query varchar2(5000);
this_strin varchar2(50);
begin
a_query := 'select flight_nmbr, sequence_nmbr'||
'from flights '||
'where sequence_nmbr >= 0'||
'and data_version_name = '''||
:P3_DATA_VERSION || '''';
if :P3_SEARCH_NUMBER is not null then
if instr(:P3_SEARCH_NUMBER, '%') > 0 then
this_strin := :P3_SEARCH_NUMBER;
else
this_strin := '%'||:P3_SEARCH_NUMBER||'%';
end if;
a_query := a_query||chr(10)||
' and flight_nmbr like '''|| upper(this_strin) ||'''';
end if;
return a_query;
end;
Here is same piece of code that does says "no data found" when I add the order by clause to the query:
declare
a_query varchar2(5000);
this_strin varchar2(50);
begin
a_query := 'select flight_nmbr, sequence_nmbr'||
'from flights '||
'where sequence_nmbr >= 0'||
'and data_version_name = '''||
'order by sequence_nmbr 1'|| ------------------Order by clause
:P3_DATA_VERSION || '''';
if :P3_SEARCH_NUMBER is not null then
if instr(:P3_SEARCH_NUMBER, '%') > 0 then
this_strin := :P3_SEARCH_NUMBER;
else
this_strin := '%'||:P3_SEARCH_NUMBER||'%';
end if;
a_query := a_query||chr(10)||
' and flight_nmbr like '''|| upper(this_strin) ||'''';
end if;
return a_query;
end;
Obviously, your problem is here:
begin
a_query := 'select flight_nmbr, sequence_nmbr'||
'from flights '||
'where sequence_nmbr >= 0'||
'and data_version_name = '''|| -- double qoute!!!
'order by sequence_nmbr 1'|| ------------------Order by clause
:P3_DATA_VERSION || '''';
Due to that redundant double quote, your resulting query looks like this:
select flight_nmbr, sequence_nmbr
from flights
where sequence_nmbr >= 0
and data_version_name = 'order by sequence_nmbr 1<value of P3_DATA_VERSION item>';
As soon as the table has no value order by sequence_nmbr 1 in the column data_version_name, the query returns no rows.
The second problem you will encounter when you'll fix this one is here:
if :P3_SEARCH_NUMBER is not null then
When this statement will be true, you will get a query where the condition and flight_nmbr like ... stands after the ORDER BY clause.
By the way, I would recommend you write a simple query for the report. Generating SQL dynamically leads to such errors and costs you a performance decrease also.
Not related to your question, but - why don't you switch to interactive report? It offers much more than a classic report, don't you think?
As of your problem: if you look at query that fails, its SELECT looks like this (I've removed single quotes):
and data_version_name = ||
order by sequence_nmbr 1 || ------------------Order by clause
:P3_DATA_VERSION ||
and flight_nmbr like upper(this_strin)
Either you didn't post actual code, or this is generally wrong - I hope you see what is wrong here. ORDER BY should be the last clause. Besides, what's that "1" doing at the end of the ORDER BY?
I'd suggest you to first display contents of the A_QUERY, check whether it works OK (in SQL*Plus, TOAD, SQL Developer or any other tool you use), and - once you're satisfied with it - let it work in Apex.

Not properly closed sql command

I have this code:
def_where:=def_where||' TO_CHAR(date_of_input,''MM'') like '''||'to_char(date_of_input,''MM'')=nvl(:DSP_month,to_char(date_of_input,''MM''))'||'%' ||'to_char(date_of_input,''RRRR'')=nvl(:DSP_year,to_char(date_of_input,''RRRR''))'||'%''';
and i m getting error sql command not properly ended.
def_where suggest, that this is part of dynamically built query, condition of where clause. But produced string makes no sense, it should be something like:
declare
def_where varchar2(32767) := '';
begin
def_where := def_where
|| ' to_char(date_of_input, ''MM'') '
|| ' = nvl(:DSP_month, to_char(date_of_input, ''MM'')) and'
|| ' to_char(date_of_input, ''RRRR'') '
|| ' = nvl(:DSP_year, to_char(date_of_input, ''RRRR''))';
dbms_output.put_line(def_where);
end;
Look what you got from dbms_output, correct this syntax if needed. You could also rewrite your string to get this:
(extract(month from date_of_input) = :DSP_month or :DSP_month is null) and
(extract(year from date_of_input) = :DSP_year or :DSP_year is null)

Error in dynamic SQL query. Missing expression with correct syntax

I have a problem working with a stored procedure on work.
It's a stored procedure which is used by several bigger procedures. The procedure which does the work is called C, and the ones who call it are A and B.
The problem I have is that when I run A, everything goes smoothly, but when I run B, I get a missing expression error, which I don't get when I call A, even tough B and A have the same flow of procedure calls (so, it's kind of a really weird error).
The C procedure has the same code:
procedure C ( LO in varchar2,
EN in varchar2,
CA in array1d,
IA in number,
AR in array2d )
is
CQ varchar2(5);
ET varchar2(2000);
OL varchar2(100);
NE varchar2(100);
TE varchar2(100);
XU varchar2(100);
begin
LO := '05';
TE := 'VAR';
CQ := '''';
OL := CQ || LO || CQ;
TE := CQ || TE || CQ;
NE := CQ || EN || CQ;
ET := 'PAR1 = ' || CA(1) || ',' ||
'PAR2 = ' || CA(2) || ',' ||
'PAR3 = ' || CA(3) || ',' ||
'PAR4 = ' || CA(4) || ',' ||
'PAR5 = ' || CA(5) || ',' ||
'PAR6 = ' || CA(6) || ',' ||
'PAR7 = ' || CA(7) || ',' ||
'PAR8 = ' || CA(8) || ',' ||
'PAR9 = ' || CA(9);
execute immediate 'update table_st set ' || ET || '
where field1 = ' || OL || '
AND field2 = ' || NE || '
AND field3 = ' || TE;
end;
The error I get is missing expression, and it seems to appear on the first line of the execute immediate. After some analysis, I realized the data from the 2d ARRAY is initialized with some empty strings ''.
I am wondering if you could help me to see this error from a new perspective, because as I see it, there seems to be no syntax error to justify the missing expression error I get, but I know I may be wrong.
If further details are needed, let me know.
At a minimum, I'd say the variables LO, CQ haven't been declared, and EN and CA haven't been declared or initialized.
Also, you declared NE as a verchar2 when I think you meant varchar2.
I also agree with Juan's observation that you may want to double check this line:
CQ := q'[']';
Did you mean:
CQ := q'['']';
Honestly not sure, but worth a look.
Oracle should tell you if the procedure compiles, and I think these errors alone will prevent it from doing that. If you don't ever declare the contents of EN and CA, it might still compile but fail when it runs.

PL/SQL invalid cursor error

So I really don't have any idea why my cursor isn't working. The select statement works fine, so I'm not sure why the SQL server is throwing the error. The For loop has an implicit open and close, so that shouldn't be the problem either. Any ideas?
DECLARE
var_lname customer.c_last%TYPE;
var_fname customer.c_first%TYPE;
var_addr customer.c_address%TYPE;
var_phone customer.c_dphone%TYPE;
CURSOR expl_cursor IS SELECT c_last, c_first, c_address, c_dphone from customer;
cust_record expl_cursor%ROWTYPE;
BEGIN
DBMS_OUTPUT.PUT_LINE('ClearWater Traders Mailing List');
FOR cust_record IN expl_cursor
LOOP
FETCH expl_cursor INTO cust_record;
var_lname := cust_record.c_last;
var_fname := cust_record.c_first;
var_addr := cust_record.c_address;
var_phone := cust_record.c_dphone;
DBMS_OUTPUT.PUT_LINE(var_lname || ' ' || var_fname || ' ' ||
var_addr || ' ' || var_phone);
END LOOP;
END;
Here's the error:
ERROR at line 1:
ORA-01001: invalid cur
ORA-06512: at line 15
Ah I solved this. Can't do a FETCH inside a for loop. Since the cursor is incremented automatically.

SQL stmt concatenate(sp*)

I’m dong some SQL work this week and I normally write Java.
I need to add some if's into my SQL like so, but don’t want to do any string concatenation.
This should be an easy one: I just don’t know the SQL syntax
I want to make all those "AND" statements "if" conditions for params I’m passing in
Would I have to do something like this:
IF p_sac IS NOT NULL
THEN
stmt := stmt || ' AND nsns.sac = ''' || p_sac || '''';
END IF;
IF p_value1 IS NOT NULL
THEN
stmt := stmt || ' AND UPPER(value1s.value1) LIKE ''' || UPPER(p_value1) || ''' ';
END IF;
Or is there an alternative to this above?
Basically I've got this:
FUNCTION summarize_item_search_data (p_obj_code IN VARCHAR2, p_value1 IN VARCHAR2,
p_sac IN NUMBER, p_job_type_id IN NUMBER,
p_value4 IN NUMBER)
RETURN sys_refcurvalue2
IS
result_cur sys_refcurvalue2;
BEGIN
OPEN result_cur FOR
SELECT DISTINCT jp.id, jp.row_top.mwslin AS mwslin, jp.obj_code, jp.jobload_year, jp.row_top.fiscal_year AS fiscal_year,
nsns.sac, value1s.value1, nsns.nsn,
DECODE( jp.row_top.nsn_id, NULL, jp.row_top.nomenclature ,nsns.nomenclature) AS nomenclature, jp.row_top.value4 AS value4
FROM scabs sch, jobs JP, master_nsn nsns, master_value1 value1s, TABLE(value1s.group_id) (+) ntab,
groups pgds
WHERE jp.row_top.nsn_id = nsns.id(+) AND nsns.value1_id = value1s.id(+)
-- stmt := stmt || ' AND ''' || p_year || ''' = ntab.fiscal_year(+)';
AND ntab.group_id = pgds.id(+)
AND nsns.sac = p_sac
AND UPPER(value1s.value1) LIKE UPPER(p_value1)
AND UPPER(jp.obj_code) = UPPER(p_obj_code)
AND jp.row_top.value4 <= p_value4
AND jp.row_top.job_type_id =p_job_type_id
RETURN result_cur;
END summarize_item_search_data;
Just put it all into your WHERE clause as conditions:
WHERE
(p_sac IS NULL OR nsns.sac = p_sac) AND
....
If performance suffers greatly then you might want to look into using dynamic SQL, but I would start with the approach above.