Oracle Apex Flash Chart not displaying label - oracle

I am building stacked column 3d Flash chart in Oracle Apex. it is based on the PL/SQL returning SQL query. PL/sql is required to capture all types of properties and count number of instances in database connected to those properties. The code is :
DECLARE
l_qry VARCHAR2(32767);
v_id NUMBER;
v_resort VARCHAR2(80);
BEGIN
l_qry := 'SELECT ''fp=&APP_ID.:802::app_session::::P5_SEARCH_MONTH:''||TO_CHAR(E.ENQUIRED_DATE,''MON-YY'')||'':'' link,';
l_qry := l_qry || ''' ''||TO_CHAR(E.ENQUIRED_DATE,''MON-YY'')||'':'' label,';
--Loop through the resorts and add a sum(decode...) column with column alias
FOR r1 IN (SELECT DISTINCT a.resort_id FROM enquiry a, resort b where a.resort_id IS NOT NULL and a.resort_id = b.id and b.active =1)
LOOP
select name into v_resort
from resort
where id = r1.resort_id;
What happens now PLSQL is loping through all resorts and counts them. this solution does work to certain degree however after value returned I want to have label with name of resort taken from v_resort. It is where main difficulty is
l_qry := l_qry || 'sum(decode(resort_id,''' || r1.resort_id ||''',1,0)) test,';
l_qry := l_qry || 'sum(decode(resort_id,''' || r1.resort_id ||''',1,0)) '|| v_resort||',';
First line will display 'test' label when you hover over the columns just fine. However the the second one with '|| v_resort ||' will cause issue with not displaying back any results... it is not giving #no_data_found# message but just blank field..
The rest of the code :
END LOOP;
--Trim off trailing comma
l_qry := rtrim(l_qry, ',');
--Append the rest of the query
l_qry := l_qry || ' from ENQUIRY E,resort r
where
e.enquiry_type=''AVAILR''
and e.enquiry_channel like '''||:P5_CHANNEL||'''
and trunc(e.created) >= '''||:P5_DATE_FROM||'''
and trunc(e.created) <= '''||:P5_DATE_TO||'''
and e.ENQUIRED_DATE > '''||:P5_DATE_FROM||'''
and ((NVL(:P5_AVAILABLE,''A'')=''A'') or ('''||:P5_AVAILABLE||'''=AVAILABLE))
and e.resort_id = r.id
and ((resort_id = '''||:P6_RESORT||''') or ('''||:P6_RESORT||''' like ''0''))
group by To_Char(ENQUIRED_DATE,''MON-YY''),TO_CHAR(ENQUIRED_DATE,''YYMM'')
Order By TO_CHAR(ENQUIRED_DATE,''YYMM'')';
return(l_qry);
END;
I tired '|| v_resort ||' , '''||v_resort||''' . Any other ideas how to create value of label to be taken from v_resort which holds resort name ?

Try "'||v_resort||'"
You have to use a quoted identifier since v_resort can be any string and there are many rules for unquoted names.

Related

Oracle pl/sql Array

let's see if somebody can help me, I need to delete rows from different tables and I did think to do it using an array so i wrote this :
DECLARE
TYPE mytype_a IS TABLE OF VARCHAR2(32) INDEX BY BINARY_INTEGER;
mytype mytype_a;
BEGIN
mytype(mytype.count + 1) := 'MYTABLE';
FOR i IN 1 .. mytype.count
LOOP
DELETE mytype(i) WHERE valid = 'N';
END LOOP;
END;
Trying to run this piece of code using sqldeveloper I get the ORA-00933 command not properly ended, if I put directly the table name it works, what am I doing wrong?
Thank you.
Thank you very much guys, it works perfectly.
This is not the correct approach. You have to use Dynamic SQL for this -
DECLARE
type mytype_a is table of varchar2(32) index by binary_integer;
mytype mytype_a;
stmt varchar(500) := NULL;
BEGIN
mytype (mytype.count + 1) := 'MYTABLE';
for i in 1..mytype.count loop
stmt := 'DELETE FROM ' || mytype(i) || ' where valid =''N''';
EXECUTE IMMEDIATE stmt;
end loop;
END;
You would need to use dynamic SQL, concatenating the table name from the collection into the statement, inside your loop:
execute immediate 'DELETE FROM ' || mytype(i) || ' where valid = ''N''';
Or you can put the statement into a variable so you can display it for debugging purposes, and then execute that, optionally with a bind variable for the valid value:
stmt := 'DELETE FROM ' || mytype(i) || ' where valid = :valid';
dbms_output.put_line(stmt);
execute immediate stmt using 'N';
dbms_output.put_line('Deleted ' || sql%rowcount || ' row(s)');
... which I've made also display how many rows were deleted from each table. Note though that you shoudln't rely on the caller being able to see anything printed with dbms_output - it's up to the client whether it shows it.
The whole anonymous block would then be:
DECLARE
type mytype_a is table of varchar2(32) index by binary_integer;
mytype mytype_a;
stmt varchar2(4000);
BEGIN
mytype (mytype.count + 1) := 'MYTABLE';
for i in 1..mytype.count loop
stmt := 'DELETE FROM ' || mytype(i) || ' where valid = :valid';
dbms_output.put_line(stmt);
execute immediate stmt using 'N';
dbms_output.put_line('Deleted ' || sql%rowcount || ' row(s)');
end loop;
END;
/
You could use a built-in collection type to simplify it even further.
db<>fiddle showing some options.
Hopefully this doesn't apply, but if you might have any tables with quoted identifiers then you would need to add quotes in the dynamic statement, e.g.:
stmt := 'DELETE FROM "' || mytype(i) || '" where valid = :valid';
... and make sure the table name values in your collection exactly match the names as they appear in the data dictionary (user_tables.table_name).

