oracle view SYS.ALL_TAB_COLUMNS - view

Aloha
Here's my purpose : I need to gather in a view some essential information about my OracleDB. What to do ? To use it in an ETL as a schema ressource I could query to qualify the data I'll translate and certify them.
I'm not logged as SYS. So, here's my view :
CREATE OR REPLACE FORCE VIEW "BRINDAVOINE".FME_SCHEMA_SIGE
AS
SELECT S.TABLE_NAME AS "feature_type",
S.COLUMN_NAME AS "attribute_name",
CASE S.DATA_TYPE
WHEN 'BLOB'
THEN
'fme_buffer'
WHEN 'CHAR'
THEN
CASE
WHEN S.DATA_LENGTH IS NULL THEN 'fme_char(400)'
ELSE 'fme_char(' || S.DATA_LENGTH || ')'
END
WHEN 'DATE'
THEN
'fme_date'
WHEN 'NUMBER'
THEN
CASE
WHEN S.DATA_LENGTH IS NULL
THEN
'fme_decimal(400,'
ELSE
'fme_decimal('
|| S.DATA_LENGTH
|| ','
|| CASE
WHEN S.DATA_PRECISION IS NULL THEN '2)'
ELSE S.DATA_PRECISION || ')'
END
END
WHEN 'VARCHAR2'
THEN
CASE
WHEN S.DATA_LENGTH IS NULL THEN 'fme_char(400)'
ELSE 'fme_char(' || S.DATA_LENGTH || ')'
END
WHEN 'NVARCHAR2'
THEN
CASE
WHEN S.DATA_LENGTH IS NULL THEN 'fme_char(400)'
ELSE 'fme_char(' || S.DATA_LENGTH || ')'
END
ELSE
S.DATA_TYPE
END
AS "attribute_data_type",
'' AS "geometry_type"
FROM SYS.ALL_TAB_COLUMNS S
WHERE S.OWNER = 'A_REIMS'
AND S.TABLE_NAME NOT LIKE '%RELATION'
AND S.TABLE_NAME IN (SELECT NOM
FROM A_DESIGN_REIMS.APICD_COMPOSANT
WHERE NUMERO_MODELE = 1 AND action != 2)
AND NOT REGEXP_LIKE(S.COLUMN_NAME,
'(APIC_.*)|_([STXYLO]|S[GT]|[XY][12])$');
Unfortunately, I have an error message : A bad "ORA-04063: view "BRINDAVOINE.FME_SCHEMA_SIGE" comporte des erreurs" when I attempt to query it. I've tried an ALTER VIEW BRINDAVOINE.FME_SCHEMA_SIGE COMPILE but it didn't seem to change.
Here's my questions : is it ok to create a view from a sys."view" ? If so, why couldn't I create this view ?
Thanks in advance,

You should be able to create a view that queries a SYSTEM view. I was able to compile your view by removing the reference to A_DESIGN_REIMS.APICD_COMPOSANT (which of course is not present in my database).
Check for errors either by using the SQLPlus command "show errors" (immediately after creating the view), or by querying the "user_errors" or "all_errors" views. My guess is that the BRINDAVOINE user is missing a necessary privilege.

Related

In a CASE statement, can you store WHEN subquery result for use in the THEN output?

