Oracle query to get latest table or stored procedure schema change? - oracle

I'm trying to write a query to get the latest schema changes to a table or stored procedure on Oracle.
This is how to do this on Sybase:
select top 10 name from sysobjects where type = 'U' order by crdate desc
(I accept that this is built on created date and not modified date - I'd appreciate anyone who can show me how the modified date works in Sybase for tables but what I'm looking for is Oracle schema change date right now).
My question is: What is the Oracle query to get latest table or stored procedure schema change?

select * from
(SELECT * FROM user_objects ORDER BY last_ddl_time DESC)
where rownum <= 10;
user_objects contains all the objects owned by the current user (= current schema objects)
all_objects contains all the objects on which the user has any privileges
dba_objects contains all the DB objects (requires some special privileges to access).
all_ and dba_ have the additional column owner
3rd party edit
You may want to read does-rebuilding-an-index-update-the-last-ddl-time ...
From ROWNUM Pseudocolumn
For each row returned by a query, the ROWNUM pseudocolumn returns a
number indicating the order in which Oracle selects the row from a
table or set of joined rows. The first row selected has a ROWNUM of 1,
the second has 2, and so on.
You can use ROWNUM to limit the number of rows returned by a query,...

If you want to be specific about the table or procedure, you can limit like below
with 11g database
select * from
(SELECT * FROM user_objects where OBJECT_TYPE in ('TABLE','PROCEDURE') ORDER BY last_ddl_time DESC)
where rownum <= 10;
The above will give the latest changed objects either in table or procedure.
whereas in 12c database no need to use subquery
SELECT * FROM user_objects
where OBJECT_TYPE in ('TABLE','PROCEDURE')
ORDER BY last_ddl_time DESC
FETCH FIRST 10 ROWS ONLY;

Related

Query to check the full schema scan for tables in Oracle DB

Hi I have a requirement to scan through the schema and identify the tables which are redundant (candidate for dropping) ,so i did a select in DBA_Dependencies to check whether the tables are being used in any of the DB object types like (Procedure, package body, views, Materialized views....) i was able to find some tables and excluded the tables ,since i also need to capture the total counts, when the table was last loaded/used is there a automated way to select only selected tables (not found in dependencies list) and capture the counts and also when it was used/loaded
Difficulty - so many tables 500+
i have used the below query
Query 1
select table_name,
to_number(extractvalue(xmltype(dbms_xmlgen.getxml('select count(*) c from '||owner||'.'||table_name)),'/ROWSET/ROW/C')) as count
from all_tables
where owner = 'SCHEMA_NAME'
Query 2
select owner, table_name, num_rows, sample_size, last_analyzed from all_tables;
Query 1 Result
Filter Table_name=CUST_ORDER
OWNER TABLE_NAME COUNT SAMPLE_SIZE LAST_ANALYZED
ABCD CUST_ORDER 1083 1023 01.01.2020
Query 2 Result
Filter Table_name=CUST_ORDER
OWNER TABLE_NAME NUM_ROWS SAMPLE_SIZE LAST_ANALYZED
ABCD CUST_ORDER 1023 1023 01.01.2020
Question
Query 1 - Results not matching when compared with query 2 ,since the same table and filter is applied
in both the queries and why the results are not matching ?
but when i randomly checked other filter it is matching , does any one know the reason ?
Upon further testing i encountered an error ,what does this error signify permissions ?
ORA-29913: error in executing ODCIEXTTABLEOPEN callout
ORA-29400: data cartridge error
KUP-04040: file **-**.csv in ****_***_***_***** not found
29913. 00000 - "error in executing %s callout"
*Cause: The execution of the specified callout caused an error.
*Action: Examine the error messages take appropriate action.
The number you see on all_tables is a point in time capture of the number of rows. It will only be updated if the statistics are rebuilt for that table.
Here is an example:
CREATE TABLE t1 AS
SELECT *
FROM all_objects;
SELECT t.num_rows
FROM all_tables t
WHERE t.table_name = 'T1';
-- 78570
SELECT COUNT(*)
FROM t1;
-- 78570
The stats and the physical number of rows match!
INSERT INTO t1
SELECT *
FROM all_objects ao
WHERE rownum <= 5;
-- 5 rows inserted
SELECT t.num_rows
FROM all_tables t
WHERE t.table_name = 'T1';
-- 78570
SELECT COUNT(*)
FROM t1;
-- 78575
Here we have the mis-match because rows were inserted (or maybe even deleted), but the stats for the table have not been updated. Let's update them:
BEGIN
dbms_stats.gather_table_stats(ownname => 'SCHEMA',
tabname => 'T1');
END;
/
SELECT t.num_rows
FROM all_tables t
WHERE t.table_name = 'T1';
-- 78575
Now you can see the rows match. Using the value from all_tables may be good enough for your research (and will certainly be faster to query than counting every table).
Query - 1 is actual data of the table and hence it is accurate data. One can rely on this query's output.
Query - 2 is not actual data. It is the data captured when table was last analyzed and one should not be dependant on this query for finding number of records in the table.
You can gather the stats on this table and execute the query-2 then you will find the same data as query-1
If records are not inserted or deleted from the table after stats are gathered, then query-1 and query-2 data will match for that table.