Search string to match Data inside of all existing columns and rows from Views in Oracle SQL

The code below is looking for a string to match a column name. However I would like to search for a string to match Data (meaning, search on each existing column and row from all views - not column names). I want the results to show me all Views Names that contain that string on their Data. Hope this makes sense.
begin
dbms_output.put_line('Owner View name');
dbms_output.put_line('------------------------------ -------------------------------');
for r in (
select v.owner, v.view_name, v.text
from all_views v
where v.owner <> 'SYS'
)
loop
if lower(r.text) like '%my_String%' then
dbms_output.put_line(rpad(r.owner,31) || r.view_name);
end if;
end loop;
end;
I suggest you at least review some of the Oracle documentation. Your statement "Oracle SQL... i am using Oracle SQL Developer" indicates a lack of understanding. So lets clear some of that up. You are actually using 3 separate software tools:
Oracle SQL - all access to data being stored in your Oracle database.
Oracle Pl/SQL - the programming language, which tightly integrates with but is still separate from SQL. This is the language in which your script is written.
Oracle SQL Developer - an IDE within which you develop, run, etc run your Pl/SQL scripts and/or SQL statements.
Now as for your script. The syntax is fine and it will run, successfully retrieving all non sys owned views and printing the names of those containing the specified search string. However, as it currently stands it'll never find a match. Your match statement attempts to match a lower case string to a string that contains the character 'S' (upper case). There will never be a match. Also, keep in mind that within LIKE the underscore (_) is a single character wild card. You may need to escape it as "like '%my_ ...'". With these in mind we come to:
REVISED
The requirement to actually find the string in view columns completely changes things from your original query. Although the title does suggest that was actually the initial desire. What you want to accomplish is much more complex and cannot be done in SQL alone; it requires PL/SQL or an external language code. The reason is that you need run select but you don't know against what nor what columns nor even how many columns area needed. For that you need to identify the view, isolate the viable columns and generate the appropriate SQL dynamically then actually execute that sql and check the results.
Two approaches come to mind: Parse the view to extract the columns (something I would even consider doing in PL/SQL) or join ALL_VIEWS with ALL_TAB_COLUMNS (All table columns). That we'll do. The majority of the code will be constructing the SQL and the necessary error handling dynamic SQL essentially forces on you. I've created this a a procedure with 2 parameters: the target string, and the schema.
create or replace procedure find_string_in_view(
schema_name_in varchar2
, target_string_in varchar2
)
is
--- set up components for eventual execution
k_new_line constant varchar2(2) := chr(10);
k_base_statement constant varchar2(50) :=
q'!select count(*) from <view_name> where 1=1 and !' || k_new_line;
k_where_statement constant varchar2(50) :=
q'! <column_name> like '%<target>%' !' || k_new_line;
k_limit_statement constant varchar2(20) :=
' ) and rownum < 2';
k_max_allowed_errors constant integer := 3;
--- cursor for views and column names
cursor c_view_columns is
(select av.owner,av.view_name , atc.column_name
, lead(atc.column_name) over (partition by av.view_name order by atc.column_id) next_col
, lag(atc.column_name) over (partition by av.view_name order by atc.column_id) prev_col
from all_views av
join all_tab_columns atc
on ( atc.owner = av.owner
and atc.table_name = av.view_name
)
where av.owner = upper(schema_name_in)
and atc.data_type in
('CHAR', 'NCHAR', 'VARCHAR2','NVARCHAR2','VARCHAR','NVARCHAR')
) ;
--- local variables
m_current_view varchar2(61);
m_sql_errors integer := 0;
m_where_connector varchar(2);
m_sql_statement varchar2(4000);
-- local helper function
function view_has_string
return boolean
is
l_item_count integer := 0;
begin
execute immediate m_sql_statement into l_item_count;
return (l_item_count > 0);
exception
when others then
dbms_output.put_line(rpad('-',61,'-') || k_new_line);
dbms_output.put_line('Error processing:: ' || m_current_view);
dbms_output.put_line('Statement::' || k_new_line || m_sql_statement);
dbms_output.put_line(sqlerrm);
m_sql_errors := m_sql_errors + 1;
if m_sql_errors >= k_max_allowed_errors
then
raise_application_error(-20199,'Maximun errors allowed reach. Terminating');
end if;
return false;
end view_has_string;
begin -- MAIN --
dbms_output.put_line('Owner View name');
dbms_output.put_line('------------------------------ -------------------------------');
for rec in c_view_columns
loop
if rec.prev_col is null
then
m_current_view := rec.owner || '.' || rec.view_name;
m_sql_statement := replace(k_base_statement,'<view_name>',m_current_view);
m_where_connector := ' (';
end if;
m_sql_statement := m_sql_statement || m_where_connector
|| replace(k_where_statement,'<column_name>',rec.column_name);
m_where_connector := 'or' ;
if rec.next_col is null
then
m_sql_statement := replace(m_sql_statement,'<target>',target_string_in);
m_sql_statement := m_sql_statement || k_limit_statement;
if view_has_string
then
dbms_output.put_line(rpad(rec.owner,31) || rec.view_name);
end if;
end if;
end loop;
end find_string_in_view;
select v.owner, v.view_name, v.text
from all_views v
where v.owner <> 'SYS' and lower(v.text) like '%my_String%'
one SQL do this?

