How to check if a trigger is invalid? - oracle

I'm working on databases that have moving tables auto-generated by some obscure tools. By the way, we have to track information changes in the table via some triggers. And, of course, it occurs that some changes in the table structure broke some triggers, by removing a column or changing its type, for example.
So, the question is: Is there a way to query the Oracle metadata to check is some triggers are broken, in order to send a report to the support team?
The user_triggers give all the triggers and tells if they are enable or not, but does not indicate if they are still valid.

SELECT *
FROM ALL_OBJECTS
WHERE OBJECT_NAME = trigger_name
AND OBJECT_TYPE = 'TRIGGER'
AND STATUS <> 'VALID'

Have a look at SYS.OBJ$, specifically the STATUS column.

Related

How to know if a db-link is used somewhere in a DB

I would like to know if it exists an Oracle command to know if a DB-LINK (name: myBDLink) is used somewhere in a DB and how to display the objects (views,materialized views, procedures, functions, ...) which use it.
Could you please help me with that ?
Thanks for your help
Well, you could try to query various system views and see whether any of them contains a string you're looking for. As you want to check the whole database, you'll probably connect as a privileged user and check dba_ views; otherwise, all_ or user_ would do.
For example, to check procedures, functions, packages, ...:
select owner, name, type, line
from dba_source
where owner not in ('SYS', 'SYSTEM')
and lower(text) like '%mydblink%';
To check views, you'll need a function which will search through its LONG datatype column (as you can't use it directly in SQL):
create or replace function f_long(par_view in varchar2, par_String in varchar2)
return varchar2
is
l_text varchar2(32000);
begin
select text
into l_text
from dba_views
where owner not in ('SYS', 'SYSTEM')
and view_name = par_view;
return case when instr(lower(l_text), lower(par_string)) > 0 then 1
else 0
end;
end;
/
and then
select owner, view_name
from dba_views
where f_long(view_name, 'mydblink') = 1;
I excluded SYS and SYSTEM as they should not contain anything of users' stuff. Perhaps you'd want to exclude some more users.
To see some more (re)sources, query the dictionary, e.g.
select table_name, comments
from dictionary;
TABLE_NAME COMMENTS
------------------------------ --------------------------------------------------
USER_CONS_COLUMNS Information about accessible columns in constraint
definitions
ALL_CONS_COLUMNS Information about accessible columns in constraint
definitions
DBA_CONS_COLUMNS Information about accessible columns in constraint
definitions
<snip>
There is no complete answer. How would the database know of code that is outside of the database? It can't. So if you have a sql script, or some application that does not rely on stored procedures to do everything, the database will not know of them.
That said, for dependencies that are in stored procedures in the database, you can try this:
select *
from dba_dependencies
where referenced_link_name is not null
;
To add to the other (correct) answers that have been posted by #Littlefoot and #EdStevens, a quick-and-dirty analysis can also be made against the Automated Workload Repository (AWR).
The benefit of this approach is it will find usages of remote objects from SQL submitted to the database whether that SQL is in DBA_SOURCE or not (e.g., is embedded in an external application).
-- Find any objects referenced across a database link (sort of)
select object_node, object_name, count(distinct sql_id) sql_id_count
from dba_hist_sql_plan
where object_type = 'REMOTE'
group by object_node, object_name
order by object_node, object_name
;
The problem is that AWR data isn't 100% complete. First of all, it's not kept around forever, so a database link last used more than a month (or two months or however long your DBAs keep AWR data for) wouldn't be seen. Second of all, AWR only takes snapshots periodically, say every hour. So it's theoretically possible for a SQL to use a database link and then get aged out of the library cache before the next AWR snapshot.
I think the chance of missing something due to that last bit is small on the systems I work with. But, if you have poorly written applications (i.e., no bind variables) and limited shared pool space, it's something to worry about.

how to use triggers to inherit values from another "parent" record in same table

I feel like this is one of those "if you're careful you can do it" scenarios that Oracle just doesn't want to let me do.
My problem is that I have a single configuration table that I want to enable inheritance via Triggers. Think an Employee table with a SUPERVISOR ID column, and 'inherited' SUPERVISOR NAME that self populates if the ID is changed.
I'd like to do a simple self-lookup to capture a value from another row at time of INS/UPD. But Oracle is rejecting as a mutating trigger error.
My code is essentially:
TRIGGER UPD_CHILD_RECORD
BEFORE INSERT OR UPDATE
ON MYSCHEMA.FAKE_EMPLOYEE
FOR EACH ROW
WHEN (NEW.SUPERVISOR_ID IS NOT NULL)
BEGIN
IF INSERTING OR UPDATING
THEN
:NEW.SUPERVISOR_NAME = (
SELECT MAX(NAME)
FROM MYSCHEMA.FAKE_EMPLOYEE
WHERE EMPLOYEE_ID = :NEW.SUPERVISOR_ID
);
END IF;
END UPD_CHILD_RECORD
;
thanks.
This is a normal behavior. Oracle protects you from inconsistent data that you may get accessing a table which is already being updated.
Imagine this scenario.
You submit two update statements and have a trigger that selects from that same table. Let's assume that the first statement is successfully applied and the data gets changed. Now it's time for the second statement. What output would you expect from the select statement in the trigger? Should it return data as it was before the first update, or should it include the changes made? You probably think that Oracle should return the new data. But first, Oracle does not really know your intentions, and second, that would mean that your query is dependent on row order, which contradicts the relational algebra.
The solution for your problem is quite simple. You do not need the SUPERVISOR_NAME column at all. To get supervisor's name, simply join the table with itself and get the desired result, something like:
select t1.ID, t1.SUPERVISOR_ID, t2.NAME from FAKE_EMPLOYEE t1
left join FAKE_EMPLOYEE t2 on t1.SUPERVISOR_ID = t2.ID;

