When to qualify the schema name of an object in Oracle - sql

What determines whether an Oracle object (table, view, etc.) is required to be qualified with a schema name (for example, schema.table_name, or schema.view_name, etc.)? At times I am able to access a remote objects (via a DB link) without having to qualify the schema, but other times, I receive an error stating that the "table or view doesn't exist", and to correct this, I must qualify the schema name.
I am aware that it is a best practice to always qualify a schema name, but I am just curious why I am able to access certain remote objects without a qualified schema, and others only with a qualified schema.

From the Oracle documentation:
http://download.oracle.com/docs/cd/B14117_01/server.101/b10759/sql_elements009.htm
The following example illustrates how Oracle resolves references to objects within SQL statements. Consider this statement that adds a row of data to a table identified by the name departments:
INSERT INTO departments
VALUES
(
280,
'ENTERTAINMENT_CLERK',
206,
1700);
Based on the context of the statement, Oracle determines that departments can be:
A table in your own schema
A view in your own schema
A private synonym for a table or view
A public synonym
Oracle always attempts to resolve an object reference within the namespaces in your own schema before considering namespaces outside your schema. In this example, Oracle attempts to resolve the name departments as follows:
First, Oracle attempts to locate the object in the namespace in your own schema containing tables, views, and private synonyms. If the object is a private synonym, then Oracle locates the object for which the synonym stands. This object could be in your own schema, another schema, or on another database. The object could also be another synonym, in which case Oracle locates the object for which this synonym stands.
If the object is in the namespace, then Oracle attempts to perform the statement on the object. In this example, Oracle attempts to add the row of data to departments. If the object is not of the correct type for the statement, then Oracle returns an error. In this example, departments must be a table, view, or a private synonym resolving to a table or view. If departments is a sequence, then Oracle returns an error.
If the object is not in any namespace searched in thus far, then Oracle searches the namespace containing public synonyms. If the object is in that namespace, then Oracle attempts to perform the statement on it. If the object is not of the correct type for the statement, then Oracle returns an error. In this example, if departments is a public synonym for a sequence, then Oracle returns an error.
What it's saying is that Oracle will check locally for objects you call before expanding its search outwards.
It may well be that there are public (or your own private) synonyms on some of your remote objects allowing you to reference them directly whereas those without the synonyms you'll have to fully qualify.

It depends on what username have you used when you logged in. Or what username was used when the database link was created/configured.
See, for each schema, there is a user. If you logged in as a user "XYZ", then you do not need to qualify object within the "XYZ" schema.

Related

If not exist clause SQL statement

so I found this sql query in a project I am succeeding. This is the first time I encountering this clause/statement. I understand that this is to look if the table exist before creating one and that Object_ID is the table name that is to be created.
My questions are:
Does sysobject mean the database?
What is the Object property?
I know that it is not the columns inside the table to be created.
The columns are : dtb_color_id and description.
can someone explain this to me. please?
IF NOT EXISTS(SELECT * FROM SYSOBJECTS WHERE ID = OBJECT_ID('DTB_COLOR') AND OBJECTPROPERTY(ID,'ISUserTable') = 1)
BEGIN
.......some query I understand
END
sysobjects, OBJECTPROPERTY and OBJECT_ID are used in Microsoft SQL Server. They are part of the SQL Server DMVs and system functions/procedures used to query and manipulate the metadata.
sys.sysobjects is simply the list of all objects (tables, views, SPs, functions, etc) on the server in the active database. Please note, that sys.sysobjects is deprecated and is only available for backward compatibility. Use sys.objects instead
https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/system-dynamic-management-views?view=sql-server-ver16
It has (as far as I know) no meaning in MySQL, unless somebody specifically created them.
You can also use INFORMATION_SCHEMA which is available in MySQL too (however slightly different in different RDBMS).
MSSQL INFORMATION_SCHEMA: https://learn.microsoft.com/en-us/sql/relational-databases/system-information-schema-views/system-information-schema-views-transact-sql?view=sql-server-ver16
MySQL INFORMATION_SCHEMA: https://dev.mysql.com/doc/refman/8.0/en/information-schema.html
SQL Server has no CREATE TABLE IF NOT EXISTS construct, a variation of the mentioned condition is commonly used to imitate that.
This is a way in SQL Server to check if a table exists in the active database and to perform actions according to the result, like creating the table.
OBJECTPROPERTY simply checks (in this case) if the table is a user created one.
https://learn.microsoft.com/en-us/sql/t-sql/functions/objectproperty-transact-sql?view=sql-server-ver16
I would remove the OBJECTPROPERTY condition in case the part you understand is a CREATE TABLE statement. You don't want to create a table which has a similar name to any system table/view, also you don't want to execute the CREATE TABLE if there is a VIEW with the same name (table creation will fail)
Yes sysobject means database.
The OBJECTPROPERTY() function returns information about schema-
scoped objects in the current database. Use this to check if an
object is a table, view, stored procedure, etc. You can also use
it to check if a table has a primary key, foreign key, foreign
key reference, etc.
For more details : https://learn.microsoft.com/en-us/sql/t-sql/functions/objectpropertyex-transact-sql?view=sql-server-ver16
In this scenario it is used to check whether it is user table or
not. The result of the ISUserTable property is 1 when it is user
table otherwise returns 0.
Here the following steps are followed:
First, it executes the select statement inside the IF Exists
If the select statement returns a value that condition is TRUE for IF Exists
It starts the code inside a begin statement
DTB_COLOR - May be a stored procedure

