I have 10 stored procedures they are different with their definition in sys_modules. I find them with this query:
select
b.definition, a.name
from
sysObjects a
left outer join
sys.sys_modules b on b.id = a.object_id
where
b.definition not like '%' + b.name + '%'
Could someone tell me why this happens?
It's the second time I faced this problem.
This happens if you use sp_rename and is explicitly called out in the documentation
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.
Note that the rename functionality in SSMS object explorer does in fact call this procedure.
Use INFORMATION_SCHEMA.ROUTINES and get the ROUTINE_DEFINITION column for stored procedures
Related
Some time ago the procedure ALF_GetPopulationForPolygon_2_old was created. Then in SSMS, it was renamed (right mouse button -> rename) to the procedure ALF_GetPopulationForPolygon_2_old_FOR_DELETE_20170504. Renaming passed normally, but as a result, the query:
SELECT
sm.definition
FROM
sys.objects AS o
INNER JOIN sys.sql_modules AS sm
ON ( 1 = 1 )
AND ( sm.object_id = o.object_id )
WHERE
( 1 = 1 )
AND ( o.name like 'ALF_GetPopulationForPolygon_2_old_FOR_DELETE_20170504' )
And calling the stored procedure:
EXEC sp_helpText 'ALF_GetPopulationForPolygon_2_old_FOR_DELETE_20170504'
Return the following text:
...
CREATE PROCEDURE [dbo]. [ALF_GetPopulationForPolygon_2]
...
Those show the OLD(!) name of the procedure. Do you have any idea what this is caused, and how can this be fixed?
You shouldn't rename your objects for at least two reasons.
If you'd use a T_SQL command instead of GUI (all that you "clicks" in Management Studio produces T-SQL coede behind the scenes), you'd get a warning, the same you can see in BOL article:
sp_rename (Transact-SQL)
CAUTION 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.
And it was the first reason against renaming.
Scrolling the article find the Remarks section:
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.
And this was the second.
So when you want to rename your procedure you should script your procedure as CREATE and change the procedure name, doing so you recreate your proc with the new name and then you can drop the old one
Can someone quickly explain to me (as in without directing me to an illegible mountain of documentation) what a construct such as this (below) means in a SQL Server stored procedure?
Note, this is in a stored procedure on a database which resides on a server with many other databases and this is a generalization not the exact query
INSERT INTO [schema].TableName (Field1, Field2)
SELECT
OtherField1,
OtherField2
FROM
#Something TMP
INNER JOIN
[schema].[Field] A ON A.Whatever = TMP.Whatever;
Note: I've been using MySQL and Postgres for years so understand the basics, but this SQL Server has a lot of features that are new to me. What I can tell here is that we are filling a table with the results from another table (or something) and that is what I want to know. What is the or something? In this example, what does #Something actually reference?
I am aware of linked servers, but I don't see one in this system with the name referenced. And I also don't see any definition in this stored procedure of what #Something references.
One thought I had was that perhaps a stored procedure can use another stored procedure and in that way perhaps this #Something is defined in the calling procedure? Is this even possible?
This indicates that the table in question is a temp table.
You can find the table by checking the system database.
SELECT *
FROM tempdb.sys.table
WHERE name LIKE '#something%'
You can find other procedures that reference the same table by using the following query.
DECLARE #s VARCHAR(255) = '#Something';
SELECT DISTINCT
O.name sproc_name,
O.type_desc,
(
SELECT TOP (1)
SUBSTRING(definition,CHARINDEX(#s,definition),100)
FROM sys.sql_modules
WHERE object_id=M.object_id
AND CHARINDEX(#s,definition)>0
) DEF
FROM sys.sql_modules M
JOIN sys.objects O
ON M.object_id=O.object_id
WHERE M.definition LIKE '%' + #s + '%'
ORDER BY 2,1;
Object names that start with a # are temporary objects. A single # means that the object is limited to the local scope (so therefore must have been created in the same scope of a parent of it), and 2 (or more) #s at the start denote "global" temporary objects, where they can be referenced in any scope.
Either way, a temporary object is dropped once the scope that created it ends or the object is no longer in use (which ever is last).
Some time ago the procedure ALF_GetPopulationForPolygon_2_old was created. Then in SSMS, it was renamed (right mouse button -> rename) to the procedure ALF_GetPopulationForPolygon_2_old_FOR_DELETE_20170504. Renaming passed normally, but as a result, the query:
SELECT
sm.definition
FROM
sys.objects AS o
INNER JOIN sys.sql_modules AS sm
ON ( 1 = 1 )
AND ( sm.object_id = o.object_id )
WHERE
( 1 = 1 )
AND ( o.name like 'ALF_GetPopulationForPolygon_2_old_FOR_DELETE_20170504' )
And calling the stored procedure:
EXEC sp_helpText 'ALF_GetPopulationForPolygon_2_old_FOR_DELETE_20170504'
Return the following text:
...
CREATE PROCEDURE [dbo]. [ALF_GetPopulationForPolygon_2]
...
Those show the OLD(!) name of the procedure. Do you have any idea what this is caused, and how can this be fixed?
You shouldn't rename your objects for at least two reasons.
If you'd use a T_SQL command instead of GUI (all that you "clicks" in Management Studio produces T-SQL coede behind the scenes), you'd get a warning, the same you can see in BOL article:
sp_rename (Transact-SQL)
CAUTION 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.
And it was the first reason against renaming.
Scrolling the article find the Remarks section:
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.
And this was the second.
So when you want to rename your procedure you should script your procedure as CREATE and change the procedure name, doing so you recreate your proc with the new name and then you can drop the old one
I need to log the stored procedure name to determine which stored procedure are being used.
To accomplish this I am embedding an insert statement in each of the stored procedures we have to log it's usage.
I could hard code the SP name in the INSERT statement but I am looking for an elegant way to get the current stored procedure name rather than hard coding, this is primarily to be able to search for and remove identical lines of code after the project.
I have a table called tblUsed (ID INT, dateused date, sprocused varchar(50)) and was planning to do an insert in each query.
INSERT INTO [stockist].[dbo].[tblUsed]
([objectName])
VALUES
(*procname*)
I just need to get the name of the proc for this to work.
If there are any other ways to accomplish this I would be happy to hear them.
Thank you in advance.
Let's look at this from the ground up for you.
To get the name of the stored procedure you need to run the OBJECT_NAME(object_id [, database_id ]) metadata function(more info here). As you are running this T-SQL within the object in question, you won't need the database_id so the code you'll run will look something like this:
OBJECT_NAME(*object_id*)
To get the object id for the current T-SQL module you will need to use the ##PROCID metadata function(more info here) giving you the following code:
OBJECT_NAME(##PROCID)
In this case your INSERT statement will look like this:
INSERT INTO tblUsed (sprocused)
VALUES (OBJECT_NAME(##PROCID))
If you use multiple schema's you will probably need to be record which schema you are in using the OBJECT_SCHEMA(object_id [, database_id ]) metadata function(more info here) giving you this:
OBJECT_SCHEMA_NAME(##PROCID) + '.' + OBJECT_NAME(##PROCID)
In this case your INSERT statement will look like this:
INSERT INTO tblUsed (sprocused)
VALUES (OBJECT_SCHEMA_NAME(##PROCID) + '.' + OBJECT_NAME(##PROCID))
One other possible way to accomplish this without all the overhead of an unnecessary insert in all your queries is through the use of DMVs(Dynamic management views) here is a sample query (from this SO thread)
SELECT sc.name
, p.name
FROM sys.procedures AS p
INNER JOIN sys.schemas AS sc
ON p.[schema_id] = sc.[schema_id]
LEFT OUTER JOIN sys.dm_exec_procedure_stats AS st
ON p.[object_id] = st.[object_id]
WHERE st.[object_id] IS NULL
ORDER BY p.name;
NB: This will only give you the information from the last time SQL was restarted.
As a result of this question you might want to ensure that none of your procs are referenced anywhere else in the db you can do this like so:
SELECT referencing_schema_name
, referencing_entity_name
FROM sys.dm_sql_referencing_entities ('*schemaname.objectname*', 'OBJECT');
I am in the process of changing the schema of a couple of tables. Currently all the tables are in the dbo schema and need to be moved into a different schema.
I have run the following script ( on many tables):
ALTER SCHEMA client TRANSFER dbo.Companies
The issue I have now is that there are stored procedures that ned to be updated to use the correct table name
dbo.Companies -> client.Companies
Is there any way one can check which stored procedures need to be checked and fixed?
There might be a best method since this one needs some manual editing but here is what I would do.
I have a small query that lets me search stored procedure for a string.
SELECT
sysobjects.name
,sysobjects.id
,sysobjects.xtype
FROM
sysobjects
INNER JOIN
syscomments
ON
sysobjects.id = syscomments.id
WHERE
syscomments.text LIKE '%dbo.Companies%'
GROUP BY
sysobjects.name
,sysobjects.id
,sysobjects.xtype
order by
sysobjects.name
The query will give you the name, id and xtype of all stored procedures containing dbo.Companies. If you change the WHERE-clause to look for all the tables you moved to the other scheme you will (hopefully :) ) get a list of all stored procedures you need to update.
If you want you can probably modify the query and update the stored procedure body with REPLACE and have it all automated. But make sure the query gives you the correct results first. I did not use it for this use case, I simply use it to search for text in stored procedure but theoretically it should work.
This will give you all objects that depend on dbo.companies. Please do remember that you will also need to change functions, views and other objects as well, apart from the stored procedures.
SELECT Db_name() referencing_database_name,
Object_name (referencing_id) referencing_entity_name,
Isnull(referenced_schema_name, 'dbo') referenced_schema_name,
referenced_entity_name,
ao.type_desc referenced_entity_type,
Isnull(referenced_database_name, Db_name()) referenced_database_name
FROM sys.sql_expression_dependencies sed
JOIN sys.all_objects ao
ON sed.referenced_entity_name = ao.name
WHERE sed.referenced_schema_name='dbo' AND sed.referenced_entity_name='Companies'
following are the way can check the depedencies
Method 1: Using sp_depends
sp_depends 'dbo.First'
GO
Method 2: Using information_schema.routines
SELECT *
FROM information_schema.routines ISR
WHERE CHARINDEX('dbo.First', ISR.ROUTINE_DEFINITION) > 0
GO
Method 3: Using DMV sys.dm_sql_referencing_entities
SELECT referencing_schema_name, referencing_entity_name,
referencing_id, referencing_class_desc, is_caller_dependent
FROM sys.dm_sql_referencing_entities ('dbo.First', 'OBJECT');
GO