what does EXEC master.. Do? - sql

I have seen this like:
EXEC master.dbo.xp_cmdshell
What does master refer to?
Update
And why sometimes is followed by two points:
master..
generally we would use master.dbo. Am I correct, so why some people write master..?

master is one of the default SQL Server system databases. You can tell because what you posted:
EXEC master.dbo.xp_cmdshell
...uses the three name notation. "master" is in the database position, "dbo" is the schema, and "xp_cmdshell" is the function/stored procedure in this case. You use this notation for also referring to tables and views, in different contexts.
This:
EXEC master..xp_cmdshell
...just omits the schema, but isn't a good idea if there are more than one schema being used in a database.

It refer to a stored procedure that has been created (by default) in the master table.
The name master refer to the database that contains the different schema of your server instance.

In Transact SQL, the fully qualified path to any object is:server_name.db_name.owner.object parm1, ...
The dots separate the four components
the first three components have defaults:
the current server
the current database
dbo (database owner) (which should be the owner of the shared tables)
master is the system database that defines the server.
For MS, since the system stored procs are still located in master, the following is completely redundant:EXEC master.dbo.stored_proc_name parm1, ...
and can be replaced with:EXEC stored_proc_name parm1, ...
and since EXEC is the default command:stored_proc_name parm1, ...
There is no difference between master.. and master.dbo.. They are both unnecessary when addressing system stored procs.

master refers to the master database (it is a System database).
In SSMS: Databases -> System Databases -> master

Related

MSSQL avoid multiple prefixes by using alias

I am using al lot of sql queries and tyred of typing the complete prefixes of
[LINKED_SERVER_ALIAS].[LINKED_SERVER_ON_LINKED_SERVER].[DATABASEPATH].[SCHMEMA].TABLE
No way to change the serverstructure or direct login to linked server on another linked server.
Question: Is there som transact sql command to create a global alias like
create
alias my_linked_connection
for
[LINKED_SERVER_ALIAS].[LINKED_SERVER_ON_LINKED_SERVER].[DATABASEPATH].[SCHMEMA].TABLE
that it is possible to use:
select * from my_linked_connection.TABLE
an additional problem is, that these are to many prefixes, so a normal select query is only possible by openquery or declare #cmd ... exec #cmd
Thanks
Combine a part of the prefixes inside the linked server alias sp_addlinked server.
Synonym is what you are looking for here
CREATE SYNONYM schema.tablename for linkedservername.remotedatabasename.schema.tablename
This has the advantage (which I expect is what you are looking for) that you can move views, functions and procedures through your development environments whithout having to modify the object code; the only thing that should be different is that the target database for the synonym will be different each time.
Note that Synonym is a MSSQL feature and may not be supported by your ODBC/JDBC drivers so please test fully before deployment.

Loop Through All SSMS Databases without Recreating Stored Procedure