Altering a stored procedure not throwing "Invalid column name" error when that particular column is removed from the table in SQL Server

I have removed a column from a table which is referred in a stored procedure. When I alter that stored procedure, there is no error, but when executing it, an error
Invalid column name
is thrown.
I'm using SSMS 2017
You are looking for functionality called "schema binding". This means that if you cannot change the schema of an object if it is being referenced in a view or stored procedure.
This is handled on the dependent level, rather than on the original object. The place to start is with the documentation on SCHEMABINDING.
In practice, this means the following procedure:
Alter the object (i.e. table).
Get a schema binding error.
Drop the schemabinding option on all objects that refer to the original object.
Modify the original object.
Modify the dependent objects.
Be sure schema binding is back "on" the dependent objects.
It is a bit cumbersome, but it helps enforce database dependencies.

sys.objects [name] column is not consistent with object name in definition (stored procedure name)

Last week, as a part of one requirement, I wrote a script to generate object definition for all database objects.
While testing, I found that for few stored procedures, [sys.objects].name was not matching with name in actual object definition (as returned by OBJECT_DEFINITION(Object_ID)). It was very strange and I saw it first time in life.
While thinking for what could be the reason of same, I found that it happens when we rename stored procedure from Object Explorer (View--> Object Explorer in SQL Server Management studio).
Just wondering, is there any way to retrieve actual object name (in this case, SP name)?
I had the same problem. It appears SP_RENAME doesn't update the object definition. From the sp_rename link, microsoft says:
Renaming a stored procedure, function, view, or trigger will not change the name of the corresponding object either in the definition column of the sys.sql_modules catalog view or obtained using the OBJECT_DEFINITION built-in function. Therefore, we recommend that sp_rename not be used to rename these object types. Instead, drop and re-create the object with its new name.
I had a similar situation, where a stored procedure had been renamed using sp_rename. The new name used was iterative, with an extension of *_1. If the original name was 'MyProcedure', the new name would have been 'MyProcedure_1'.
'MyProcedure' represented the production code. 'MyProcedure_1' represented code that had been production code at one time, but was now obsolete. Indeed, 'MyProcedure_1' referenced objects that were no longer present in the database.
When looking at the name in sys.objects, the new name with the extension was there ('MyProcedure_1'), but the object_definition returned the old name ('MyProcedure'), but with the code for 'MyProcedure_1'.
This was discovered via a call to 'MyProcedure', which errored out, due to the missing objects.
The solution was to DROP 'MyProcedure_1', which effectively removed the object_id, and the erroneous object_definition, and reCREATE it. Of course we had to address the missing objects. And - we spread caution about using sp_rename for objects other than tables/columns.

SQL dot notation

