How to correctly make a public synonym - oracle

This is a pretty silly one, but I need help.
I have a table owned by mydbowner. It is named mydbowner.mytable. I tried to make a public synonym by issuing the command:
CREATE OR REPLACE PUBLIC SYNONYM mytable FOR mydbowner.mytable;
When I do this, and I query the table I get:
ORA-01775: looping chain of synonyms
How do I make this synonym without having the problem.

I think Justin is on the right track. What I think it actually means is that mydbowner.mytable doesn't exist.
Here's an example:
SQL> conn mbobak
Enter password:
Connected.
SQL> drop table mytable;
drop table mytable
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> create public synonym mytable for mbobak.mytable;
Synonym created.
SQL> select * from mytable;
select * from mytable
*
ERROR at line 1:
ORA-01775: looping chain of synonyms
I think what's happening is that Oracle tries to resolve mytable, there is no mytable in mbobak schema, so it looks for it in PUBLIC, it finds it, and sees that it points to mbobak.mytable. But, mbobak.mytable doesn't exist, so, it looks for mytable in PUBLIC, and there's the loop.
And in fact, if you create mytable, the error goes away:
SQL> create table mytable as select * from dual;
Table created.
SQL> select * from mytable;
D
-
X
1 row selected.
SQL> drop table mytable;
Table dropped.
SQL> select * from mytable;
select * from mytable
*
ERROR at line 1:
ORA-01775: looping chain of synonyms
Yes, I realize that doesn't really entirely make sense, as, once the public synonym resolved to mbobak.mytable, and that's not found, it seems to me, it should return an error ORA-942 "table or view does not exist", which makes far more sense to me.
But, this does seem to be how it works.
QED
Hope that helps.

The error you're getting implies that mydbowner.mytable is not, in fact a table. What does
SELECT object_type
FROM all_objects
WHERE owner = 'MYDBOWNER'
AND object_name = 'MYTABLE'
return?

Related

How to select all DML statement done to a table

With this query, I can see which table where modified last hour.
select * from ALL_TAB_MODIFICATIONS where timestamp> sysdate-1/24
Now I want to know what has been insert, updates, deletes in a table. And if possible with the user id.
How do I do that?
I've tried to use audit.
https://www.ibm.com/docs/en/svgaa?topic=c-enabling-auditing-oracle-resource
in sqlplus
SHOW PARAMETER AUDIT_TRAIL
DB --OK
AUDIT ALL BY SEV BY ACCESS
audit succeeded
I've tried to see the content of all the audit table (SELECT view_name FROM dba_views WHERE view_name LIKE 'DBA%AUDIT%';)
for instance :
select * from dba_audit_exists;
but they are empty

How to read all table names from Oracle thru Spark

I want to fetch table names from Oracle database via Spark.
But it always failed.
with error:
Exception in thread "main" java.sql.SQLSyntaxErrorException:
ORA-00942: table or view does not exist
Sql = SELECT * FROM sys.tables WHERE 1=0, OriginalSql = SELECT * FROM
sys.tables WHERE 1=0, Error Msg = ORA-00942: table orview does not
exist
Have I missed something ? thanks.
class TrxxConnection(sparkSession:SparkSession) {
val trxxCon = sparkSession.read
.format("jdbc")
.option("url", "jdbc:oracle:thin:#//*****:****/****")
.option("user", "*****")
.option("password", "*****")
.option("driver", "oracle.jdbc.driver.OracleDriver")
// import sparkSession.implicits._
// // List the name of all tables in ARAMIS Database
def AllTableList =
trxxCon
.option("dbtable", "information_schema.tables") // or use sys.tables
.load()
.select("name").orderBy($"name".asc)
}
// below is unit test
println("Begin to establish connection to Oracle")
val AllTableList = new TrxxConnection(sparkSession).AllTableList // Dataset[Row] type
println("Connection to Oracle established")
println("Number of all tables: " + AllTableList.count())
AllTableList.show()
Apparently, there's no such thing as tables owned by sys available to you (nor me, when we're at it):
SQL> select count(*) from sys.tables;
select count(*) from sys.tables
*
ERROR at line 1:
ORA-00942: table or view does not exist
What to do? Use something that is available to you, e.g. your own tables in user_tables:
SQL> select count(*) from user_tables;
COUNT(*)
----------
30
or tables accessible to you, owned either by you or someone else:
SQL> select count(*) from all_tables;
COUNT(*)
----------
842
SQL>
or, if you are powerful enough, the whole database's tables by querying dba_tables:
SQL> connect sys#pdb1 as sysdba
Enter password:
Connected.
SQL> select count(*) from dba_tables;
COUNT(*)
----------
2398
SQL>
Pick one.
As I'm connected as sys right now, what do I see in that tables thing you used?
SQL> select * from tables;
select * from tables
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL>
Still nothing.
So, where exactly did you find information about tables owned by sys you could use for that query?

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';

EFCore error:- ORA-00904: "m"."Id": invalid identifier

