Update Query not working inside postgresql function but it works fine outside function - sql

I am creating function in postgresql to update table. when I ran single function it works fine but I use same query inside function it wont works.
update house1 SET calendar=
'H'||' '||house_num::text||' '||left(to_char(sdate, 'Mon'),2) ||' to ' || to_char(sdate, 'DD') ||to_char(rdate, 'Mon-DD')
where id=1
Inside function I wrote following query
begin
execute
'UPDATE house1 SET calendar = '
||quote_nullable( 'H')||' '||house_num||' '||left(to_char(sdate, 'Mon'),2) ||' to ' || to_char(sdate, 'DD') ||to_char(rdate, 'Mon-DD')
|| ' WHERE' || 'stage'
'>=' || quote_nullable(0) ;
END
It generates following error
ERROR: column "house_num" does not exist.
Please help me

Why do you use the execute statement in function?
You can use update statement directly in function (When using the execute statement if you need to build dynamic query)
create or replace function function_name()
returns void
language plpgsql
as
$$
begin
update house1 SET calendar=
'H'||' '||house_num::text||' '||left(to_char(sdate, 'Mon'),2) ||' to ' || to_char(sdate, 'DD') ||to_char(rdate, 'Mon-DD')
where stage >= 0;
end;
$$;
select function_name();

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)

PLSQL does not compile when substracting two long variables

I'm writing a pretty basic procedure where I need to substract two long variables and assign the value to the other variable. But the code doesn't compile and I am getting hopeless - why is that?
create or replace PROCEDURE TrendCalculator(p_id Prodeje.product%TYPE)
AS
v_week_last Prodeje.WEEK%TYPE;
v_week_current Prodeje.WEEK%TYPE;
v_year_last Prodeje.YEAR%TYPE;
v_year_current Prodeje.YEAR%TYPE;
v_weekly_sales_last PRODEJE.SALES%TYPE;
v_weekly_sales_current PRODEJE.SALES%TYPE;
v_pomocna PRODEJE.SALES%TYPE;
CURSOR c_data IS SELECT WEEK, YEAR, SALES FROM Prodeje WHERE PRODUCT = p_id ORDER BY YEAR, WEEK ASC;
BEGIN
v_pomocna := 0;
OPEN c_data;
LOOP
FETCH c_data INTO v_week_current, v_year_current, v_weekly_sales_current;
EXIT WHEN c_data%NOTFOUND;
IF (v_weekly_sales_last IS NOT NULL) THEN
DBMS_OUTPUT.PUT_LINE(p_id || ' ' || v_week_current || ' ' || v_year_current || ' ' || v_weekly_sales_current);
v_pomocna := (v_weekly_sales_current - v_weekly_sales_last);
END IF;
v_week_last := v_week_current;
v_year_last := v_year_current;
v_weekly_sales_last := v_weekly_sales_current;
END LOOP;
CLOSE c_data;
END;
The Error messages I'm getting are:
Error(19,9): PL/SQL: Statement ignored
Error(19,95): PLS-00306: wrong number or types of arguments in call to '-'
And PRODEJE.SALES Datatype is LONG.
v_weekly_sales_last is not set to anything. So line 19 evaluates to
v_pomocna := (v_weekly_sales_current - );
Which seems to be the cause of your error.

Using Variables in Nested query for Execute Immediate

This might be a simple query for most of you.
I would like to use a variable in nested query while writing an execute immediate, but somehow it throws an error everytime on the variable in nested query.
create or replace PROCEDURE p_decrement_id(
in_table VARCHAR2,
in_seg_nme VARCHAR2)
AS
version VARCHAR2(5) := 'v1.0';
BEGIN
EXECUTE IMMEDIATE 'UPDATE '|| in_table || '
SET X_VERSION_ID = X_VERSION_ID - 1
where DATE_1 = (SELECT DATE_2 FROM CYCLE_DATES
WHERE SEG_NME = ' ||in_seg_nme||')';
COMMIT;
END p_decrement_id;
for execution I use:
set serveroutput on
call p_decrement_id('TEST_DECREMENT', 'TEST');
Also, I need to put a constant value within the query
i.e.
SELECT DATE_2 FROM CYCLE_DATES
WHERE SEG_NME = ' ||in_seg_nme||'
and indicator = 'Y'
Please guide.
Thank you all in advance
It's better to use USING to bind params to your query
EXECUTE IMMEDIATE 'UPDATE '|| in_table || '
SET X_VERSION_ID = X_VERSION_ID - 1
where DATE_1 = (SELECT DATE_2 FROM CYCLE_DATES
WHERE SEG_NME = :1 and indicator = ''Y'')' using in_seg_nme;
Without USING you may try this (as it's VARCHAR2 you need '):
EXECUTE IMMEDIATE 'UPDATE '|| in_table || '
SET X_VERSION_ID = X_VERSION_ID - 1
where DATE_1 = (SELECT DATE_2 FROM CYCLE_DATES
WHERE SEG_NME = ''' ||in_seg_nme||''' and indicator = ''Y'')';
(Two consequent apostrophies is an escape sequence for apostrophe)

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.