Can someone please explain to me how SQL Server uses dot notation to identify
the location of a table? I always thought that the location is Database.dbo.Table
But I see code that has something else in place of dbo, something like:
DBName.something.Table
Can someone please explain this?
This is a database schema. Full three-part name of a table is:
databasename.schemaname.tablename
For a default schema of the user, you can also omit the schema name:
databasename..tablename
You can also specify a linked server name:
servername.databasename.schemaname.tablename
You can read more about using identifiers as table names on MSDN:
The server, database, and owner names are known as the qualifiers of the object name. When you refer to an object, you do not have to specify the server, database, and owner. The qualifiers can be omitted by marking their positions with a period. The valid forms of object names include the following:
server_name.database_name.schema_name.object_name
server_name.database_name..object_name
server_name..schema_name.object_name
server_name...object_name
database_name.schema_name.object_name
database_name..object_name
schema_name.object_name
object_name
An object name that specifies all four parts is known as a fully qualified name. Each object that is created in Microsoft SQL Server must have a unique, fully qualified name. For example, there can be two tables named xyz in the same database if they have different owners.
Most object references use three-part names. The default server_name is the local server. The default database_name is the current database of the connection. The default schema_name is the default schema of the user submitting the statement. Unless otherwise configured, the default schema of new users is the dbo schema.
What #Szymon said. You should also make a point of always schema-qualifying object references (whether table, view, stored procedure, etc.) Unqualified object references are resolved in the following manner:
Probe the namespace of the current database for an object of the specified name belonging to the default schema of the credentials under which the current connection is running.
If not found, probe the namespace of the current database for an object of the specified name belonging to the dbo schema.
And if the object reference is to a stored procedure whose name begins with sp_, it's worse, as two more steps are added to the resolution process (unless the references is database-qualified): the above two steps are repeated, but this time, looking in the database master instead of the current database.
So a query like
select *
from foo
requires two probes of the namespace to resolve foo (assuming that the table/view is actually dbo.foo): first under your default schema (john_doe.foo) and then, not being found, under dbo (dbo.foo'), whereas
select *
from dbo.foo
is immediately resolved with a single probe of the namespace.
This has 3 implications:
The redundant lookups are expensive.
It inhibits query plan caching, as every execution has to be re-evaluated, meaning the query has to be recompiled for every execution (and that takes out compile-time locks).
You will, at one point or another, shoot yourself in the foot, and inadvertently create something under your default schema that is supposed to exist (and perhaps already does) under the dbo schema. Now you've got two versions floating around.
At some point, you, or someone else (usually it happens in production) will run a query or execute a stored procedure and get...unexpected results. It will take you quite some time to figure out that there are two [differing] versions of the same object, and which one gets executed depends on their user credentials and whether or not the reference was schema-qualified.
Always schema-qualify unless you have a real reason not to.
That being said, it can sometimes be useful, for development purposes to be able to maintain the "new" version of something under your personal schema and the "current" version under the 'dbo' schema. It makes it easy to do side-by-side testing. However, it's not without risk (which see above).
When SQL sees the syntax it will first look at the current users schema to see if the table exists, and will use that one if it does.
If it doesn't then it looks at the dbo schema and uses the table from there

How do you set the database schema, at the package level, in SPARX Enterprise Architect?

Example:
I have a Data Model with a package called Academic. Inside of Academic, I have tables called Instructor and Student. When I "Generate DDL", I'd like Instructor and Student to be generated as:
CREATE TABLE [Academic].[Instructor] ...
CREATE TABLE [Academic].[Student] ...
I have tried setting the tagged value named OWNER (EAUML::table::OWNER) on each table (which works), however I'd like to think that I could somehow set this at the package level and have all of the tables within 'inherit' this value. To that end, I tried adding a new tagged value to the package, both as EAUML::table::OWNER and OWNER but it doesn't work as desired.
Ideally I'd like to use the package name as the schema name but it would be acceptable for the schema name to be an individual value, as long as it's only set in one place.
Settings on the package aren't used when generating the schema, so that won't help.
But if you right-click the package in the package browser and select Code Engineering -- Reset DBMS Options, you can change the DBMS type and table owner for all tables in the package.