What does # indicate in SQL Server SELECT FROM? - sql-server

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).

Related

Find procedures referencing a column and not another column containing the same name?

There are many methods here for finding all stored procedures in SQL Server containing some specified text but I'd like something a bit different.
Suppose I want to find all procedures referencing the column named defg, but I don't want that procedure listed if it references only column abcdefg. If it contains both then I want it, but if it only contains abcdefg then it doesn't reference column defg so I am not interested in it.
Try this
DECLARE #ColName sysname = 'MyTable.defg'
SELECT OBJECT_NAME(object_id) AS stored_proc, is_selected, is_updated, is_select_all
FROM sys.sql_dependencies
WHERE OBJECT_NAME(referenced_major_id) = PARSENAME(#ColName, 2)
AND COL_NAME(referenced_major_id, referenced_minor_id) = PARSENAME(#ColName, 1)
AND OBJECTPROPERTYEX(object_id, 'BaseType') = 'P'
ORDER BY 1
This might miss stored procedures which use deferred name resolution on queries that reference your column e.g. if you create temp tables in a stored procedure and then JOIN some of these tables with your base table the stored procedure will use deferred name resolution and your base table + column might not end up in sys.sql_dependencies so the query above will miss the stored procedure.

SQL Server stored prcedure definition is different with sys_modules.definition

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

Accessing the name of the currently executing stored procedure name via T-SQL?

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');

How to determine the SQL Server object name from object id and database id?

I need the behaviour of SQL Server 2005 where function OBJECT_NAME takes two arguments, obj id and db id, while SQL Server 2000 takes only obj id so the execution must be in the context of the database to which inspected object belongs to.
Solution must be possible to implement in a function, so it can be used in a select query.
In SQL 2005 and up it is of course trivial to do this. The problem is SQL 2000. I used 2000 a lot back when, but no longer have access to any installations of it; the rest of this is largely from memory, and may be inaccurate.
The key thing is how to retrieve data from a database other than the "current" database, when you cannot know what that other database (or databases) will be at the time the code is written. (Yes, the db_id parameter is very convenient!) For this problem and for similar problems, the general work-around is to create dynamic code, something like:
SET #Command = 'select name from ' + #dbname + '.dbo.sysobjects where object_id = ' + #ObjectId
EXECUTE (#Command)
The problem is, I'm pretty sure you can't run dynamic code within functions (or perhaps just within SQL 2000 functions).
You might have to resort to creating a temp table, populating it via dynamic query, and then using it within the "main" query you are trying to write. Psuedo code would be like:
CREATE #TempTable
IF SQL2000 or earlier
INSERT #TempTable EXECUTE (select data from TargetDb.dbo.sysobjects)
-- Note that the entire insert may need to be in the dynamic statement
ELSE
INSERT #TempTable SELECT [from query based on object_id]
SELECT [the data you need]
from YourTable
join #TempTable
In SQL 2008 and up, use:
OBJECT_NAME ( object_id [, database_id ] )
for example:
SELECT TOP 10
object_schema_name(objectid, dbid) as [SchemaName],
object_name(objectid, dbid) as [ObjectName],
e.*
from sys.dm_exec_cached_plans P
CROSS APPLY sys.dm_exec_query_plan(P.plan_handle) E

MSSQL Database Cleanup - How do you find unused objects (Tables, Views, Procs, Functions)

Lets say you have inherited a MS SQL 2000 or 2005 database, and you know that some of the Tables, Views, Procs, and Functions are not actually used in the final product.
Is there some kind of internal logging or another mechanism that could tell me what objects are NOT being called? or have only been called a few times versus thousands of times.
This SO question, Identifying Unused Objects In Microsoft SQL Server 2005, might be relevant.
The answer will depend a little on how the database has been put together, but my approach to a similar problem was 3-fold:
Figure out which objects have no internal dependencies. You can work this out from queries against sysdepends such as:
select
id,
name
from
sys.sysdepends sd
inner join sys.sysobjects so
on so.id = sd.id
where
not exists (
select
1
from
sysdepends sd2
where
sd2.depid = so.id
)
You should combine this with collecting the type of object (sysobjects.xtype) as you'll only want to isolate the tables, functions, stored procs and views. Also ignore any procedures starting "sp_", unless people have been creating procedures with those names for your application!
Many of the returned procedures may be your application's entry points. That is to say the procedures that are called from your application layer or from some other remote call and don't have any objects that depend on them within the database.
Assuming the process won't be too invasive (it will create some additional load, though not too much) you can now switch on some profiling of the SP:Starting, SQL:BatchStarting and / or SP:StmtStarting events. Run this for as long as you see fit, ideally logging into a sql table for easy cross referencing. You should be able to eliminate many of the procedures that are called directly from your application.
By cross referencing the text data from this log and your dependent object list you will hopefully have isolated most of the unused procedures.
Finally, you may want to take your candidate list resulting from this process and grep your sourcecode base against them. This is a cumbersome task and just because you find references in your code doesn't mean you need them! It may simply be that the code hasn't been removed though it's now logically inaccessible.
This is far from a perfect process. A relatively clean alternative is to set up far more detailed (and therefore invasive) profiling on the server to monitor all the activity. This can include every SQL statement called during the time the log is active. You can then work back through the dependent tables or even cross-database dependencies from this text data. I've found the reliability of the log detail (too many rows per second attempting to be parsed) and the sheer quanitity of data difficult to deal with. If your application is less likely to suffer from this then it may be a good approach.
Caveat:
Because, so far as I'm aware, there isn't a perfect answer to this be particularly wary of removing tables. Procedures, functions and views are easily replaced if something goes wrong (though make sure you have them in source control before burning them of course!). If you're feeling really nervous why not rename the table and create a view with the old name, you've then got an easy out.
We can also find unused columns and table using following query. I tired to write cursor. Cursor will give you information aboout each column n each table.
declare #name varchar(200), #id bigint, #columnname varchar(500)
declare #temptable table
(
table_name varchar(500),
Status bit
)
declare #temp_column_name table
(
table_name varchar(500),
column_name varchar(500),
Status bit
)
declare find_table_dependency cursor for
select name, id from sysobjects where xtype ='U'
open find_table_dependency
fetch find_table_dependency into #name, #id
while ##fetch_Status = 0
begin
if exists(select top 1 name from sysobjects where id in
(select id from syscomments where text like '%'+#name +'%'))
insert into #temptable
select #name, 1
else
insert into #temptable
select #name, 0
declare find_column_dependency cursor for
select name from syscolumns where id = #id
open find_column_dependency
fetch find_column_dependency into #columnname
while ##fetch_Status = 0
begin
if exists(select top 1 name from sysobjects where id in
(select id from syscomments where text like '%'+#columnname +'%'))
insert into #temp_column_name
select #name,#columnname, 1
else
insert into #temp_column_name
select #name,#columnname, 0
fetch find_column_dependency into #columnname
end
close find_column_dependency
deallocate find_column_dependency
fetch find_table_dependency into #name, #id
end
close find_table_dependency
deallocate find_table_dependency
select * from #temptable
select * from #temp_column_name

Resources