I have a report outputting the results of a query which was designed to provide links to a webpage:
SELECT
a,
b,
c,
'string' ||
(SELECT sso_code
FROM men_sso
WHERE sso_parm LIKE '%URL_LINK~' || ipp_code || '%'
ORDER BY sso_cred, sso_cret
FETCH FIRST 1 ROWS ONLY
) AS URL
FROM men_ipp
This works well, but I was asked to amend it so that if the records needed to generate the URL were missing (ie. sso_code can't be retrieved), it outputs a warning message instead of the subquery output.
Since there's always going to be a string of a set length (6 characters in this example), my solution was to create a CASE statement which is evaluating the length of the subquery output, and if the answer is greater than 6 characters it returns subquery result itself, otherwise it returns a warning message to the user. This looks like:
SELECT
a,
b,
c,
CASE
WHEN
LENGTH('string' ||
(SELECT sso_code
FROM men_sso
WHERE sso_parm LIKE '%IPP_URL_LINK~' || (ipp_code) || '%'
ORDER BY sso_cred, sso_cret
FETCH FIRST 1 ROWS ONLY)
) > 6
THEN
('string' ||
(SELECT sso_code
FROM men_sso
WHERE sso_parm LIKE '%IPP_URL_LINK~' || (ipp_code) || '%'
ORDER BY sso_cred, sso_cret
FETCH FIRST 1 ROWS ONLY)
ELSE 'warning message'
END AS URL
FROM men_ipp
The statment works fine, however the processing time is nearly doubled because it's having to process the subquery twice. I want to know if there's any way to store the result of the subquery in the WHEN, so it doesn't need to be run a second time in the THEN? eg. as a temporary variable or similar?
I've tried to declare a variable like this:
DECLARE URLLINK NVARCHAR(124);
SET URLLINK = 'string' ||
(SELECT sso_code
FROM men_sso
WHERE sso_parm LIKE '%URL_LINK~' || ipp_code || '%'
ORDER BY sso_cred, sso_cret
FETCH FIRST 1 ROWS ONLY
)
However this causes the query to error saying the it Encountered the symbol "https://evision.dev.uwl.tribalsits.com/urd/sits.urd/run/siw_file_load.sso?" when expecting one of the following: := . ( # % ; not null range default character
You can use NULLIF to make the result null if it is "string" (i.e., you appended nothing to it from your subquery). Then use NVL to convert to the warning message. Something like this:
SELECT
a,
b,
c,
nvl(nullif(
'string' ||
(SELECT sso_code
FROM men_sso
WHERE sso_parm LIKE '%IPP_URL_LINK~' || (ipp_code) || '%'
ORDER BY sso_cred, sso_cret
FETCH FIRST 1 ROWS ONLY),'string'),'warning message')
FROM men_ipp
Use a CTE.
with temp as
(SELECT sso_code
FROM men_sso
WHERE sso_parm LIKE '%IPP_URL_LINK~' || (ipp_code) || '%'
ORDER BY sso_cred, sso_cret
FETCH FIRST 1 ROWS ONLY
)
select a, b, c,
case when sso_code is null then 'warning message'
else 'string' || sso_code
end as url
from men_ipp full outer join temp on 1 = 1;
Use a sub-query:
SELECT a,
b,
c,
CASE
WHEN LENGTH(sso_code) > 6
THEN sso_code
ELSE 'warning message'
END AS URL
FROM (
SELECT a,
b,
c,
'string' ||
( SELECT sso_code
FROM men_sso
WHERE sso_parm LIKE '%IPP_URL_LINK~' || ipp_code || '%'
ORDER BY sso_cred, sso_cret
FETCH FIRST 1 ROWS ONLY ) AS sso_code
FROM men_ipp
)

Oracle function to select multiple rows in a single row not working

I am loading a file into a staging record using Application Engine. when ever there is blank in BU,Deptid etc... I have to capture what all columns are blank and update error text field with those values.
UPDATE SYSADM.PS_VI_EMP_TS SET ERR_TEXT =
SELECT ERROR FROM (SELECT * FROM (
SELECT CASE WHEN BUSINESS_UNIT = ' ' THEN 'BUSINESS_UNIT IS NULL' ELSE ' ' END AS ERROR FROM SYSADM.PS_VI_EMP_TS WHERE USERID='JCOOPER' AND ACTION = 'E' AND PROCESS_INSTANCE = '7852429'
UNION
SELECT CASE WHEN DEPTID = ' ' THEN 'DEPTID IS NULL' ELSE ' ' END AS ERROR FROM SYSADM.PS_VI_EMP_TS WHERE USERID='JCOOPER' AND ACTION = 'E' AND PROCESS_INSTANCE = '9852429'
UNION
SELECT CASE WHEN PROJECT_ID =' ' THEN 'PROJECT_ID IS NULL' ELSE ' ' END AS ERROR FROM SYSADM.PS_VI_EMP_TS WHERE USERID='JCOOPER' AND ACTION = 'E' AND PROCESS_INSTANCE = '9852429'
)) WHERE ERROR <> ' '
WHERE USERID='JCOOPER' AND ACTION = 'E' AND PROCESS_INSTANCE = '9852429'
The above script results as below.
ERROR
BUSINESS_UNIT IS NULL
DEPTID IS NULL
I want the result as below.
ERROR
BUSINESS_UNIT IS NULL,DEPTID IS NULL
I am using ListAgg function but facing errors as below.Any help would be great.
SELECT LISTAGG(BUSINESS_UNIT, ';') WITHIN GROUP(ORDER BY USERID)
FROM SYSADM.PS_VI_EMP_TS WHERE USERID='JCOOPER'
GROUP BY BUSINESS_UNIT
Facing the error:
ORA-00923: FROM keyword not found where expected
00923. 00000 - "FROM keyword not found where expected"
*Cause:
*Action:
Error at Line: 47 Column: 43
You overcomplicated things. You don't need two unions and listagg at all. Simple use concatenation of case... when, write your select like here:
select case business_unit when ' ' then 'BUSINESS_UNIT IS NULL; ' end ||
case deptid when ' ' then 'DEPTID IS NULL; ' end ||
case project_id when ' ' then 'PROJECT_ID IS NULL; ' end as error
from ps_vi_emp_ts
where userid = 'JCOOPER' and action = 'E' and process_instance = '9852429'
demo
If your table has primary key then use it for update. Otherwise you can use merge with rowid. Or do it the way you did it if it worked for you, especially if there is only one row meeting criteria.

How to retrieve recursive information in Oracle Apex?

In my Apex Application there is the opportunity to set filters for creating a chart. A user can choose several systems if he wants to. The systems are created as a checkbox item. The source of the checkbox item is based on a list of values which contains a SQL Query to retrieve all systems out of my database table. Here is the structure of my database table:
CREATE TABLE system_table (
system_id NUMBER(16) NOT NULL,
system_name VARCHAR2(100 CHAR) NOT NULL,
system_table_uebergeordnet_ID NUMBER(16),
CONSTRAINT system_name_unique UNIQUE(system_name),
CONSTRAINT system_table_pk PRIMARY KEY ( system_id ),
CONSTRAINT system_table_uber_id_fk FOREIGN KEY ( system_table_uebergeordnet_ID )
REFERENCES system_table ( system_id ) );
As you can see in the code, the last attribute is a recursive relationship. What I want to have now is the following: If a user selects a system_name and submits the page, the system name and all other systems that are referencing the chosen system should be selected. Therefore I have created a hidden item called System_ID. Before submitting the page I have defined a dynamic action which picks up the id of the chosen system_name. After submitting the page, my chart is created and I am checking for the condition in a where-clause. It looks like that:
where ((instr(':' || upper(:P26_SYSTEMS) || ':', upper(SYSTEM_TABLE.SYSTEM_NAME)) > 0) or (instr(':' || upper(:P26_SYSTEMS_ALL) || ':', upper(SYSTEM_TABLE.SYSTEM_NAME)) > 0) or (SYSTEM_TABLE.SYSTEM_TABLE_UEBERGEORDNET_ID = :P26_SYSTEM_ID))
The query is working so far, but only selects the chosen system_name and not the systems who are referencing the chosen system. I hope I was able to explain the problem and you can understand it. Does anyone of you know what I am doing wrong here?
The following code shows my query:
select COUNT(TRIGGER_TABLE.DATUM_UHRZEIT) as Anzahl_Trigger,
TEST.NUMMER as NUMMER
from BRIDGE_SYSTEM_TRIGGER, SYSTEM_TABLE, TRIGGER_TABLE, FAHRT, TEST, MITARBEITER
where BRIDGE_SYSTEM_TRIGGER.SYSTEM_TABLE_SYSTEM_ID = SYSTEM_TABLE.SYSTEM_ID
and BRIDGE_SYSTEM_TRIGGER.TRIGGER_TABLE_TRIGGER_ID = TRIGGER_TABLE.TRIGGER_ID
and TRIGGER_TABLE.FAHRT_FAHRT_ID = FAHRT.FAHRT_ID
and MITARBEITER.NUMMER = FAHRT.MITARBEITER_NUMMER
and FAHRT.TEST_ID= TEST_ID
and TRIGGER_TABLE.PRIORITAET = 1
and ((instr(':' || upper(:P26_TEST) || ':', upper(TEST.TEST_ID)) > 0) or (instr(':' || upper(:P26_TEST_ALL) || ':', upper(TEST.TEST_ID)) > 0))
and ((instr(':' || upper(:P26_SYSTEMS) || ':',':' || upper(system_table.system_name) ||':') > 0) or (instr(':' || upper(:P26_SYSTEMS_ALL) || ':', upper(SYSTEM_TABLE.SYSTEM_NAME)) > 0) or exists (select child.system_id from system_table child where instr(':' || upper(:P26_SYSTEMS) ||':',':'|| upper(child.system_name) ||':') > 0 and child.system_table_uebergeordnet_id = system_table.system_id))
and ((instr(':' || upper(:P26_COUNTRIES) || ':', upper(FAHRT.LAND)) > 0) or (instr(':' || upper(:P26_COUNTRIES_ALL) || ':', upper(FAHRT.LAND)) > 0))
and ((instr(':' || upper(:P26_FAHRER) || ':', upper(MITARBEITER.QNUMMER)) > 0) or (instr(':' || upper(:P26_FAHRER_ALL) || ':', upper(MITARBEITER.QNUMMER)) > 0))
GROUP BY TEST.NUMMMER
ORDER BY TEST.NUMMER;
The query counts the number of triggers per priority ordered by Testnumbers. The triggers that are meant here have nothing to do with sql triggers! So please don't be confused about that term.
A 'Fahrt' belongs to one 'Test' and a 'Test' can contain several 'Fahrten'. Furthermore each 'Fahrt' contains several triggers. The last four where conditions are the mentioned conditions to retrieve the filterinformation that have been set and only those triggers that met the filter conditions are counted.
A hierarchical data structure can be queried using a hierarchical query. In Oracle you can use something like this (note: not tested):
select ...
from system_table
where instr(':'||upper(:P26_SYSTEMS)||':'
,':'||upper(system_table.system_name)||':') > 0
or system_table.system_id in (
select parent.system_id
from system_table parent
start with instr(':'||upper(:P26_SYSTEMS)||':'
,':'||upper(parent.system_name)||':') > 0
connect by prior parent.system_table_uebergeordnet_id = parent.system_id
)
This hierarchical query starts from the selected system name(s) and walks up the hierarchy to their parents, grandparents, etc. to the top. The resulting set of system IDs is then used to filter the main table.
If you need it to select any children of a selected system, switch the connect by clause, e.g.
select ...
from system_table
where instr(':'||upper(:P26_SYSTEMS)||':'
,':'||upper(system_table.system_name)||':') > 0
or system_table.system_id in (
select parent.system_id
from system_table parent
start with instr(':'||upper(:P26_SYSTEMS)||':'
,':'||upper(parent.system_name)||':') > 0
connect by prior parent.system_id = parent.system_table_uebergeordnet_id
)
On the third hand, if it's not a multi-level hierarchy you can make the query simpler, e.g.
select ...
from system_table
where instr(':'||upper(:P26_SYSTEMS)||':'
,':'||upper(system_table.system_name)||':') > 0
or exists (
select child.system_id
from system_table child
where instr(':'||upper(:P26_SYSTEMS)||':'
,':'||upper(parent.system_name)||':') > 0
and child.system_table_uebergeordnet_id = system_table.system_id
)

oracle apex shuttle saving deselections

I'm using Apex 4.2.4 and Oracle 11g. I have a mailing list application where I'm maintaining multiple mailing lists. A given recipient may belong to one or more lists. I'm using an Apex Shuttle to maintain the lists.
The source of all mailing recipients is in the table: mail_recipient. There are four important fields in mail_recipient:
prim_key
first_name
last_name
email_address
There is another table that stores the selected recipients for a given mailing list: mail_recipient_category: The important fields in mail_recipient_category are:
prim_key
recipient_fkey (this stores the prim_key from the mail_recipient table)
category
merge_check
There are two displayed items on the page. The category drop down list (P31_email_list) and the shuttle (P31_email_list_assignments)
The LOV for P31_email_list_assignments is:
Select last_name || ', ' || first_name || ' -- ' || email_address, prim_key from mail_recipient
order by 1;
The PL/SQL function body for the shuttle source is:
declare
emp_list apex_application_global.vc_arr2;
i number := 1;
begin
for r in (Select mr.last_name || ', ' || mr.first_name || ' -- ' || mr.email_address, mr.prim_key
From mail_recipient mr left outer join
mail_recipient_category mrc
On mr.prim_key = mrc.recipient_fkey
Where mrc.category = :P31_EMAIL_LIST)
loop
emp_list(i) := r.prim_key;
i := i + 1;
end loop;
return APEX_UTIL.TABLE_TO_STRING(emp_list, ':');
end;
There is also a single page process to update the database table mail_recipient_category. The process is executed on submit after computations and validations.
Begin
MERGE INTO MAIL_RECIPIENT_CATEGORY ss
USING (
Select
shuttle.column_value shuttle_st
, db.recipient_fkey db_st
from
table(string_to_coll(:P31_email_list_assignments)) shuttle
left outer join mail_recipient_category db
on shuttle.column_value = db.recipient_fkey
and db.category = :P31_email_list) t
on (ss.recipient_fkey = t.db_st
and ss.category = :P31_email_list
)
when matched
then
update
set
ss.merge_check = ss.merge_check
delete
where
t.shuttle_st is null and ss.category = :P31_email_list
-- t.shuttle_st is null
when not matched
then
insert
(recipient_fkey, category)
values
(t.shuttle_st, :P31_email_list);
end;
The shuttle works fine to load from left to right and save items. The problem I'm having is deselecting items from the right side to the left side of the shuttle. After moving a a mail recipient from the right to the left side, when I press the submit button, the items don't leave the right side of the shuttle and the process doesn't delete the row from the mail_recipient_category table.
Thanks for your help with this.
After working with a very experienced colleague, we determined that the page process was at fault. Specifically, the Delete clause of the Merge statement doesn't seem to work for this shuttle. We ended up adding a separate Delete statement after the the Merge statement in the page process.
I also dropped the mail_recipient_category table and am now using the more meaningful name mail_recipient_list.
The shuttle field name is (p31_email_list_assignments).
The working shuttle LOV Definition code is:
Select last_name || ', ' || first_name || ' -- ' || email_address, prim_key
From mail_recipient
order by 1;
The working shuttle Source code is:
declare
mail_list apex_application_global.vc_arr2;
i number := 1;
begin
for r in (Select mr.last_name || ', ' || mr.first_name || ' -- ' || mr.email_address, mr.prim_key
From mail_recipient mr left join
mail_recipient_list mrl
On mr.prim_key = mrl.recipient_fkey
Where mrl.list = :P31_EMAIL_LIST)
loop
mail_list(i) := r.prim_key;
i := i + 1;
end loop;
return APEX_UTIL.TABLE_TO_STRING(mail_list, ':');
end;
The working After Submit page process code is:
Begin
Merge Into MAIL_RECIPIENT_LIST mrl
Using (
Select
shuttle.column_value shuttle_cv
, db.recipient_fkey db_rfk
From
table(string_to_coll(:P31_email_list_assignments)) shuttle
left outer join mail_recipient_list db
on shuttle.column_value = db.recipient_fkey
and db.list = :P31_email_list) t
On (mrl.recipient_fkey = t.db_rfk
And mrl.list = :p31_email_list
)
When Matched
Then
Update
Set
mrl.merge_check = mrl.merge_check
-- Delete
-- Where
-- t.shuttle_cv is null
When Not Matched
Then
Insert
(recipient_fkey, list)
Values
(t.shuttle_cv, :P31_email_list);
/* The commented-out delete clause of the Merge statement never worked with this shuttle.
The following delete statement will every time this page process is called
*/
Delete from MAIL_RECIPIENT_LIST
Where instr(':' || :P31_email_list_assignments || ':',':' || recipient_fkey || ':') = 0
And list = :P31_email_list;
end;
I hope someone finds this useful.

Cursor giving NO_DATA_FOUND if column with empty value included

I have a cursor defined as
CURSOR all_movie_nominations IS SELECT a.title, a.award_year,n.people_id FROM award a JOIN
nominee n ON
a.award_id = n.award_id
WHERE n.movie_id = (SELECT movie_id FROM movie WHERE movie_name = movieName);
The cursor is being opened and closed right.
Using the cursor in following code as
FETCH all_movie_nominations INTO award_title, award_year,nominee_people_id;
WHILE all_movie_nominations%FOUND LOOP
SELECT given_name, family_name INTO first_name, last_name FROM people WHERE people_id=nominee_people_id;
IF first_name = '' THEN
DBMS_OUTPUT.PUT_LINE('The Movie was nominated for '||award_title||' for the year '||award_year);
ELSE
DBMS_OUTPUT.PUT_LINE(first_name||' '||last_name||' was nominated for '||award_title||' for the year '||award_year);
END IF;
FETCH all_movie_nominations INTO award_title, award_year, nominee_people_id;
END LOOP;
Now the attribute n.people_id in cursor definition. This column contains empty values for some rows.
On executing the above code, I get the correct output but a 'NO_DATA_FOUND` Exception at the end of the output.
If I exclude the n.people_id from the cursor, I do not get any exception.
Any suggestions on what is possibly going wrong?
Unless this is student code about learning to use cursors, you would never code this way in real life. SQL statements inside a loop construct are a red flag. Because you are hammering the database this way with numerous (number of awards) tiny select statements retrieving a single person. Which means the PL/SQL engine has to switch to the SQL engine numerous times, leading to relatively expensive context switches. If you use joins, or in your case outer joins, you can minimize the number of context switches to one.
An example of an alternative (untested of course):
for r in
( select a.title
, a.award_year
, p.given_name
, p.family_name
from award
inner join nominee n on a.award_id = n.award_id
left outer join people p on n.people_id = p.people_id
where n.movie_id = (select movie_id from movie where movie_name = movieName)
)
loop
dbms_output.put_line
( case
when r.given_name is null then
'The Movie'
else
r.given_name || ' ' || r.family_name
end ||
' was nominated for ' || r.title || ' for the year ' || r.award_year
);
end loop;
I am not sure what could be happen, I think that the not_found exception is thrown by the inner select sentence:
IF nominee_people_id is not null THEN
SELECT given_name, family_name INTO first_name, last_name FROM people WHERE
people_id=nominee_people_id;
END IF;
I would try to put a condition that checks nominee_people_id is not null for executing the senetence.
I hope it was useful for you
Redgards
Hi you can opt for exception block for that if you want to ignore IF--END IF BLOCK;
BEGIN
SELECT given_name, family_name INTO first_name, last_name FROM people WHERE people_id=nominee_people_id;
EXCEPTION WHEN NO_DATA_FOUND THEN
dbms_output.put_line('no data found for '||nominee_people_id);
END;

Resources