Error in pl/sql block has me stuck - Number and/or types of columns in a query does not match

Not quite sure what I am doing wrong here, went over the code a few times tonight and I think I need a fresh set of eyes. I keep getting an error that states:
*Cause: Number and/or types of columns in a query does not match declared
return type of a result set variable, or declared types of two Result
Set variables do not match.
*Action: Change the program statement or declaration. Verify what query the variable
actually refers to during execution.
DECLARE
cv_prod SYS_REFCURSOR;
rec_payment dd_payment%ROWTYPE;
TYPE pay2 IS RECORD (
pledge_id dd_pledge.idpledge%TYPE,
amount NUMBER(8,2)
);
rec_payment2 pay2;
lv_donor_id dd_donor.iddonor%TYPE := 303;
lv_indicator_value CHAR(1) := 'd';
BEGIN
IF lv_indicator_value = 'd' THEN
OPEN cv_prod FOR
SELECT idpledge, payamt, paydate, paymethod
FROM dd_pledge inner join dd_payment USING (idpledge)
WHERE iddonor = lv_donor_id
ORDER BY idpledge, paydate;
LOOP
FETCH cv_prod INTO rec_payment;
EXIT WHEB cv_prod%NOTFOUND;
dbms_output.put_line(rec_payment.idpledge || ' ' || rec_payment.payamt || ' ' || rec_payment.paydate || ' ' || rec_payment.paymethod);
END LOOP;
ELSIF Lv_Indicator_Value = 's' THEN
OPEN cv_Prod FOR
SELECT idpledge, payamt, paydate, paymethod
FROM dd_pledge INNER JOIN dd_payment USING (idpledge)
WHERE iddonor = lv_donor_id
GROUP BY idpledge;
LOOP
FETCH cv_prod INTO rec_payment2;
EXIT WHEN cv_prod%NOTFOUND;
dbms_output.put_line(rec_payment2.pledge_id || ' ' || rec_payment2.amount);
END LOOP;
END IF;
END;
You're collecting the fields selected by your query into a record which doesn't have the same number and type of fields of your query.
For example, in your second cursor you're selecting the fields idpledge, payamt, paydate, paymethod:
OPEN cv_prod FOR
SELECT idpledge, payamt, paydate, paymethod
FROM dd_pledge INNER JOIN dd_payment USING (idpledge)
WHERE iddonor = lv_donor_id
GROUP BY idpledge;
And you're trying to put them into the rec_payment2 record:
FETCH cv_prod INTO rec_payment2;
But the type of this record is pay2, which is a record with only two fields:
TYPE pay2 IS RECORD (
pledge_id dd_pledge.idpledge%TYPE,
amount NUMBER(8,2)
);

