sys.objects [name] column is not consistent with object name in definition (stored procedure name) - sql

Last week, as a part of one requirement, I wrote a script to generate object definition for all database objects.
While testing, I found that for few stored procedures, [sys.objects].name was not matching with name in actual object definition (as returned by OBJECT_DEFINITION(Object_ID)). It was very strange and I saw it first time in life.
While thinking for what could be the reason of same, I found that it happens when we rename stored procedure from Object Explorer (View--> Object Explorer in SQL Server Management studio).
Just wondering, is there any way to retrieve actual object name (in this case, SP name)?

I had the same problem. It appears SP_RENAME doesn't update the object definition. From the sp_rename link, microsoft says:
Renaming a stored procedure, function, view, or trigger will not change the name of the corresponding object either in the definition column of the sys.sql_modules catalog view or obtained using the OBJECT_DEFINITION built-in function. Therefore, we recommend that sp_rename not be used to rename these object types. Instead, drop and re-create the object with its new name.

I had a similar situation, where a stored procedure had been renamed using sp_rename. The new name used was iterative, with an extension of *_1. If the original name was 'MyProcedure', the new name would have been 'MyProcedure_1'.
'MyProcedure' represented the production code. 'MyProcedure_1' represented code that had been production code at one time, but was now obsolete. Indeed, 'MyProcedure_1' referenced objects that were no longer present in the database.
When looking at the name in sys.objects, the new name with the extension was there ('MyProcedure_1'), but the object_definition returned the old name ('MyProcedure'), but with the code for 'MyProcedure_1'.
This was discovered via a call to 'MyProcedure', which errored out, due to the missing objects.
The solution was to DROP 'MyProcedure_1', which effectively removed the object_id, and the erroneous object_definition, and reCREATE it. Of course we had to address the missing objects. And - we spread caution about using sp_rename for objects other than tables/columns.

Related

Altering a stored procedure not throwing "Invalid column name" error when that particular column is removed from the table in SQL Server

I have removed a column from a table which is referred in a stored procedure. When I alter that stored procedure, there is no error, but when executing it, an error
Invalid column name
is thrown.
I'm using SSMS 2017
You are looking for functionality called "schema binding". This means that if you cannot change the schema of an object if it is being referenced in a view or stored procedure.
This is handled on the dependent level, rather than on the original object. The place to start is with the documentation on SCHEMABINDING.
In practice, this means the following procedure:
Alter the object (i.e. table).
Get a schema binding error.
Drop the schemabinding option on all objects that refer to the original object.
Modify the original object.
Modify the dependent objects.
Be sure schema binding is back "on" the dependent objects.
It is a bit cumbersome, but it helps enforce database dependencies.

Is there any major issue in using EXEC sp_rename '<source table name>', '<destination table name>'?

I recently used - EXEC sp_rename '<source table name>', '<destination table name>' to rename an existing table and want to execute the same on one of our live server. Is there any issue in using this procedure to rename a table?. I am asking this because one of our DBA says there will be problems in using this procedure on live server.
Is nothing referencing the table you're renaming? That would be the only instance where I would think renaming the table would not have an impact. If the table was not referenced by anything however, what would be the purpose of the table?
you can read more about sp_rename here:
http://msdn.microsoft.com/en-us/library/ms188351.aspx
Specifically note the following:
Renaming an object such as a table or column will not automatically
rename references to that object. You must modify any objects that
reference the renamed object manually. For example, if you rename a
table column and that column is referenced in a trigger, you must
modify the trigger to reflect the new column name. Use
sys.sql_expression_dependencies to list dependencies on the object
before renaming it.
There is no major issue with renaming the table using that procedure. The only thing you need to remember is that while that command is being executed, the locks that are applied on that table won't allow you to query the data, but that should only take only a couple of milliseconds, so you should be fine.
P.S. Don't forget to modify your views, procedures, functions etc :)
Below is the only caution as described inthe microsoft official web site.
Changing any part of an object name can break scripts and stored procedures. We recommend you do not use this statement to rename stored procedures, triggers, user-defined functions, or views; instead, drop the object and re-create it with the new name.
More details at : http://msdn.microsoft.com/en-us/library/ms188351.aspx
EXEC sp_rename is recommended only when we sure that all the depended SP, View function are not get affected. Make sureyou changed or deleted the depended objects.
Perhaps your DBA can share the details of his/her concerns. Renaming a table will of course be a breaking change for any objects that reference the table so you'll need to perform due diligence to ensure dependent objects are changed to use the new name. The rename operation will also require a short schema modification lock and void existing referencing cached plans, so be aware of this if the table is heavily used.

SQL dot notation