Oracle puzzle: Selecting from a non-existing table

I have a table named "libisatz" in my database, and there is no table, nor view with name "libiSatz" (with capital S instead of s) and I don't find any kind of object in my schema having name "libiSatz". But, surprisingly selecting from "libiSatz" results in the same result as if I had written "libisatz". If I change any other letter in this name from lower case to upper case (e.g. I write "Libisatz", then I get an error. How can this be?.
ADDENDUM
I've checked the ideas of #Jon Heller with the following result:
Both select * from DBA_OBJECTS where OBJECT_NAME like 'libi_atz'; and select * from DBA_OBJECTS where lower(OBJECT_NAME) = 'libisatz'; returns one single row (it is the "libisatz" table)
select * from DBA_OBJECTS where OBJECT_NAME = 'libisatz'; returns one row and select * from DBA_OBJECTS where OBJECT_NAME = 'libiSatz'; returns no row.
Both select * from DBA_SQL_TRANSLATIONS; and select * from DBMS_ADVANCED_REWRITE; results in ORA-00942: table or view does not exist
select * from DBA_REWRITE_EQUIVALENCES; results in no rows selected
select DUMP(OBJECT_NAME) from DBA_OBJECTS where lower(OBJECT_NAME) = 'libisatz'; returns Typ=1 Len=8: 108,105,98,105,115,97,116,122
So it seems that the puzzle is not yet solved.
ADDENDUM 2.
When I try to create a view named "libiSatz" then I get
ORA-00955: name is already used by an existing object
in spite of the results above.
After I renamed "libiSatz" to "oraclepuzzle",
select count(*) from "libisatz"; and "select count(*) from "oraclepuzzle"; works, but select count(*) from "libiSatz"; doesn't.
select * from dba_objects where object_name in ( 'oraclepuzzle', 'libisatz', 'libiSatz'); returns one row with object_name "oraclepuzzle".
Do you have SQL translations, rewrite equivalances, or UTF8 characters?
The SQL translation framework was built to allow applications designed for other database types to seamlessly query Oracle. But instead of translating syntaxes, the feature could also be used to silently change your queries. For example, here is an example of querying a table that does not exist in order to workaround table size limitations. Check the view DBA_SQL_TRANSLATIONS.
Rewrite equivalences can be created by the package DBMS_ADVANCED_REWRITE, and can be used to silently change the results of wrong queries or for some rare performance problems. (In my simple tests I wasn't able to get this query to work for invalid queries, but I bet there is a way to make it work.) Check the view DBA_REWRITE_EQUIVALENCES.
UTF8 characters may be silently swapped out for similar ASCII characters. This probably depends on your database and client character set settings. The below example is pretty obviously not an ASCII "S", but you may have a more subtle problem. Check the source of your values, retype them manually, and use the DUMP function to evaluate the binary of the characters.
SQL> create table "libisatz"(a number);
Table created.
SQL> -- An uppercase "S" does not work
SQL> select * from "libiSatz";
select * from "libiSatz"
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> -- But a "LATIN SMALL LETTER S WITH CARON" works.
SQL> select * from "libiĆĄatz";
no rows selected
Lastly, are you 100% sure that the object doesn't exist on your database? The above examples are possible, but extremely rare. Triple-check DBA_OBJECTS.OBJECT_NAME for the mystery object.
My deafult Oracle object names are case insensitive.
So, when you issue teh command:
CREATE TABLE the_table ..
CREATE TABLE The_Table ..
CREATE TABLE THE_TABLE ..
The underlying object name in all cases is THE_TABLE, but you can access it using any mix of upper/lower case:
SELECT * FROM THE_TABLE
SELECT * FROM tHe_TaBlE
SELECT * FROM the_table
Will all work.
When a table is created with the name wrapped in double-quotes, the name becomes case-sensitive.
So, if you issue:
CREATE TABLE "libiSatz" ..
Then the table name in all SQL statements must match the exact name in the double quotes, i.e.
SELECT * FROM "libiSatz" is OK (Correction following comments)
SELECT * FROM libisatz is NOT OK
SELECT * FROM LibiSatz is NOT OK
When you search for this in USER_OBJECTS or USER_TABLES you will have to match the creation name:
SELECT * FROM USER_OBJECTS WHERE OBJECT_NAME = 'libiSatz';

Select from multiple tables oracle

I'm new in Oracle. I have a table that lists tablenames of database. Its name is "AD_Table". I want to select ID table, and createdby from ad_table list. For example in ad_table it has one column name tablename that represents table name in database:
tablename
---------
AD_Tab1
AD_Tab2
AD_Tab3
AD_Tab4
AD_Tab5
AD_Tab6
AD_Tab7
AD_Tab8
AD_Tab9
AD_Tab10
I want query like this :
SELECT
createdby
from (SELECT TABLENAME FROM AD_TABLE)
but it won't work. Can anyone help?
In Oracle you can have many tables with the same name, on different schemas;
assuming that you need to find all the tables, and their owners, whose names are contained in your table, you can try with something like this:
select owner, table_name
from AD_table AD
inner join dba_tables DBA ON ( dba.table_name = UPPER(ad.tableName))
Notice that you need to log in with a user having rights to make a select on DBA_TABLES to run this query.

CHAR_USED query returned '0 rows fetched from 1 column'

I created the following table:
Create table temp.test(c1 VARCHAR2(10 BYTE));
I was trying to use CHAR_USED to determine whether the column size is in BYTES or CHARS but all I am getting back is '0 rows fetched from 1 column'. The database version i am using is Oracle 11g. Does anyone have a clue as to why it is not return the semantic length information for this table?
The query used are as follows:
select CHAR_USED from all_tab_columns where table_name='temp.test'
select CHAR_USED from all_tab_columns where table_name='test' and owner = 'temp'
Assuming that you are not using case-sensitive identifiers (which you are not and should not), object names are stored in the data dictionary in upper case. So when you query a table like all_tab_columns, you'd need to use upper-case
SELECT column_name, char_used
FROM all_tab_columns
WHERE table_name = 'TEST'
AND owner = 'TEMP'

How to get all columns in Oracle in SYNONYMS

I know how to get all columns in oracle.
select * from all_tab_columns
but how can I get all columns from SYNONYMSas well?
Is this possible to do in oracle?
Isn't that a bit redundant? If you can see the table a synonym points to, then selecting from all_tab_columns gets you what you want.
You can get any synonyms for tables you can see thusly:
SELECT atc.*, s.synonym_name
FROM all_tab_columns atc LEFT JOIN all_synonyms s
ON (atc.owner = s.table_owner AND atc.table_name = s.table_name)
ORDER BY atc.owner, atc.table_name;

Resources