Background Information:
In Python, I might write something like this if I want to apply the same logic to different values in a list.
database_list = ["db_1", "db_2", "db_3"]
for x in range(0,len(database_list),1):
print("the database name is " + database_list[x])
What I am trying to do:
What I am trying to do in SSMS, is pull a list of DB objects for each database. I created a stored procedure to pull exactly what I want, but I have to run it against each database, so 10 databases mean running it 10 times.
My goal is to do this with a T-SQL query instead of Python.
I tried doing something like this:
exec sp_MSforeachdb 'USE ?; EXEC [dbo].[my_stored_procedure]';
The problem with this is, [dbo].[my_stored_procedure] has to exist in every database I want to do this in.
How can I create the stored procedure in 1 database, but execute it for all databases or a list of databases that I choose?
I know what you are trying to do and if it's what I think (you seem reluctant to actually say!) you can do the following:
In the master database, create your procedure. Normally you wouldn't do this, but in this case you must prefix it sp_
use master
go
create procedure sp_testproc as
select top 10 * from sys.tables
go
Now if you run this, it will return tables from the master database.
If you switch context to another database and exec master.dbo.sp_testproc, it will still return tables from the master database.
In master, run
sys.sp_MS_marksystemobject sp_testproc
Now switch context to a different database and exec master.dbo.sp_testproc
It will return tables from the database you are using.
Try creating your sproc in master and naming it with an sp_ prefix:
USE master
GO
CREATE PROCEDURE sp_sproc_name
AS
BEGIN
...
END
GO
-- You *may* need to mark it as a system object
EXEC sys.sp_MS_marksystemobject sp_sprocname
See: https://nickstips.wordpress.com/2010/10/18/sql-making-a-stored-procedure-available-to-all-databases/
It should then be available in all dbs
Create the stored procedure in the Master database with the sp_ prefix, and use dynamic SQL in the stored procedure so it resolves object names relative to the current database, rather than the database which contains the stored procedure.
EG
use master
go
CREATE OR ALTER PROCEDURE [dbo].[sp_getobjects]
AS
exec ('
select *
from [sys].[objects]
where is_ms_shipped = 0
order by type, name
')
go
use AdventureWorks2017
exec sp_getobjects
#LunchBox - it's your single stored procedure (that you create in one database) that is actually going to need to contain the "exec sp_MSforeach ...." command, and instead of the command to be executed being "EXEC ", it will need to be the actual SQL that you were going to put into the stored proc.
Eg. (inside your single stored procedure)
EXEC sp_MSforeachdb 'USE ?; SELECT * FROM <table>; UPDATE <another table> SET ...';
Think of the stored procedure (that you put into one database) as being no different than your Python code file - if you had actually wanted to achieve the same thing in Python, you would have either needed to create the stored proc in each database, or build the SQL statement string in Python and execute it against each database.
I understand what you thought you might be able to achieve with SQL, but stored procedures really don't work the way you were expecting. Even when you're in the context of a different database, but you run EXEC <different_db>.stored_proc, that stored proc ends up running in the context of the database in which it exists (not your context database).
Now, the only one issue you may come up against is that the standard sp_MSforeachdb stored proc has a limit of 2000 characters for the command that can be executed (although, it does have multiple "command" parameters, this may not be practical if you were planning on running a very large code block, perhaps with variables that carry all the way through). If this is something that might impact what you're intending to do, you could do a search online for "sp_MSforeachdb alternatives" - there seem to be a handful that people have created where the command parameter can contain a larger string.

R SQL query: Could not find stored procedure

I am using R to run a stored SQL procedure:
query.str = "EXEC [StoredProcedure].[Procedure1]"
con <- odbcConnect("my_database")
my_data = sqlQuery(con, query.str)
This code works fine on my laptop. But when I try to run it on the server it gives an error:
42000 2812 [Microsoft][ODBC SQL Server Driver][SQL Server]Could not find stored procedure
I don't think this is a problem with the stored procedure itself, as I have encountered the same situation with multiple stored procedures (they work on my laptop but not the server).
Edit: I am sure the connection string works. When I use the same connection string for a non-stored-procedure, it works and data reads in just fine. The problem only occurs with stored procedures.
Thank you in advance!
Solution found: going through the Window Odbc connector, changing the default database to be the desired database fixed the problem.
This error may raise due to three main issues:
Incorrect reference of object's encapsulation including schema or database.
Every SQL Server object (table, stored procedure, function, etc.) resides in a schema and every schema resides in a database. Also, every object can be referenced by multi-part names. The default schema in SQL Server is dbo. Therefore by not specifying the database and schema in object reference, object is assumed to reside in connecting database and dbo schema. Consequently, below calls are equivalent:
EXEC [myServer].[myConnectedDatabase].[dbo].[myStoredProcedure]
EXEC [myConnectedDatabase].[dbo].[myStoredProcedure]
EXEC [dbo].[myStoredProcedure]
EXEC [myStoredProcedure]
If myStoredProcedure does not reside in either specified database or schema, this error would raise. If you do not know or remember where stored procedure resides, run queries on system sys views, INFORMATION_SCHEMA views, or system stored procedures, sp_*.
Incorrect spelling of stored procedure including not escaping special characters or reserved words.
To escape spaces, special characters (non-alphanumeric and non-underscore), and reserved words, enclose object names in square brackets [...]. Even better avoid such names. Thankfully for you, by default SQL Server is not case sensitive regarding identifiers. In other RDBMS's, like Oracle and Postgres, case sensitivity is retained for mixed cases during CREATE TABLE stage and double quotes would be needed for mixed cases types (i.e., "myStoredProc" <> mystoredproc <> MYSTOREDPROC).
Non-existent object in database or schema either by deletion or transfer to a different database or schema.

Need to move stored procedure into system stored procedure folder

When I created my stored procedure somehow I managed to place it within the stored procedures folder, however not inside the system stored procedures folder (the system SP folder exists within the stored procedures folder). How do I move it one level down into the system stored procedures folder?
EDIT: After reading the answers below I'm thinking that the problem is how I'm telling my C# program to access the stored procedure. I have this line of code that is throwing an exception, telling me that it cannot find it:
SqlCommand cmd = new SqlCommand("<database_name>.dbo.<stored_procedure_name>.sql", conn);
If anyone can offer any help on how to call the stored procedure properly it would be appreciated. Thx!
You don't, or at the least shouldn't.
This is for system stored procedures, which are built into the RDBMS and used for system functions, like renaming objects or checking users on the server.
Don't think of these as folders like in a file system - they are just organizing your objects based on existing meta-data (Stored procedure or View? System object or User object?)
You can conceivably mark it as a system object, but that's just a terrible idea.
Why do you want to obfuscate your procedure? If you are creating it it's obviously a user procedure and not a system one.
I'm really not sure why you would need to do this, but you can:
exec sp_ms_marksystemobject myprocname
It's undocumented - so I you won't have any support if you try and use it, and it might be removed from a future version of SQL Server.
+1 for #JNK's comment above.
Also, ensure that you've created the stored procedure under the schema you think you did. If you execute a statement like this:
create procedure foobar as ...
the stored procedure foobar gets created under your default schema, which is likely not dbo. You should always create and reference database objects with at least a 2-level, schema-qualified name:
create procedure dbo.foobar ...
create procedure some_schema.foobar ...
lest you shoot yourself in the foot. You should schema-qualify references as well. References like
select * from some_table
exec some_stored_procedure
rather than
select * from dbo.some_table
exec dbo.some_stored_procedure
are resolved by first probing for an object of the desired name and type under your default schema. If found, that is the object used to resolve the reference. If no such object is found, then a probe is made under the schema dbo.
Further, you should not generally give a stored procedure a name that begins with sp_: that further complicates (and slows down) resolution, throwing probes of the master database into the mix.

Possible to create a SQL stored procedure for use for all databases

I have a stored procedure, in one database within my SQL server, that sets permissions to all stored procedures at once for that particulat database. Is there a way to create this stored procedure in a way were I can call it easily from any database within the SQL server and if so how do I go about doing such a thing
While the best solution to this specific question of granting execute to all procedures is the one provided by marc_s, the actual question was is there a way to create a single stored procedure and make it available to all databases.
The way to do this is documented at https://nickstips.wordpress.com/2010/10/18/sql-making-a-stored-procedure-available-to-all-databases/:
Create the stored procedure in the master database.
It must be named to start with sp_, e.g. sp_MyCustomProcedure
Execute sys.sp_MS_marksystemobject passing the name of the procedure, e.g. EXEC sys.sp_MS_marksystemobject sp_MyCustomProcedure
Here is a simple example which just selects the name of the current database:
use master
go
create procedure dbo.sp_SelectCurrentDatabaseName as begin
select db_name()
end
go
execute sys.sp_MS_marksystemobject sp_SelectCurrentDatabaseName
go
Calling exec dbo.sp_SelectCurrentDatabaseName on any database will then work.
To mark the procedure as not a system object, there a some nasty hacks suggested at https://social.msdn.microsoft.com/Forums/sqlserver/en-US/793d0add-6fd9-43ea-88aa-c0b3b89b8d70/how-do-i-undo-spmsmarksystemobject?forum=sqltools but it is safest and easiest to just drop and re-create the procedure.
Caveat
Of course creating system procedures like this is breaking the common rule of not naming your own procedures as sp_xxx, due to the possibility of them conflicting with built-in procedures in future versions of SQL Server. Therefore this should be done with care and not just create a load of randomly named procedures which you find useful.
A common simple way to avoid this is to add your own company/personal prefix to the procedure which Microsoft is unlikely to use, e.g. sp_MyCompany_MyCustomProcedure.
I have a stored procedure, in one database within my SQL server, that
sets permissions to all stored procedures at once for that particular
database.
You could archive the same result much easier:
create a new role, e.g. db_executor
CREATE ROLE db_executor
grant that role execute permissions without specifying any objects:
GRANT EXECUTE TO db_executor
This role now has execute permissions on all stored procedures and functions - and it will even get the same permissions for any future stored procedure that you add to your database!
Just assign this role to the users you need and you're done....
Have you tried a 3 or 4 part name?
InstanceName.DatabaseName.dbo.usp_Name
That procedure could in turn reference objects in other databases using the same conventions. So you could parameterize the name of the database to be operated on and use dynamic SQL to generate 4 part names to reference objects such as system tables.