I am working with an application using asp.net core 2.2 and efcore database first approach with Oracle database. I am using Oracle.EntityFrameworkCore (2.19.60) nuget package, successfully mapped db model, but when I try to fetch data from DBContext , getting error
ORA-00904: "m"."Id": invalid identifier
Oracle Database version: Oracle Database 12c Standard Edition Release 12.2.0.1.0 - 64bit Production
code:
var fetched = await myDatabaseContext.MyTableVersions.ToListAsync();
LinQ is generating following query :
SELECT "m"."Id", "m"."MAJORVERSION" FROM "MyTableVersions" "m"
Since It's not a correct syntax for PL/Sql query so getting error ORA-00904: "m"."Id": invalid identifier.
Is there any way to fix this error? Thanks.
I have searched on the web and found
Bug 30352492 - EFCORE: ORA-00904: INVALID IDENTIFIER
but that issue is related to schema.
The query is perfectly valid (db<>fiddle here), assuming your table looks something like
CREATE TABLE "MyTableVersions"
("Id" NUMBER,
MAJORVERSION NUMBER)
However, I suspect your table looks like
CREATE TABLE "MyTableVersions"
(ID NUMBER,
MAJORVERSION NUMBER)
I don't know what the class looks like that you're trying to fetch into, but I suspect it has a field named Id. If you can change the name of that field to ID (in other words, so that its capitalization matches the capitalization of the related database column) you might find it works then.
Double quotes are something you should avoid in Oracle world.
Your query:
SELECT "m"."Id", "m"."MAJORVERSION" FROM "MyTableVersions" "m"
means that column name is exactly Id (capital I followed by d). Only if that's really so, you should use double quotes. Otherwise, simply remove them:
SELECT m.id, m.MAJORVERSION FROM MyTableVersions m
The same goes for the table name - if it was created using mixed case (and you can't do that without double quotes), you'll have to use double quotes and exactly same letter case always. Otherwise, don't use them.
Oracle is case-insensitive regarding object and column names and are UPPERCASE by default:
SQL> create table test (id number);
Table created.
SQL> desc test
Name Null? Type
----------------------------------------- -------- -----------------
ID NUMBER
SQL> select table_name, column_name
2 from user_tab_columns
3 where table_name = 'TEST';
TABLE_NAME COLUMN_NAME
------------------------------ ------------------------------
TEST ID
SQL> insert into test (id) values (1);
1 row created.
SQL>
But, if you use mixed case with double quotes, then use them always:
SQL> create table "teST" ("Id" number);
Table created.
SQL> insert into test (id) values (1);
insert into test (id) values (1)
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> insert into "test" (id) values (1);
insert into "test" (id) values (1)
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> insert into "teST" (id) values (1);
insert into "teST" (id) values (1)
*
ERROR at line 1:
ORA-00904: "ID": invalid identifier
SQL> insert into "teST" ("Id") values (1);
1 row created.
SQL>
So: first make sure what table and column names really are, then use them appropriately.
To avoid problems with case-sensitivity, add the option to eliminate EF to add quotes to the generated queries. For instance, if you are using Devart Oracle provider, this is done in the following way:
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpDbContextOptions>(options =>
{
var config = Devart.Data.Oracle.Entity.Configuration.OracleEntityProviderConfig.Instance;
config.Workarounds.DisableQuoting = true;
...
}
}
If you are using official provider - just inherit from DbCommandInterceptor (do quotes replacement with empty character in dbCommand in ...Executing methods), add this interceptor to DbContextOptionsBuilder instance.

creating mview containing pl/sql definitions in with clause

How to use pl sql definitions in with clause while creating mview?
An explanation with example would really help.
Also I have tried the following queries and I have faced some errors.
create table tab1
(
fname varchar2(15) ,
lname varchar2(15)
);
create or replace type user_data_type as object (val1 varchar2(20),val2 varchar2(20));
/
CREATE OR REPLACE Function get_fname_lname(n in varchar2)
RETURN user_data_type as
name user_data_type;
cursor buffer_cur is
select fname,lname from tab1 where fname=n;
BEGIN
name := new user_data_type(null,null);
OPEN buffer_cur;
fetch buffer_cur into name.val1,name.val2;
close buffer_cur;
return name;
End;
/
select * from tab1;
select get_fname_lname(fname).val1 fname,get_fname_lname(fname).val2 from tab1;
drop materialized view mv1;
create materialized view mv1
with names as
(select get_fname_lname(fname).val1 fname,get_fname_lname(fname).val2 lname from tab1)
select fname,lname from names;
select * from mv1;
I have seen this error:
Error while creating mview:
ORA-00905: missing keyword
Can some one point me out what might be the issue.
You can try something like this while creating view , since recursive views are not supported in oracle.
By using with clause you are already creating an inline view and for that view you are trying to create a materialised view which is not supported in oracle
create materialized view mv1
as
select fname,lname from
(select get_fname_lname(fname).val1 fname,get_fname_lname(fname).val2 lname
from tab1);

Resources