can we create synonym with the same name in same schema - sql

I'm preparing for SQL Expert certification, and I found one question and It said,which is the correct option. And, out of four, one option said A table and a synonym can have the same name in the same schema.
And, per my knowledge, in oracle anything we create that treated as an object, which means when we say create synonym, which means we are creating new object. And create same object in same schema not allowed in Oracle or any database AFAIK.
Even Burleson says
You can have a public and private synonym of the same name. In fact,
you can have a public and private synonym called EMP in the SCOTT
schema and have a table called EMP in the same schema
So, I tried.
create synonym emp for scott.emp
It shows some error object already exist
Then I tried
create public synonym emp for scott.emp.
And, got same error. So, anyone please share some knowledge on Synonyms. Can we create synonyms with same name in same schema ?

You can have:
Table and Public Synonym with the same name
Public Synonym and Private Synonym with the same name
But can not have:
Table and Private Synonym with the same name inside the same schema
The first thing to note is that Public Synonyms are non-schema objects, while Private Synonyms and Tables are. Another is that the uniqueness of database objects' names are defined by the namespace. As it is stated in SQL Expert Study Guide:
USER, ROLE, and PUBLIC SYNONYM objects are in their own collective namespace.
TABLE, VIEW, SEQUENCE, PRIVATE SYNONYM, and user-defined TYPE objects have their own unique namespace within a given schema.
INDEX objects have their own namespace within a given schema.
CONSTRAINT objects have their own namespace within a given schema.
So, as long as objects do not share the same namespace you can give them the same names.
Hope this helps.

Public synonyms are non-schema objects, when private synonyms as tables are schema objects.
USER, ROLE and PUBLIC SYNONYM are in their own collective namespace.
TABLE, VIEW, SEQUENCE, PRIVATE SYNONYM have their own unique namespace.
An INDEX has their own unique namespace.
A CONSTRAINT object has their own unique namespace within a given schema
While the objects don't share the same namespace, you can give them the same names.
Remember, that you can have:
a table and public synonym with the same name
a public synonym and a private synonym with same name
You cannot have:
a table and a private synonym with the same name inside the same schema.

Related

What happens if I don´t define a specific schema to the database?

If a specific schema is not defined in a database, where are the database objects going to be stored? Is that a good or a bad thing? Why?
Quote from the manual
In the previous sections we created tables without specifying any schema names. By default such tables (and other objects) are automatically put into a schema named “public”. Every new database contains such a schema
If no schema is defined when creating a table, the first (existing) schema that is found in the schema search path will be used to store the table.
In psql
create database sch_test;
CREATE DATABASE
\c sch_test
You are now connected to database "sch_test" as user "postgres".
--Show available schemas
\dn
List of schemas
Name | Owner
--------+----------
public | postgres
drop schema public ;
DROP SCHEMA
\dn
List of schemas
Name | Owner
------+-------
(0 rows)
show search_path ;
search_path
-----------------
"$user", public
create table tbl(id integer);
ERROR: no schema has been selected to create in
LINE 1: create table tbl(id integer);
create table test.tbl(id integer);
ERROR: schema "test" does not exist
LINE 1: create table test.tbl(id integer);
Just to show that an object may not be created if a schema does not exist. Bottom line is an object(table, function, etc) needs to be created in a schema. If there is none available for search_path to find or you specifically point at one that does not exist the object creation will fail.

SQL Developer: Why can't I select by column synonym?

I just created a column synonym
CREATE PUBLIC SYNONYM col_syn FOR X_CHILD.FIRST_NAME;
This was executed without error.
But when i say
select dob, col_syn from x_child;
I get this:
ORA-00904: "COL_SYN": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
Error at Line: 4 Column: 13
The column "first_name" for sure exists:
select * FROM x_child;
shows:
I've pressed commit at least 18 times and restarted SQL developer. This did not help.
Also, when I click on synonyms in this schema, there's nothing there. And the only synonym i can see is the table synonym. Am I supposed to be able to see the column synonym here too?
A synonym, which is an alternative name for a table, view, sequence, procedure, stored function, package, materialized view, Java class schema object, user-defined object type, or another synonym. You cannot have a synonym to a column
Synonyms provide both data independence and location transparency. Synonyms permit applications to function without modification regardless of which user owns the table or view and regardless of which database holds the table or view. However, synonyms are not a substitute for privileges on database objects. Appropriate privileges must be granted to a user before the user can use the synonym.
When you create the synonym in your example, the reference object does not need to exist at all. In your case
CREATE PUBLIC SYNONYM col_syn FOR X_CHILD.FIRST_NAME;
you are creating a public synonym ( available for everybody ) which makes a reference to the object X_CHILD ( that is why you have in your dba_synonyms as reference_name X_CHILD ) and as reference_type TABLE ( not column )
Specify the schema to contain the synonym. If you omit schema, then Oracle Database creates the synonym in your own schema. You cannot specify a schema for the synonym if you have specified PUBLIC.
https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/CREATE-SYNONYM.html#GUID-A806C82F-1171-478E-A910-F9C6C42739B2