How to retrieve body of "verify_function" Oracle 11g

I am auditing an Oracle BD and I need to know the password policy assigned to this Database.
One way I thought to do it is retrieving the body of verify_function that is assigned to the profiles.
How can I list the body of these "verify_function"? Such as the body of utlpwdmg.sql and ora12c_strong_verify_function etc.
Thx!
As I see the problem from the comments you can't find the function "ORA_COMPLEXITY_CHECK" which is an oracle standart function. The code might be obtained under
{ORACLE_HOME}/rdbms/admin/catpvf.sql
And it could be that the catpvf.sql script wasn't executed against the instance you're on.
In general, here is the script to get the ddl of an object withour specifying it's type(might take longer time to execute).
select owner, object_name, object_type, dbms_metadata.get_ddl(object_type, object_name)
from dba_objects
where object_name = 'CFL_BITAND';
The same way you'd get the DDL for any object in the database -- dbms_metadata.get_ddl. There's nothing magic about the particular function you are after. It's just another function defined in the database.

how can i avoid this error with a trigger i've made it but the DBMS lost it?

there
I've made a trigger that automatically insert a random password of 5 char and num
to any new hired police man
CREATE OR REPLACE TRIGGER POLICE_NO_TRIGG_11111
BEFORE INSERT ON police
FOR EACH ROW
BEGIN
SELECT dbms_random.string('x', 5)
INTO :new.password
FROM dual;
END;
trigger created
then, i went to the form bulider, unfortunatly, unable to insert, see pic
I went back to the sql command, this is what happened
see pic
any help please!
see this for disc police table for further info
It seems like your trigger is invalid. The trigger code seems fine to me, without knowing the table definition.
You probably find some information when executing
select * from user_errors where type = 'TRIGGER' and name = 'POLICE_NO_TRIGG_11111';
If this doesn't help, maybe you find further information here.

Sequences (using as ID) issue in Oracle SQL Developer

I am using sequences to create IDs, so while executing insert stored procedure it will create unique value for ID. But after some time it is losing the definition for the sequence.
Not sure why this is happening again and again and how to solve the problem?
I am using Oracle SQL Developer and in the edit table property there is 'Identity Column' setting. See below:
Next step is setting up trigger and sequence:
It was working fine for some time until this property defaulted. Now it is not there anymore:
Still have this trigger and sequence object in the schema and able to setup again but it will break later.
How to avoid this problem in future?
I think it is just a bug/limitation in your client software, Oracle SQL Developer. The "Identity Column" tab is a handy way to create the corresponding sequence and trigger but it doesn't seem to recognise existing elements. I've just verified my own system and that's exactly what happens.
It makes sense, because adding a new sequence and trigger is a pretty straightforward task (all you need is a template) but displaying current sequence is hard given that a trigger can implement any conceivable logic. Surely it could be done but the cost-benefit ratio probably left things this way.
In short, your app is not broken so nothing needs to be fixed on your side.
This is what I received from IT support regarding the issue:
A few possibilities that might cause this:
1 - Another user with limited privileges might be editing the table using SQL Developer. In this case, if this user's privilege is not enough to obtain the sequence and/or trigger information from the database, the tool might leave the fields blank and disable it when table changes are saved.
2 - The objects are being changed or removed outside of SQL Developer, causing it to lose the information. In my tests I noticed that dropping the trigger and recreating it with the same name caused the identity property information to be lost on SQL Developer.
Even being the trigger enabled, and working for inserts it could not retrieve the information.
Then, if I run an alter trigger to enable it (even tough dba_trigger is reporting it as already enabled), SQL Developer will list the information again:
ALTER TRIGGER "AWS"."TABLE1_TRG" ENABLE;
So it looks like there are some issues with the SQL Developer, that is causing this behavior.
Next time it happen, please check if the trigger still exist on the database and is enabled with the query below:
select owner, trigger_name, TRIGGER_TYPE, TRIGGERING_EVENT, TABLE_OWNER, TABLE_NAME, STATUS
from dba_triggers
where trigger_name = 'ENTER_YOUR_TRG_NAME'; --Just change the trigger name in WHERE

Resources