Adding a stored procedure to a database - sql

If I create a database called MyDatabase and then wish to add a stored procedure to this database, do I have to specifically reference this database when running the SQL query for the stored procedure or is the stored procedure added to this database automatically?

A stored procedure is an object that belongs to one database exctly.
When you add the SP, it will be added to the database you are currently using.
To make sure you are running the current database, run this:
Use [MyDatabase]
GO

If you have selected your database in top left corner (Management Studio) MyDatabase the procedure will be created there. Else you can use the "Use" keyword I provide a little sample for you here.
Use MyDatabase
create procedure hello
as
select 'Hello World I'm a stored procedure'
go
And then run the exec command pointing to the name of the procedure
exec hello
If you have selected another database ex master you could exec the procedure by pointing out what database to use.
exec MyDatabase.dbo.hello
And the dbo schema is the default schema in SQL.
This is for SQL Server.

Related

Target tables in different schemas from store procedure but don't change code

Please can any one advise if it is possible to have a stored procedure in the [dbo] schema select data from one table in one schema for users accessing via one database role and for it to select data from a like-named table in another schema for users accessing via another database role?
For example if I have three schemas in my database:
dbo
green
red
I have two database logins [RedLogin] and [GreenLogin]. These connect to my database using respective database users [RedUser] and [GreenUser]. These users are members of the respective database roles [RedRole] and [GreenRole].
[RedUser] has a default schema of [red].
[GreenUser] has a default schema of [green].
[RedRole] has execute permission on [dbo] and select permission on
the [red] schema.
[GreenRole] has execute permission on [dbo] and select permission on
the [green] schema.
In the [green] schema I have a table called [User].
In the [red] schema I have a table called [User].
In the [dbo] schema I have a stored procedure called [User_GetAll]
that runs.
SELECT * FROM USER;
What I would like is:
For users who login with [Redlogin] and call the
[User_GetAll] get all users from the [red].[User] table.
For users who login with [Greenlogin] and call the
[User_GetAll] get all users from the [green].[User] table.
So I have a question. For example:
-[dbo] schema in the past, I had 100 stored procedures. And now, I don't want to change code in stored procedure because It's so much, so How can I do to address the problem? Please help me.
....................................................................................
Update:
For simple example:
I have a schema [dbo], and in that schema, I have created a stored procedure dbo.GetAccount:
CREATE PROCEDURE dbo.GetAccount
AS
BEGIN
SELECT * FROM tblAccountNet
END
Then, I have created a schema [ABC] with user named UserABC.
Now, I would like to login with UserABC and execute dbo.GetAccount for schema [ABC] to get all user of it and don't want to change code of dbo.GetAccount. So, how can I do?
These are my ideas to resolve it:
Create another stored procedure in [dbo] schema, and use it to read all other procedure to make them execute against schema with user when login. Can I do that? So, how can I do that?
Create a stored procedure to change schema of all [dbo] procedure to [ABC]. Can I do that?
Thanks for your help.
Your best bet here would be to use dynamic SQL. That is something which allows you to pass string variables into a script which then gets executed against the SQL engine. For example, if you had variables #dynamicsql and #usertype, you would build a dyanmic SQL string like:
#dynamicsql = 'SELECT * FROM '+#usertype+'.tblAccountNet'
Then you would execute this code in a stored procedure using EXEC(#dynamicsql). This would probably work, but it requires additional permissions for the user, and also opens you up to a whole world of security concerns, with the biggest one being SQL Injection attacks. So this would probably work, but it might be more trouble than it is worth.
http://xkcd.com/327/

Calling sp_help on linked server

I have a table named 'Application' on linked server (hosting server) in schema 'ID'.
I am trying to view the details of same using sp_help.
But I'm not able to do it.
The problem is:
1. sp_help is in schema dbo. (It is obvious!)
2. But my table in another schema named ID. (e.g. select * from ID.Application)
I've added linked server to my local sql server management studio.
And tried:
exec [198.198.198.198].[sms].[dbo].sp_help applicantion
exec [198.198.198.198].[sms].[dbo].sp_help id.applicantion
exec [198.198.198.198].[sms].[dbo].sp_help sms.id.applicantion
'sms' is my database on linked server.
Results: syntax error.
I tried: SQL using sp_HelpText to view a stored procedure on a linked server
But my problem is 2 different schema.
Any suggestions??
Does this work?
exec [198.198.198.198].[sms].[dbo].sp_help 'id.applicantion'

SQL 2012 returns different results when running ad-hoc query and stored procedure

This is really strange.
I have the following code:
SELECT [name]
FROM sys.databases
WHERE [name] NOT IN('tempdb')
AND [source_database_id] IS NULL
AND [state_desc] = 'ONLINE'
when I run the code, I get a list of 5 databases (which is ok):
master
model
msdb
Maintenance
SSISDB
when I create a procedure that runs this same code, I get only two:
CREATE PROCEDURE [dbo].[usp_test99]
WITH EXECUTE AS OWNER
AS
BEGIN
SELECT [name]
FROM sys.databases
WHERE [name] NOT IN('tempdb')
AND [source_database_id] IS NULL
AND [state_desc] = 'ONLINE'
END
exec Maintenance.[dbo].[usp_test99]
and this is the results:
master
Maintenance
What do I miss here?
This is SQL 2012. It happens on some servers, not only on one.
Thanks
Try WITH EXECUTE AS CALLER, since the owner of your stored procedure probably does not have the proper privileges on your system.
The documentation states:
If the caller of sys.databases is not the owner of the database
and the database is not master or tempdb, the minimum
permissions required to see the corresponding row are ALTER ANY
DATABASE or VIEW ANY DATABASE server-level permission, or CREATE
DATABASE permission in the master database. The database to which
the caller is connected can always be viewed in sys.databases.
So you can use either
USE [Maintenance]
GRANT VIEW ANY DATABASE TO [dbo]
or
WITH EXECUTE AS 'sa'

Permissions when using "Execute sp_Executesql"

I have a database where all access is controlled by stored procedures. The DBA would like to avoid giving users direct read/write access to the underlying tables, which I can understand. Hence all updating and selecting of data is done via stored procedures. Basically he has created one role that has EXECUTE permissions to all the stored procedures in the database and given users that role.
The problem is that one of the stored procedures dynamically builds a SQl Query and executes it via "Execute sp_Executesql". Without going into great detail the query is built dynamically because it changes significantly depending on many user input parameters. The stored procedure in question is only a SELECT sql statement however I am finding that just giving the stored procedure EXECUTE permission is not enough. The underlying tables referenced within the stored procedure that make use of "Execute sp_Executesql" need to have been given "datareader" access or else the stored procedure fails.
Any thoughts on how to correct this? I really wanted to restrict access to the tables to only stored procedures, but I need to find a way to work around the stored procedures that make use of "Execute sp_Executesq"l. Thank you.
In the wrapper proc you can use EXECUTE AS OWNER or EXECUTE AS SomeuserWithNoLogin
This will change the login context for the duration of the stored proc which includes sp_executesql.
If you use OWNER, it will work because you're already using ownership chaining.
If your DBA (good man!) does not want you running as dbo, then set up a user that has full read but no rights. EXECUTE AS <user> requires an entry is sys.database_principals
Like this:
CREATE USER SomeuserWithNoLogin WITH WITHOUT LOGIN
EXEC sp_addrolemember 'db_datareader', 'SomeuserWithNoLogin'
For more info, see EXECUTE AS Clause on MSDN and CREATE PROCEDURE
The real problem is that sp_Executesql is in the master database, not necessarily the database your working in. Your DBA has to give execute sp_Executesql permission to the calling procedure. Than anyone who has permission to call that procedure will be able to run the sp_Executesql.

Why should GRANT be written after GO in a SQL Stored Procedure?

We had a Stored Procedure written and it had a GRANT written at the last line of the SP.. Our DBA recommended that there should be a GO before the GRANT statement, else it will be executed every time.
What does this mean? I am not sure how GO will prevent GRANT executing "every time".
A stored procedure definition doesn't have to end with and END. If you define your procedure
like this:
CREATE PROCEDURE MySP AS
SELECT field1, field2 FROM table;
GO
GRANT EXECUTE ON MySP TO user1;
...then SQL Server will create a procedure that returns a result set, and grant execute permissions on that stored procedure to user1.
If you do something like this, though:
CREATE PROCEDURE MySP AS
SELECT field1, field2 FROM table;
GRANT EXECUTE ON MySP TO user1;
...then SQL Server will create a procedure that both returns a result set, and grants execute permission every time that stored procedure is executed. In other words, the GRANT is included in the definition of the stored procedure. Probably not what you wanted.
A GO statement is used to mark the end of a batch in SQL Server. It unambiguously tells SQL Server "I'm done with whatever I was executing in the previous set of statements". It's very good practice to add this to the end of every definition in your create scripts; this exact situation has bitten me more than once in the past.
Your DBA meant that this GRANT will be a part of your stored procedure, and as such will execute every time your procedure is executed.
Typically users should not be allowed to grant privileges, so your procedure should raise errors every time its last command is executed.
GO is the default command separator used in query analyzer, you can actually configure it to be whatever you want. you could also achieve the same by using BEGIN..END around the proc body.