If condition in PL/SQL script with cursor and loop

I would like to ask for some help or advice in this particular case.
I have table called "Teams". The table contains 3 columns - Issue, Responsible_team and More_Info (all varchar2).
I have a PL/SQL script with cursor and loop for selecting as many teams as issue description you type (some random word you think it might help you find the responsible team). This part works great for me.
But I do not know how to compile the IF condition in there. If no team is found according to typed word description, I would like to get some basic output dbms_output.put_line('Responsible team is not found').
There are 2 ways how I wrote the script. Classic loop and while loop.
I would be happy for any advice.
1.script
set verify off
DECLARE
v_issue teams.issue%type; --variable for issue column from teams table
v_respteam teams.responsible_team%type; --variable for responsible_team column from teams table
v_info teams.more_info%type; --variable for more_info column from teams table
--cursor declaration
CURSOR c_respteam
RETURN teams%ROWTYPE
IS
SELECT issue, responsible_team, more_info
FROM teams
WHERE lower(issue) like '%&Describe_Issue%';
BEGIN
OPEN c_respteam;
LOOP
FETCH c_respteam into v_issue, v_respteam, v_info;
EXIT when c_respteam%NOTFOUND;
dbms_output.put_line('Responsible team is '|| v_respteam || ' --> ' || v_info);
END LOOP;
CLOSE c_respteam;
end;
/
2.script
-- cursor with while loop
set verify off
DECLARE
v_issue teams.issue%type; --variable for issue column from teams table
v_respteam teams.responsible_team%type; --variable for responsible_team column from teams table
v_info teams.more_info%type; --variable for more_info column from teams table
CURSOR c_respteam
RETURN teams%ROWTYPE IS
SELECT issue, responsible_team, more_info
FROM teams
WHERE lower(issue) like '%&Describe_Issue%';
BEGIN
OPEN c_respteam;
FETCH c_respteam INTO v_issue, v_respteam, v_info;
WHILE c_respteam%FOUND
LOOP
dbms_output.put_line('Responsible team is '|| v_respteam || ' --> ' || v_info);
FETCH c_respteam INTO v_issue, v_respteam, v_info;
END LOOP;
CLOSE c_respteam;
END;
/
You could rewrite to:
declare
l_found boolean :=false;
cursor c_respteam is
select issue
,responsible_team
,more_info
from teams
where lower(issue) like '%&Describe_Issue%';
begin
for r in c_respteam
loop
l_found := true;
dbms_output.put_line('Responsible team is ' || r.responsible_team || ' --> ' || r.more_info);
end loop;
if not l_found
then
dbms_output.put_line('No records found');
end if;
end;
/
You need to have a counter variable [ETA: ooh, I like Rene's boolean variable idea instead; either way, you need an extra variable!] to work out if any rows were returned or not. I'm not sure why you're using an explicit cursor fetch, rather than using the cursor-for-loop? Cursor-for-loops are not only easier to write, read and maintain, but Oracle have put some behind-the-scenes optimisation in, to aid performance.
Of course, depending on what you're actually doing with the data returned by your cursor (dbms_output.put_line being something that you should never have in your production code), it's debatable that you would need to loop through a cursor at all.
Anyway, with that said, here's an example demonstrating how I would handle your requirement to check for no rows returned by the cursor:
declare
cursor cur (p_val varchar2)
is
select dummy
from dual
where dummy like '%'||p_val||'%';
v_counter integer := 0;
begin
for rec in cur('Y')
loop
dbms_output.put_line('value of dummy = '||rec.dummy);
v_counter := v_counter + 1;
end loop;
if v_counter = 0 then
dbms_output.put_line('no rows returned');
end if;
end;
/
no rows returned
declare
cursor cur (p_val varchar2)
is
select dummy
from dual
where dummy like '%'||p_val||'%';
v_counter integer := 0;
begin
for rec in cur('X')
loop
dbms_output.put_line('value of dummy = '||rec.dummy);
v_counter := v_counter + 1;
end loop;
if v_counter = 0 then
dbms_output.put_line('no rows returned');
end if;
end;
/
value of dummy = X
To expand on what I said in my comment below, it sounds like you just need a single sql statement, rather than using PL/SQL and relying on dbms_output.
Eg., say you have the following statement:
select lvl
from (select 'X'||level lvl from dual connect by level <= 10)
where lvl like '%&val%';
with &val blank, you get:
LVL
-----------------------------------------
X1
X2
X3
X4
X5
X6
X7
X8
X9
X10
With &val = 2 you get:
LVL
-----------------------------------------
X2
With &val = 100 you get:
no rows selected.

Searching and replacing brackets in a string in Oracle 10G

I am currently developing a function that is meant to execute dynamically created SQL statements. This is done by concatenating the columns and fetching them via cursors. The problem is that when there is a function with a comma between its arguments, the concat concatenates the contents of the functions inclusive.
Is it possible to skip contents of every bracket found in a string using REGEXP_SUBTR or REGEXP_REPLACE?
Many thanks in advance for your prompt and kind suggestions.
-- strips out the select list
src_str := REGEXP_SUBSTR(v_sql, 'SELECT ([[:graph:]]+\ ?){1,1000000}/?');
-- Replace the commas in the select list with the concat symbol for concatenation
rep_str := REGEXP_REPLACE(src_str, ', ', p_dot);
-- Replace the select list with the replace string
v_query := REPLACE(v_sql, src_str, rep_str);
v_sql := select a, b, to_char(sysdate, 'dd/mm/yyyy') from demo;
p_dot := '||'',''||';
currently, it returns:
select a || ',' || b || ',' || to_char(sysdate || ',' || 'dd/mm/yyyy') from demo
but should return something like:
select a || ',' || b || ',' || to_char(sysdate, 'dd/mm/yyyy') from demo
Many thanks Rene, your query worked but I have one more question and here it is
for i in 1 .. p_arglist.count
loop
-- Search for : in the query
src_sym := REGEXP_SUBSTR(v_query, ':[[:graph:]]+\ ?', i,i);
-- Replace the : with each value of p_arglist passed
v_querymult := REGEXP_REPLACE(v_query, src_sym , p_arglist(i),i,i);
end loop;
return v_query;
where p_arglist is a varchar2 varray
p_arglist := ('demo#demo.com','2001')
v_query := 'SELECT A, B, C FROM DEMO WHERE USERID = :USERID AND YEAR = :YEAR';
Currently, it returns
v_query := SELECT A, B, C FROM DEMO WHERE USERID = :USERID AND YEAR = 2001
and skips the first in the list which is the userid.
many thanks for your anticipated help
Have you thought about using DBMS_SQL, that should parse the SQL and allow you to bind variables.
See these links for further reading
Oracle Docs
Ask Tom Example
something like this should do if I understood your requirement correctly:
-- multiple replacements to accomodate for functions with more
-- than two parameters (and accordingly more than one comma)
src_str := regexp_replace(src_str, '(\([^)]+),', '\1##comma-in-function##');
src_str := regexp_replace(src_str, '(\([^)]+),', '\1##comma-in-function##');
src_str := regexp_replace(src_str, '(\([^)]+),', '\1##comma-in-function##');
-- replace the left-over commas
src_str := replace(src_str, ', ', p_dot);
-- turn commas within function call back to commas:
src_str := replace(src_str, '##comma-in-function##', ',');

Resources