Default schema in procedures - schema

I'm trying to deploy stored procedure in IBM DATA STUDIO.
I'm using DB2 for LUW (Linux, Unix, Windows).
Stored procedure is in schema X and tables are in Y schema.
I get error
X.PROCEDURE_NAME is an undefined name.. SQLCODE=-204, SQLSTATE=42704, DRIVER=4.13.111,
because deploy assumes that it should use X for table objects being used in
procedure body.
How can define QUALIFIER for objects used in procedure ?
I've tried
SET SCHEMA Y;
and some similar variations.
Error is the same.
Can I somehow accomplish this ?
Maybe with precompile options?
If yes, what should I enter ?
We are using DB2 LUW for a long time,
and we must always fully qualify table names in stored procedures,
which is annoying.

Related

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.

Getting results from Oracle stored procedure insertion through pyodbc

I am using pyodbc (version 3.0.7) to access an Oracle (version 11g) database. We are writing stored procedures to handle the insertions. The primary keys for inserted objects are assigned with triggers, so we want to get the newly-inserted object's primary key into python after the stored procedure is called by the python script. (Due to client requirements, we don't have the flexibility of changing database, libraries, etc.)
According to the pyodbc documentation, return (OUT) parameters in stored procedures are not supported. Neither are stored functions. The documentation suggests to add a SELECT statement to the end of a stored procedure to get results out. However, we are new to SQL scripting, and Google searching for the last two days has turned up a lot of information for SQLServer and other databases, but next to nothing for Oracle. Trying the SQLServer examples on the Oracle db has not been tremendously helpful, as the Oracle SQL Developer shows various errors with the syntax (DECLARE where one shouldn't be, INTO required for SELECT statements, etc.).
Ultimately, we want the stored procedure to insert a new object, and then we want to somehow get the newly-created primary key for that object.
Here is an example of a stored procedure that correctly inserts an object (note that if obj_id is given as "None" in python, then the object is assigned a new primary key by a trigger):
CREATE OR REPLACE PROCEDURE insert_an_obj (an_obj_id NUMBER) AS
new_primary_key NUMBER;
BEGIN
INSERT INTO OBJS (OBJ_ID) VALUES (an_obj_id) RETURNING OBJ_ID INTO new_primary_key;
-- A SELECT statement should go here in order to get the new value for new_primary_key.
END insert_an_obj;
Supposedly, a SELECT statement at the end of the stored procedure will make it so the next time my script calls cursor.fetchall(), the script would get a list of whatever was selected. However, I have been unable to get this to work. Some failed SELECT examples (one of which might go in the stored procedure above in place of the SELECT comment) include the following:
-- These fail to compile because SQL Developer doesn't like them (though various sources online said that they work on SQLServer):
SELECT * FROM OBJS WHERE OBJ_ID=new_primary_key;
SELECT OBJ_ID FROM OBJS WHERE OBJ_ID=new_primary_key;
Like I said, I'm new to SQL, and likely I just need to know the proper syntax to get the SELECT statement working nicely in Oracle. Any suggestions? Or is there something that I'm misunderstanding?
As mentioned by Justin Cave in the comment above, "you can't just put a SELECT in a stored procedure to return data to the client." At least not with Oracle 11g. He continues: "In 11g, the only way to regurn data from a stored procedure is to have an OUT parameter", which AFIK, not possible using version 3.0.7 of pyodbc.

Calling a stored procedures within the same schema from a SP

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.

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.

Alias Columns Returned by a Stored Procedure [SQL Server 2008]

I'm not super familiar with stored procedures in general and SQL Server/T-SQL specifically. I'm wondering if there is a way to alias or rename the columns returned by a stored procedure without modifying the stored procedure itself.
Here is the stored procedure call I have now.
EXEC sp_GetNearbyLocations 38.858907, -77.261358
It returns records with the following columns:
State
Zip
Phone
StartDate
Directions
Hours
Latitude
Longitude
Distance
However I'd like them to be all lowercase and not camel cased. Sadly, I do not control the stored procedure so I cannot change it, just my call to it. Is this possible in SQL Server 2008?
If SQL Server 2012 you can use the WITH RESULT SETS feature.
Otherwise this isn't possible it would require you to insert the results into some kind of intermediate temporary table then select from that.
(You could do this without creating the temp table explicitly by using OPEN ROWSET however)
You could write your own proc that simply calls the other one, aliases the columns and returns that.
On a side note - why does the case of the column names matter to you?