Can someone please explain to me how SQL Server uses dot notation to identify
the location of a table? I always thought that the location is Database.dbo.Table
But I see code that has something else in place of dbo, something like:
DBName.something.Table
Can someone please explain this?
This is a database schema. Full three-part name of a table is:
databasename.schemaname.tablename
For a default schema of the user, you can also omit the schema name:
databasename..tablename
You can also specify a linked server name:
servername.databasename.schemaname.tablename
You can read more about using identifiers as table names on MSDN:
The server, database, and owner names are known as the qualifiers of the object name. When you refer to an object, you do not have to specify the server, database, and owner. The qualifiers can be omitted by marking their positions with a period. The valid forms of object names include the following:
server_name.database_name.schema_name.object_name
server_name.database_name..object_name
server_name..schema_name.object_name
server_name...object_name
database_name.schema_name.object_name
database_name..object_name
schema_name.object_name
object_name
An object name that specifies all four parts is known as a fully qualified name. Each object that is created in Microsoft SQL Server must have a unique, fully qualified name. For example, there can be two tables named xyz in the same database if they have different owners.
Most object references use three-part names. The default server_name is the local server. The default database_name is the current database of the connection. The default schema_name is the default schema of the user submitting the statement. Unless otherwise configured, the default schema of new users is the dbo schema.
What #Szymon said. You should also make a point of always schema-qualifying object references (whether table, view, stored procedure, etc.) Unqualified object references are resolved in the following manner:
Probe the namespace of the current database for an object of the specified name belonging to the default schema of the credentials under which the current connection is running.
If not found, probe the namespace of the current database for an object of the specified name belonging to the dbo schema.
And if the object reference is to a stored procedure whose name begins with sp_, it's worse, as two more steps are added to the resolution process (unless the references is database-qualified): the above two steps are repeated, but this time, looking in the database master instead of the current database.
So a query like
select *
from foo
requires two probes of the namespace to resolve foo (assuming that the table/view is actually dbo.foo): first under your default schema (john_doe.foo) and then, not being found, under dbo (dbo.foo'), whereas
select *
from dbo.foo
is immediately resolved with a single probe of the namespace.
This has 3 implications:
The redundant lookups are expensive.
It inhibits query plan caching, as every execution has to be re-evaluated, meaning the query has to be recompiled for every execution (and that takes out compile-time locks).
You will, at one point or another, shoot yourself in the foot, and inadvertently create something under your default schema that is supposed to exist (and perhaps already does) under the dbo schema. Now you've got two versions floating around.
At some point, you, or someone else (usually it happens in production) will run a query or execute a stored procedure and get...unexpected results. It will take you quite some time to figure out that there are two [differing] versions of the same object, and which one gets executed depends on their user credentials and whether or not the reference was schema-qualified.
Always schema-qualify unless you have a real reason not to.
That being said, it can sometimes be useful, for development purposes to be able to maintain the "new" version of something under your personal schema and the "current" version under the 'dbo' schema. It makes it easy to do side-by-side testing. However, it's not without risk (which see above).
When SQL sees the syntax it will first look at the current users schema to see if the table exists, and will use that one if it does.
If it doesn't then it looks at the dbo schema and uses the table from there

SQL Error with Typed Table

I'm using a user defined table type to pass into my stored proc.
I've had cause to change the table type to add an extra column, and now I get the error:
The parameter "#MyParam" is not the same type as the type it was
created with. Drop and recreate the module using a two-part name for
the type, or use sp_refreshsqlmodule to refresh its parameters
metadata.
when calling the proc from my .net code.
I am adding the param value to my command like so:
var param = _command.Parameters.AddWithValue("#MyParam" , myTypedDataTable)
param.SqlDbType = SqlDbType.Structured;
where myTypedDataTable has been updated to contain the new column.
I have tried dropping and recreating the stored proc that is called, as well as dropping and recreating the User Defined Table.
I have also (thanks to Google) tried to use sys.sp_refreshsqlmodule on my Stored Proc and User Defined Table (It did not work however, on the User Defined Table, giving me the error: "Could not find object '[myUserDefinedTable]' or you do not have permission.", I beleieve this may be due to sys.sp_refreshsqlmodule not being able to work on user defined tables?)
I think I am probably missing something basic here, but can't see what?
I have found the error. There was another stored proc which relied on the user defined table which needed to be dropped and recreated. I'm surprised that this was missed, as when I tried to drop the user defined table first time around, It did not let me as the SP mentioned above referenced it (I had to drop the SP to remove the dependency, then drop the User Defined Table, and then recreate them both), yet it did not complain about a dependency for the newly found SP?
Try to specify the TypeName for the parameter:
param.TypeName = "dbo.YourTableDefinition";

Rename a stored procedure in SQL Server

I'm attempting to rename a stored procedure in SQL Server 2008 with sp_rename system sproc. The third parameter is giving me difficulty though and I keep receiving the following error:
Msg 15249, Level 11, State 1, Procedure sp_rename, Line 75
Error: Explicit #objtype 'P' is unrecognized.
As the message indicates I'm passing in a P for the value of the parameter. I call the sproc like this:
EXEC sp_rename #objName = #procName, #newname = #WrappedName, #objtype = 'P';
I double checked the documentation which says this is the value from sys.objects. I ran the following to double check I wasn't going crazy
select * from sys.objects where name = 'MySprocName'
and indeed the type returned is P.
Does anyone know what I should pass here? I don't want to leave this empty since I'm creating a generic sproc to among other things rename arbitrary sprocs and if there is a name collision between a sproc and something else I don't want to have to worry about that.
Just omit the #objtype parameter (the default is null) and it will work.
EXEC sp_rename 'sp_MyProc', 'sp_MyProcName'
You will receive the following warning, but the procedure will be renamed
Caution: Changing any part of an
object name could break scripts and
stored procedures.
Like others stated, you should drop and recreate the procedure.
According to the docs, 'P' is not a correct option. You should try 'OBJECT' as that seems like the closest thing to what you're trying to do. But, you should heed this warning ...
Changing any part of an object name
can break scripts and stored
procedures. We recommend you do not
use this statement to rename stored
procedures, triggers, user-defined
functions, or views; instead, drop the
object and re-create it with the new
name.
Also (from the same MSDN page):
Renaming a stored procedure, function, view, or trigger will not
change the name of the corresponding object name in the definition
column of the sys.sql_modules catalog view. Therefore, we recommend
that sp_rename not be used to rename these object types. Instead, drop
and re-create the object with its new name.
sp_rename does not support procedures:
Changes the name of a user-created
object in the current database. This
object can be a table, index, column,
alias data type, or Microsoft .NET
Framework common language runtime
(CLR) user-defined type.
Just create the new procedure with the same body and new name, then drop the old one.
I'm not sure about the #objtype variable, however I do know that renaming via sp_rename is bad.
When you create a stored proc, a record for it exists in sys.objects and the definition of the stored proc will be stored in sys.sql_modules.
Using sp_rename will only change the name in sys.objects, not in sys.sql_modules thus your definition will be incorrect.
The best solution is a drop & recreate
The third parameter(#objtype) is required when you want to rename a
database object other than a stored procedure. Otherwise it is
necessary to pass a third parameter. For example renaming a column
using sp_rename will look something like this.
USE AdventureWorks2012;
GO
EXEC sp_rename 'Sales.SalesTerritory.TerritoryID', 'TerrID', 'COLUMN';
GO
To rename a user-defined stored procedure using sp_rename,you can do something like this and it literally works
However it is not recommended by Microsoft, DB experts (and others here as well) to use this stored procedure as it will break things internally and might possibly incur unusual results later.Therefore it is bad. Here's what Microsoft has to say:
Renaming a stored procedure, function, view, or trigger will not change the name of the corresponding object either in the definition column of the sys.sql_modules catalog view or obtained using the OBJECT_DEFINITION built-in function. Therefore, we recommend that sp_rename not be used to rename these object types. Instead, drop and re-create the object with its new name.
Renaming an object such as a table or column will not automatically rename references to that object. You must modify any objects that reference the renamed object manually. For example, if you rename a table column and that column is referenced in a trigger, you must modify the trigger to reflect the new column name. Use sys.sql_expression_dependencies to list dependencies on the object before renaming it.
You can read about it here: sp_rename (Transact-SQL)
There are two approaches to rename stored procedure.
Dropping and Recreating Procedure : The problem is it will lead to losing of permissions.
sp_rename of Procedure : Permissions will remain intact. The stored procedure will be renamed. But, sys.sql_modules will still be having the old definition.
I prefer the second approach. I followed the below steps:
Have copy of the stored Procedure content
Rename the stored procedure
EXEC sp_rename 'dbo.OldStoredProcedureName','NewStoredProcedureName'
GO
ALTER PROCEDURE to have the modified code of the procedure in the sys.sql_modules
ALTER PROCEDURE dbo.NewStoredProcedureName
...
Now, Stored procedure name is also updated and code is refreshed in sys.sql_modules and permissions are also intact.
In SQL 2000 days, it was safer to DROP/CREATE-- SQL used to let the meta data for the proc get out of synch when you use sp_rename.
The best way to find out how to do fancy DDL like that is to use SSMS to rename the object while a profiler trace is attached.
All that Valentino Vranken said is true. However bear in mind that when you drop and create a stored procedure, you lose all of your metadata. (Create_Date, Modify_Date etc.)
Renaming a stored procedure, function, view, or trigger will not change the name of the corresponding object name in the definition column of the sys.sql_modules catalog view. Therefore, we recommend that sp_rename not be used to rename these object types. Instead, drop and re-create the object with its new name.
This is also true. However I found that when you run the alter script after making the rename, it corrects the name in the definition in the modules.
I have wondered how the SSMS interface does all of this automagically without using T-SQL. (Perhaps it runs an alter script each time you rename an SP using the interface? I don't know.) It would be interesting is MS were to publish what is happening behind the scenes when you do a SSMS rename.
sp_rename only change the name of user created objects in database. Renaming a stored procedure will not change the name of the corresponding object name in the definition column of the sys.sql_modules catalog view.
Therefore, we recommend that you do not rename this object type. Instead, drop and re-create the stored procedure with its new name.
even you should not use it use to rename to change to change the name of view, function,or trigger.
If you will try to use, it will rename it, but you will also get some warning message something like this:
Changing any part of an object name can break scripts and stored procedures.
For more information you can visit.
http://onlyforcoder.blogspot.in/2017/11/sprename-where-to-use-where-not-to-use.html
http://blog.sqlauthority.com/2008/08/26/sql-server-how-to-rename-a-column-name-or-table-name/