How to grant "select" permission on public synonym "SHC.ABC" of table "SHC.ABC"

I created table called "SCH.ABC" and created PUBLIC synonym "SCH.ABC" now I want to Grant "select" permission to schema "SCH1" on synonym "ABC" . How can i do that please help resolving this.
I am creating synanym as same name of table, while granting permission we will not specify object type whether it is a table or a synonym.
If given, grant select on ABC to sch1; then which object type will get granted synonym or table ?
You already created a public synonym called abc, and you can grant selecting to a particular schema as
grant select on abc to sch1;
where you do not need to qualify with schema name as sch.abc by connecting to sys or system schemas.
or you can grant to all schemas as
grant select on abc to public;
and you don't need to qualify the public synonym abc with the schema name. Use
select * from abc;
in every schema in the database.
Thank you very much for your interest to answering it. I just now found that, in that case synonym only will get precedence of grant. I tested by drop synonym in my home Schema and tried accessing it in another schema it was giving error and i again created synonym after that it was working fine.

Explicitly refer to public DBLink when schema owns a private one of same name?

I'm working a migration project requiring an import of several Oracle database schema onto an existing database. This requirement has brought about an interesting conflict where I now have two dblinks with the same name:
One is a private dblink which uses account A to access the Foobar database
The other is a public dblink to the same Foobar database which uses account B for its access
Global Names is set to true so I cannot change the names of these dblinks.
I've already figured out through trial and error that when signed into schema that owns the private dblink that the following:
SELECT *
FROM table#foobar;
will refer to the private dblink and not the public one. But for situations where I require the account B privileges, I cannot figure out how to explicitly refer to the public dblink.
Does anyone know of syntax I can use to refer to the public #foobar?
From Oracle documentation.
Oracle first searches for a private database link in your own schema with the same name as the database link in the statement. Then, if necessary, it searches for a public database link with the same name.
I don't think this can be changed in any way. Not that I know of or found in documentation. You could create public synonym but that will work only if you need to access with B specific objects. Synonym can't be created for whole database link.
Wouldn't it be easier to turn global names to False on session level and create new link to B with otherwise invalid link name. If you change global names on session level only that session will be allowed to use new link.

is it possible to selecting table in current_schema independent of public synonym

Is there a way, to select data only form the own schema, even if there is an public synonym?
something like: Select * from current_schema.Table1
more info:
I got a public synonym on table1 on schema1.
now I have a package(on schema2) that selects table1, I want to select table1 of schema2 not schema1.
My problem is, I dont what the user to change the identifier when he uses the package at his server.
edit
I see my question is not clear, what i wanted to know is is there a placeholder for my current schema?
at the moment i need to do this:
Select * from schema2.Table1
and i want is something Like this :
Select * from MySchema.Table1
or
Select * from this.Table1
or
Select * from current_schema.Table1
does something like this exists in oracle?
The scoping rules are quite clear. When the databse parses a query it looks for objects matching the identifiers in your statement in the following order of precedence:
objects of that name in your schema
private synonyms of that name (in your schema)
public synonys of that name
But if you want to be clear certainly you can prefix your table references with the specific schema name. That is helpful in communicating your intent to others looking at your code.
Furthermore, if you have a table TABLE1 in your schema and there is a public synonym called TABLE1 pointing at a table in another schema which you want to query instead you must prefix your reference with that other schema.
"what i wanted to know is is there a placeholder for my current
schema"
No, because it's not necessary. The default is always your current schema. That is, this statement ...
SQL> select * from t23;
... will always select from T23 in your current schema, if it has a table (or a private synonym) with that name.
Note that it is possible to change the value of your current schema, with the ALTER SESSION command:
SQL> alter session set current_schema=scott;
Now if you executed the previous select it would return results from SCOTT.T23 providing the SCOTT schema had such a table, and taht you had privileges on it. You can find out more about Oracle schemas in a blog piece I wrote a while back.
I was trying to understand what problem you were having, and I noticed that your scenario is one user executing a package owned by another user. Now, by default a package owned by SCHEMA2 will run against objects owned by SCHEMA2 and use the privileges on other objects granted to SCHEMA2.
But PL/SQL offers us the ability to change that: the AUTHID clause determines whether the package runs with the definer's privileges (that is the package owner) or invoker's privileges (the current user. So if SCHEMA2 defined their package with AUTHID CURRENT_USER when SCHEMA1 runs it the instance of TABLE2 will be the one in scope of SCHEMA1, which would be the one owned by SCHEMA1 or the one indicated by a public synonym.
Find out more.