How can I call a stored procedure in the same schema without specifying the full schema name when coding another stored procedure. These are SQL PL procedures within DB2.
First SP:
CREATE PROCEDURE MYSCHEMA.SP_TEST
LANGUAGE SQL
BEGIN
END
Creating a SP calling this SP directly without a schema name causes a compilation error:
CREATE PROCEDURE MYSCHEMA.SP_TEST2
LANGUAGE SQL
BEGIN
CALL SP_TEST();
END
It will throw:
No authorized routine named "SP_TEST" of type "PROCEDURE" having compatible arguments was found.. SQLCODE=-440, SQLSTATE=42884, DRIVER=3.53.71
Directly giving the full schema name works:
CREATE PROCEDURE MYSCHEMA.SP_TEST2
LANGUAGE SQL
BEGIN
CALL MYSCHEMA.SP_TEST();
END
However if I ever move to a different schema I will have to replace that references all over the place. Is there a suitable workaround or nicer solution to the problem?
The CURRENT PATH special register is used to resolve calls to unqualified stored procedures and functions. CURRENT SCHEMA is used to resolve unqualified object names.
By default, CURRENT PATH has IBM functions plus your AUTHID:
$ db2 "values substr(current path,1,60)"
1
------------------------------------------------------------
"SYSIBM","SYSFUN","SYSPROC","SYSIBMADM","IBJORHOV"
1 record(s) selected.
You can modify this with the SET CURRENT PATH statement.
When you create a stored procedure, DB2 takes note of the value of CURRENT PATH at compilation time and uses them to resolve unqualified stored procedure and function calls within the stored procedure. The same logic applies for CURRENT SCHEMA and unqualified table names.
So the proper way to allow unqualified procedure and function calls within a stored procedure is to set the CURRENT PATH register and then creating the procedure.
Ommitting SCHEMA name is discouraged. Keep your schema names in your calls. If you move to a different schema, you have to do this by extracting/altering the SQL script anyway.
The SET SCHEMA command allows you to change the current schema:
SET CURRENT SCHEMA FOO;
CALL MY_PROC_THAT_RESIDES_IN_FOO();
It is not so easy to use set the schema to a dynamic value, though. You would have to either:
Do something with host variables (if you are within a calling application) or
Build and execute a dynamic SQL statement string.
At that point it is probably becoming more trouble than it's worth.
More information can be found at the documentation for the SET SCHEMA command.
Related
I'm trying to execute Snowflake Stored Procedure in Matilion Using Sql Script component.
But i'm getting error as Unknown user defined function.
Can someone help me to call the procedure using Matilion Job.
Thank You !
That looks like a name resolution error. Snowflake does not recognize the name of the stored procedure. You will see the same generic error message when trying to call a procedure that really does not exist...
You most likely need to
qualify the procedure name with a database and a schema
put the names inside double-quotes if they are case sensitive.
In the Matillion stored procedure article there is an example CALL "${environment_database}"."${examples_schema}"."audit"('START', ${run_history_id}, NULL)
I am presently updating a procedure with multiple EXEC lines such as:
EXEC databasename.tablename.pr_sys_drop_Object 'zt_Staging_of_class'
yet nowhere have I found the definition of EXEC in this context.
If it's a full three part name where the middle part is not the name of a table but of a schema a kind of SQL namespace. So in that context pr_sys_drop_Object is a stored procedure in a separate schema.
If you look in the named database, in the named schema you'll probably find a stored procedure called pr_sys_drop_Object.
Execute is a sql server keyword see the docs here for more details. It is used to execute stored procedures or raw sql.
In your case it seems to be executing the procedure databasename.tablename.pr_sys_drop_Object and passing in 'zt_Staging_of_class' as a parameter to that procedure.
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.
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.
I have several stored procedures that all use the same set of parameters. Is there a way to define and save the parameter list as a reusable block of code? Something like this:
CREATE PROCEDURE test
Using StoredParameterList
AS
BEGIN
SQL Statement
END
Is this possible? It would make code maintenance easier if a parameter needed to be changed.
Well, sort of. I've never used them, but Sql Server supports something called User Defined Types. I suspect you can create a user-defined type that represents your parameter list and then just have one parameter on each procedure with UDT.