Drop several stored procs in SSMS - sql-server

I have about 100 temporary stored procs in my database. How can I quickly drop all stored procs that have 'tempZZZ' in their names?

DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += N'DROP PROCEDURE dbo.'
+ QUOTENAME(name) + ';
' FROM sys.procedures
WHERE name LIKE N'tempZZZ%'
AND
SCHEMA_NAME(schema_id) = N'dbo';
EXEC sp_executesql #sql;

One method is to get SQL Server to generate your SQL using the system tables:
SELECT 'DROP PROCEDURE ['+name+']'
FROM sys.procedures
WHERE name LIKE '%tempZZZ%'
Then paste the output of that into your SSMS window and run it. You may need to modify it if you have procedures in different schemas.
Warning: Make sure you check the output before you run it!

Related

Could not find stored procedure 'sp_msforeachtable' while looping through server for stats (SSMS)

I've written this to loop through each database on a server, collecting the statistics for each table and storing them in a temp table. Eventually, I'll integrate this into a more permanent structure, but for now I'm just trying to get this working. My problem is, after 57 databases, I get the error stating it can't find the stored procedure sp_msforeachtable.
I've verified that this stored procedure exists on every database on the server and on the server level.
I've excluded this database in the findings by adding it to the "where name not in" condition, and it just moves to the next one in the list and gives the same error.(I've confirmed it exists on the next database also). I've actually done this for the next 6 databases.
This is causing me to not collect accurate information. Am I running out of resources somewhere?
DECLARE #Database TABLE (DbName SYSNAME);
IF OBJECT_ID('tempdb.dbo.#TableLvlSizes', 'U') IS NOT NULL
BEGIN
PRINT 'dropping table'
DROP TABLE tempdb.dbo.#TableLvlSizes;
END
CREATE TABLE #TableLvlSizes (
TableName nvarchar(128)
,NumberOfRows varchar(50)
,ReservedSpace varchar(50)
,TableDataSpace varchar(50)
,IndexSize varchar(50)
,unused varchar(50))
DECLARE #DbName AS SYSNAME;
DECLARE #Sql1 AS VARCHAR(MAX);
SET #DbName = '';
INSERT INTO #Database (DbName)
SELECT NAME
FROM sys.databases
where name not in ('tempdb')
ORDER BY NAME ASC;
WHILE #DbName IS NOT NULL
BEGIN
SET #DbName = (
SELECT MIN(DbName)
FROM #Database
WHERE DbName > #DbName
);
print #DbName;
SET #Sql1 =
'USE ' + #DbName + '; ' + '
Exec sp_msforeachtable
''insert into #TableLvlSizes exec sp_spaceused [?]''
'
Exec (#SQL1);
END
If someone is using Azure SQL, they will not find sp_MSforeachtable since it is not available in Azure SQL.
You may need to create one for yourself.
Since you already verified that the stored procedure does in fact exist, I believe your database is case sensitive. Therefore, the error is still accurate. Basically, the stored procedure with the case you used does not exist. The actual procedure name is sp_MSforeachtable
In your code, you are using the following:
Exec sp_msforeachtable
If you change your code to use the proper case for the stored procedure to be sp_MSforeachtable, it should work:
SET #Sql1 =
'USE ' + #DbName + '; ' + '
Exec sp_MSforeachtable
''insert into #TableLvlSizes exec sp_spaceused [?]'''

SQL Studio Prepared Statement

I am doing work for a company that stores each of their client's info in a different database. When a table needs modification, I have to go to each database and run the ALTER TABLE script. Is there a way I can use a prepared statement to run through all 100+ DBO names?
ALTER TABLE ?.dbo.profileTable
ADD COLUMN profileStatus int
where ? = 'CompanyA, CompanyB, CompanyC' or something similar?
Use Sp_MSforeachdb
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; alter query'
[?] is used as a placeholder for the heretofore unspecified database name
You can modify the query as per your needs ,to exclude system databases use like below..
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; IF DB_ID(''?'') > 4 begin yourquery end'
This will exclude any database that does not have the table you are looking for including system databases.
Declare #TableName Varchar(8000) = 'ProfileTable'
Declare #Sql Varchar(8000)
Select #Sql = Stuff(
(Select ';', 'Alter Table ' + Name + SqlText
From sys.databases
Cross Apply (Select '.dbo.profileTable ADD profileStatus int' SqlText) CA
Where Case When State_Desc = 'ONLINE'
Then Object_Id (QuoteName(Name) + '.[dbo].' + #TableName, 'U')
End Is Not Null
FOR XML PATH('')
),1,1,'')
Exec (#Sql)
This ? before is database ([database].[schema].[table]). Thus you can use sp_MSforeachdb or, as I prefer, use sys.databases view to prepare dynamic queries.
Beware, both methods can interfere with system databases.
Take a look at this solution:
DECLARE #query nvarchar(MAX)='';
SELECT #query = #query + 'USE '+QUOTENAME(name)+';ALTER TABLE dbo.profileTable ADD profileStatus int;'
FROM sys.databases
WHERE OBJECT_ID(QUOTENAME(name)+'.dbo.profileTable', 'U') IS NOT NULL
EXEC(#query)
It adds column col1 int to each dbo.profileTable in every database.

Find All Empty Tables Named MAP_ALERT In All Databases On Server

We perform studies at my job, and each study has its own database. All the study databases are on the same server, and eaxch has a table named MAP_ALERT.
I need to find all MAP_ALERT tables that contain no data, for all the study databases. I found this page that tells how to find empty tables in one database: Select all empty tables in SQL Server - how can I adapt this to find ALL empty tables named MAP_ALERT in ALL database on a given server?
You can use dynamic sql here to help you out. This is querying the system tables for each database. This will even properly handle databases that don't have that table.
declare #SQL nvarchar(MAX)
set #SQL = '';
create table #Results
(
DBName sysname
)
select #SQL = #SQL + 'if exists(select * from ' + name + '.sys.tables where name = ''MAP_ALERT'') insert #results (DBNAME) select ''' + name + ''' from ' + name + '.dbo.MAP_ALERT having count(*) > 0;'
from sys.databases
--select #SQL
--uncomment the following when you have evaluated the dynamic sql and understand what query is going to run on your system
exec sp_executesql #SQL
select * from #Results

How do I truncate a table via linked server using a synonym for the table name?

I know I can do the following:
EXEC Server_Name.DBName.sys.sp_executesql N'TRUNCATE TABLE dbo.table_name'
But what if I want to use a synonym for the table?
I'm on SERVER1 and I want to truncate a table on SERVER2 using a synonym for the table name.
Is this possible?
My workaround was using the synonyms table to lookup underlying table name, then running a dynamic SQL statement. It is documented that synonyms cannot be used with TRUNCATE, but at least this is a decent workaround.
DECLARE #TableName VARCHAR(500) = (SELECT TOP 1 base_object_name
FROM Server_Name.DBName.sys.synonyms WHERE name = 'table_name')
DECLARE #Sql NVARCHAR(MAX) = 'EXEC Server_Name.DBName.sys.sp_executesql N''TRUNCATE TABLE ' + #TableName + ''''
EXEC sys.sp_executesql #Sql
Create a Stored Procedure in Server2 Database for Truncate Tables then call the Stored Procedure from Server1.
Like this:
EXEC [Server2].[DBName].[SchemaName].sp_TruncateTable;

Dynamically named temp table returns "invalid object name" when referenced in stored procedure

When I run the following code, I get an "invalid object name" error, any idea why?
I need to create a dynamically named temp table to be used in a stored procedure.
DECLARE #SQL NVARCHAR(MAX)
DECLARE #SessionID NVARCHAR(50)
SET #SessionID = 'tmp5l7g9q3l1h1n5s4k9k7e'
;
SET
#SQL = N' CREATE TABLE #' + #SessionID + ' ' +
N' (' +
N' CustomerNo NVARCHAR(5), ' +
N' Product NVARCHAR(3), ' +
N' Gross DECIMAL(18,8) ' +
N' )'
;
EXECUTE sp_executesql #SQL
;
SET
#SQL = N' SELECT * FROM #' + #SessionID
;
EXECUTE sp_executesql #SQL
Thanks!
WHY MESS WITH THE NAMES? Let SQL Server will manage this for you:
Temporary Tables in SQL Server
from the above link:
If the same routine is executed simultaneously by several processes,
the Database Engine needs to be able to distinguish between the
identically-named local temporary tables created by the different
processes. It does this by adding a numeric string to each local
temporary table name left-padded by underscore characters. Although
you specify the short name such as #MyTempTable, what is actually
stored in TempDB is made up of the table name specified in the CREATE
TABLE statement and the suffix. Because of this suffix, local
temporary table names must be 116 characters or less.
If you’re interested in seeing what is going on, you can view the
tables in TempDB just the same way you would any other table. You can
even use sp_help work on temporary tables only if you invoke them from
TempDB.
USE TempDB
go
execute sp_Help #mytemp
or you can find them in the system views of TempDB without swithching
databases.
SELECT name, create_date FROM TempDB.sys.tables WHERE name LIKE '#%'
You are doing it wrong!
Try:
exec(#SQL)
instead of:
EXECUTE sp_executesql #SQL
To use sp_executesql the variable must be inside #SessionID the quotes and it must be provided has input parameter. Check this for a full example!
You've to be aware that Dynamic SQL is a good port for SQL injections!
This syntax works
CREATE TABLE #SessionID (CustomerNo NVARCHAR(5), Product NVARCHAR(3), Gross DECIMAL(18,8));
Select COUNT(*) from #SessionID;
Drop Table #SessionID;

Resources