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

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.

Related

Multi-schema select statement doesn't work in PL/SQL procedure?

I'm trying to create a procedure to run multiple PL/SQL statements, but I haven't gotten very far. The select statement works fine if I run it out of a procedure, but if I try to execute it inside one -- it can't find the shttran table. I'm guessing it might be a schema issue, but I have no idea how-to correct. Ideas?
CREATE OR REPLACE PROCEDURE REGREPORTUSER.findUnsent
IS
BEGIN
INSERT INTO regreportuser.maltran (maltran.maltran_key,
maltran.maltran_sent)
SELECT shttran.shttran_id || shttran.shttran_seq_no AS maltran_key,
'No' AS maltran_sent
FROM saturn.shttran -- This is the table it can't find
WHERE TO_DATE (shttran.shttran_activity_date) > SYSDATE - 14
AND shttran.shttran_user = 'WWW2_USER'
AND shttran.shttran_id || shttran.shttran_seq_no NOT IN
(SELECT maltran.maltran_key FROM regreportuser.maltran);
END findUnsent;
Most likely, the problem is that the user that owns the stored procedure, REGREPORTUSER has access to the table saturn.shttran via a role rather than as a direct grant. A definer's rights stored procedure cannot use privileges that are granted to a definer via a role. It can only use privileges granted directly.
You can verify that this is, in fact, the problem by disabling roles in your SQL*Plus session. If you run the command
SQL> set role none;
and then try to execute the SQL statement, you should get the same error. In order to fix the problem, you need to give the grant directly
GRANT SELECT ON saturn.shttran
TO REGREPORTUSER

EXECUTE AS and OPENROWSET bulkload

I've created a stored procedure as one user who has admin privileges and included
WITH EXECUTE AS SELF
Then i'm trying to execute the stored procedure with a user who has no privileges, attempting to impersonate the user who is an admin.
But it errors back saying the user does not have the privileges to use bulk load.
Anyway round this?
I supposed the admin user can execute the proc, right?
Can you show how you are doing the call?
Because EXECUTE AS SELF means execute as user calling the proc, so you would have to do something like EXECUTE AS USER = 'user_with_permission' before calling the proc
You can use this query to find the ID of the principal that is "self" for a procedure:
select execute_as_principal_id
from sys.sql_modules
where object_id = object_id('YourProcedureName')
For me, that's null most of the time, which seems like it shouldn't work. Try this instead:
WITH EXECUTE AS 'UserWhoHasAdminRights'
or to execute as DBO:
WITH EXECUTE AS OWNER

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.

Scripting execute permission along with stored procedure

In sql is it possible to script permissions as one can with the stored proc itself? So that I can simply tell somebody to hit execute and the proc and permissions just get created all at once.
Yes, you can script the execute permission as follows:
use [database_name]
GO
GRANT EXECUTE ON [dbo].[stored_procedure_name] TO [user_name]
GO
Replace the database_name, stored_procedure_name and user_name values with the appropriate values.
If you include this in your script after the SP CREATE statement it will add the permissions right after the SP is created.

Regarding Execute Immediate in stored procedure

I am having the below statement from stored procedure. It's giving Insufficient Privileges.
But If i run the create statement alone from the sql prompt it's creating table.
execute immediate 'create table TEST_ABC(
NO_AC NUMBER(8)
, ILL_PER VARCHAR2(15)
, INIT_C DATE
)';
What needs to be done to have priviliges to create table via execute immediate from stored procedure. Not sure how it's working from sql command prompt
Procedures don't inherit privileges granted via a role. More info here. Please check if that's what happening to you.
One way to solve this problem is to grant "CREATE TABLE" privilege directly to the account that owns the procedure.
Is the procedure created by the same user? If it is created by some one else and you have EXECUTE privilege alone, then the error is right (assuming the create procedure doesn't have AUTHID CURRENT USER clause).
Can you create any other table? If you can, then there is some issue. We would need more details to analyse.