Get all the table names that are available in all the schemas - sql-server

I do not have names of the schema that are available. According to my finding all the queries that i am using are specific to a schema name. I need name of all the tables irrespective of the schema name.
Can anyone help me with that.
I have used the following queries:
SELECT sch.name AS SchemaName , tbl.name AS TableName FROM sys.tables tbl INNER JOIN sys.schemas sch ON tbl.SCHEMA_ID = sch.SCHEMA_ID ORDER BY tbl.name;
select * from information.schema.tables where TABLE_TYPE='BASE TABLE';
select * from sys.tables;
select * from sysobjects where xtype='U';
All of these queries are schema specific. If we want to switch between schema we have to use USE %SCHEMA_NAME%. but i need to get all the table names irrespective of the schema name.

Apologies, but i meant to say databases
A database and a schema, in SQL Server, are very different objects. A schema is an object within a database, where as a database is on "object" in an instance. The sys and INFORMATION_SCHEMA objects are also database objects and so will only list the objects within the database context they are referenced in.
For example the below 2 examples would both return details of tables in the MyDB database:
USE master;
SELECT *
FROM MyDB.sys.tables;
GO
USE MyDB;
SELECT *
FROM sys.tables;
If you want to get the details of tables in every Database you'll either need to query them separately, or generate and run a dynamic statement. The dynamic approach would be something like this:
USE master;
GO
DECLARE #SQL nvarchar(MAX),
#CRLF nchar(2) = NCHAR(13) + NCHAR(10);
DECLARE #Delimiter nvarchar(30) = #CRLF + N'UNION ALL' + #CRLF;
SET #SQL = (SELECT STRING_AGG(N'SELECT N' + QUOTENAME(d.[name],'''') + N' AS DatabaseName, t.[name] AS TableName FROM ' + QUOTENAME(d.[name]) + N'.sys.tables t', #Delimiter) WITHIN GROUP (ORDER BY d.database_id)
FROM sys.databases d
WHERE d.database_id > 4) + N';' --skip system databases
--PRINT #SQL; --Your best friend
EXEC sys.sp_executesql #SQL;
If you're using an older version of SQL Server, you'll need to use the "old" FOR XML PATH method, rather than STRING_AGG.

Related

Get all stored procedures where table is being used in SQL Server

I need the query or code in SQL Server to get all the stored procedures in which table is being used in the server (need all stored procedures in all databases on that server).
SELECT *
FROM sys.procedures
WHERE OBJECT_DEFINITION(OBJECT_ID) LIKE '%[dbo].[Batch]%.
Above query will give in the current database but I need the query to get from all the databases in that server.
Thanks. Sandeep
Try this:
select * from sysobjects where id in
(select id from syscomments where text like '%myquery%')
order by [name]
where "myquery" is the name of the table. You need to run this on each database on the server individually.
EXECUTE master.sys.sp_MSforeachdb
"USE [?]; SELECT * FROM sys.procedures WHERE OBJECT_DEFINITION(OBJECT_ID) LIKE '%[dbo].[Batch]%'"
Just consider your permutations of the code that references the Batch object (dbo.batch, [dbo].[batch], dbo.[batch], etc)
Thanks for the help. I got that below query will give all Stored Procedures that are dependent on any table or view for all the databases in the server.
DECLARE #SQL NVARCHAR(max)
SELECT #SQL = STUFF((SELECT ' UNION ALL SELECT ' + quotename(NAME, '''') + ' AS Db_Name, Routine_Name collate SQL_Latin1_General_CP1_CI_AS as SP_Name FROM ' + quotename(NAME) + '.INFORMATION_SCHEMA.Routines WHERE ROUTINE_Definition like ''%Replace_Table_Name_Here%'' AND ROUTINE_TYPE = ''PROCEDURE''' FROM sys.databases ORDER BY NAME FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 11, '')
EXECUTE sp_executeSQL #SQL

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

Refactor rename field in many database tables

I am faced with renaming a field where the same fieldname is replicated across many tables.
Looking for a script or free/low cost tool which will go through all the tables and if fieldA exists, rename it to fieldB.
thanks
You can use SQL Server metadata tables to create dynamic sql statements for your purpose.
For list of available tables you can sys.tables for list of tables and sys.columns for list of columns. using these tables you can create a table of sql statements. For executing dynamic sqls you need to sp_executesql stored procedure.
This is a sample code just to show how to use metadata tables and sp_executesql:
And note that I used other metadata tables which I am more comfortable with. also you may use a cursor to run all the scripts returned by query.
CREATE Database TestDB
CREATE Table Table1 (Id int , fieldA varchar(50) )
Declare #update_query nvarchar(max)
select
#update_query = 'sp_rename ''' + t.TABLE_NAME + '.' + c.COLUMN_NAME + ''',''' + 'fieldB' + ''''
From INFORMATION_SCHEMA.COLUMNS c JOIN INFORMATION_SCHEMA.Tables t ON c.TABLE_CATALOG = t.TABLE_CATALOG AND c.TABLE_SCHEMA = t.TABLE_SCHEMA AND c.TABLE_NAME = t.TABLE_NAME
WHERE
c.COLUMN_NAME = 'fieldA'
SELECT #update_query
EXEC sp_executesql #update_query
Take a look at the Database project type in VS2010, if you haven't already. It has a lot of features that make DB refactoring easier than working SQL Server Management Studio.
For example if you rename a column, it will give you build errors for all the FKs that reference the old column name. And it does a lot of build-time validation to make sure your database objects don't reference objects which no longer exist. And because all of the database objects are just kept as text files, actions like rename are pretty much just search/replace.
Also, it has very handy "sync" feature which compares the DB project scripts & databases, generates a DIFF report, and generates the scripts to move selected changes between the two (either DB project to SQL Server, or vice versa).
Having said all that, it won't automatically do the renames for you -- in other words, when you rename a column it won't fix up all references to that column throughout the project. But if you make a mistake you will get build errors when it validates the database structure. So at least makes it easy to find the places that you need to change.
If you're using Azure SQL Server, you can use Sam's answer with another input parameter to sp_rename, #objtype = 'COLUMN'.
Declare #update_query nvarchar(max)
select
#update_query = 'sp_rename ''' + t.TABLE_NAME + '.' + c.COLUMN_NAME + ''',''' + 'fieldB' + ''',''' + 'COLUMN' + ''''
From INFORMATION_SCHEMA.COLUMNS c JOIN INFORMATION_SCHEMA.Tables t ON c.TABLE_CATALOG = t.TABLE_CATALOG AND c.TABLE_SCHEMA = t.TABLE_SCHEMA AND c.TABLE_NAME = t.TABLE_NAME
WHERE
c.COLUMN_NAME = 'fieldA'
SELECT #update_query
EXEC sp_executesql #update_query

In sql server, is there any way to check whether the schema change will impact on the stored procs?

In SQL Server, is there any way to check whether the changes in the schema will impact Stored Procedures (and/or Views)?
For example a change of the column name in one table, may break some Stored Procedures; how to check the impacted stored procs?
try using:
EXEC sp_depends 'YourTableName'
and/or
DECLARE #Search nvarchar(500)
SET #Search='YourTableName' --or anything else
SELECT DISTINCT
LEFT(o.name, 100) AS Object_Name,o.type_desc
FROM sys.sql_modules m
INNER JOIN sys.objects o ON m.object_id=o.object_id
WHERE m.definition Like '%'+#Search+'%'
ORDER BY 2,1
Use Visual Studio Database Edition for your T-SQL development. It will catch such problems during build, as it creates the deployment .dbschema file.
In SSMS (SQL Server Management Studio) right click on the object you are changing and click on View Dependencies. I don't think this will find references from another database.
You can also look for references in stored procedures if they are not encrypted. You would have to do this in each database you suspect might reference the object you are changing.
select objects.name
,sql_modules.definition
from sys.sql_modules sql_modules
join sys.objects objects on sql_modules.object_id = objects.object_id
where definition like '%some column name%';
I have found nothing that is 100.0000% accurate 100.000000% of the time.
Best way I can think to do this is to abstract your stored procedures from your actual tables using views, and to create those views with a "WITH SCHEMABINDING" clause which should prevent changes that will break your views...
Commercial tools such as Red Gate's SQL Refactor can do this.
I think that recent version of Visual Studio also include this kind of features, but I haven't tried.
To my knowledge, there are no built-in features of Microsoft SQL Server per-se which will do this. Correction: I just read about sp_depends in KM's answer to this post... Note that sp_depends's usage is deprecated; it is replaced by sys.dm_sql_referencing_entities and sys.dm_sql_referenced_entities
Also, if the underlying stored procedures use dynamic SQL, the task of detecting dependencies becomes more difficult and prone to "misses".
If you want to change the name of an object or column, then the Smart Rename feature of Red Gate Software's SQL Prompt 5 will generate a script that both performs the rename and updates references to the old name in other objects.
If you're just interested in what depends on a column name, then SQL Prompt 5 also has a Column Dependencies function, where hovering over the column name in a script pops up a window containing a list of objects that refer to the column.
You can download a 14-day trial for free, to see if either of these features works for you.
Paul Stephenson
SQL Prompt Project Manager
Red Gate Software
Have a look at these answers:
Refreshing metadata on user functions t-SQL
SQL Server relationships buried in stored procedures rather than schema
In SQL Server, how can I find everywhere a column is referenced?
How do I find all stored procedures that insert, update, or delete records?
Other than dynamic SQL, using SCHEMABINDING where possible and sp_refreshsqlmodule and sql_dependencies for everything else is very accurate.
If you use SQL Server
You can use this query after your change and find Stored Procedure Or View Or ...
that after your change might get error
USE <Your_DataBase_Name>;
SET NOCOUNT ON;
DECLARE #name NVARCHAR(MAX)
DECLARE #sql NVARCHAR(MAX)
DECLARE #type CHAR(2)
DECLARE #type_desc NVARCHAR(60)
DECLARE #params NVARCHAR(MAX)
DECLARE #tblInvalid TABLE
(
[type_desc] NVARCHAR(60) ,
[name] NVARCHAR(MAX) ,
[error_number] INT ,
[error_message] NVARCHAR(MAX) ,
[type] CHAR(2)
);
DECLARE testSPs CURSOR FAST_FORWARD
FOR
SELECT [name] = OBJECT_NAME(SM.[object_id]) ,
[type] = SO.[type] ,
SO.[type_desc] ,
[params] = ( SELECT (
SELECT CONVERT(XML, ( SELECT STUFF(( SELECT
', ' + [name]
+ '=NULL' AS [text()]
FROM
sys.parameters
WHERE
[object_id] = SM.[object_id]
FOR
XML
PATH('')
), 1, 1, '')
))
FOR XML RAW ,
TYPE
).value('/row[1]', 'varchar(max)')
)
FROM sys.sql_modules SM
JOIN sys.objects SO ON SO.[object_id] = SM.[object_id]
WHERE SO.[is_ms_shipped] = 0
AND SO.[type] = 'P'
OPEN testSPs
FETCH NEXT FROM testSPs INTO #name, #type, #type_desc, #params
WHILE ( ##FETCH_STATUS = 0 )
BEGIN
BEGIN TRY
SET #sql = 'SET FMTONLY ON; exec ' + #name + ' ' + #params
+ '; SET FMTONLY OFF;'
--PRINT #sql;
EXEC (#sql);
END TRY
BEGIN CATCH
PRINT #type_desc + ', ' + #name + ', Error: '
+ CAST(ERROR_NUMBER() AS VARCHAR) + ', ' + ERROR_MESSAGE();
INSERT INTO #tblInvalid
SELECT #type_desc ,
#name ,
ERROR_NUMBER() ,
ERROR_MESSAGE() ,
#type;
END CATCH
FETCH NEXT FROM testSPs INTO #name, #type, #type_desc, #params
END
CLOSE testSPs
DEALLOCATE testSPs
SELECT [type_desc] ,
[name] ,
[error_number] ,
[error_message]
FROM #tblInvalid
ORDER BY CHARINDEX([type], ' U V PK UQ F TR FN TF P SQ ') ,
[name];

How to find a text inside SQL Server procedures / triggers?

I have a linkedserver that will change. Some procedures call the linked server like this: [10.10.100.50].dbo.SPROCEDURE_EXAMPLE. We have triggers also doing this kind of work. We need to find all places that uses [10.10.100.50] to change it.
In SQL Server Management Studio Express, I didn't find a feature like "find in whole database" in Visual Studio. Can a special sys-select help me find what I need?
here is a portion of a procedure I use on my system to find text....
DECLARE #Search varchar(255)
SET #Search='[10.10.100.50]'
SELECT DISTINCT
o.name AS Object_Name,o.type_desc
FROM sys.sql_modules m
INNER JOIN sys.objects o ON m.object_id=o.object_id
WHERE m.definition Like '%'+#Search+'%'
ORDER BY 2,1
You can find it like
SELECT DISTINCT OBJECT_NAME(id) FROM syscomments WHERE [text] LIKE '%User%'
It will list distinct stored procedure names that contain text like 'User' inside stored procedure. More info
[Late answer but hopefully usefull]
Using system tables doesn't always give 100% correct results because there might be a possibility that some stored procedures and/or views are encrypted in which case you'll need to use DAC connection to get the data you need.
I'd recommend using a third party tool such as ApexSQL Search that can deal with encrypted objects easily.
Syscomments system table will give null value for text column in case object is encrypted.
-- Declare the text we want to search for
DECLARE #Text nvarchar(4000);
SET #Text = 'employee';
-- Get the schema name, table name, and table type for:
-- Table names
SELECT
TABLE_SCHEMA AS 'Object Schema'
,TABLE_NAME AS 'Object Name'
,TABLE_TYPE AS 'Object Type'
,'Table Name' AS 'TEXT Location'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%'+#Text+'%'
UNION
--Column names
SELECT
TABLE_SCHEMA AS 'Object Schema'
,COLUMN_NAME AS 'Object Name'
,'COLUMN' AS 'Object Type'
,'Column Name' AS 'TEXT Location'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%'+#Text+'%'
UNION
-- Function or procedure bodies
SELECT
SPECIFIC_SCHEMA AS 'Object Schema'
,ROUTINE_NAME AS 'Object Name'
,ROUTINE_TYPE AS 'Object Type'
,ROUTINE_DEFINITION AS 'TEXT Location'
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%'+#Text+'%'
AND (ROUTINE_TYPE = 'function' OR ROUTINE_TYPE = 'procedure');
This will work for you:
use [ANALYTICS] ---> put your DB name here
GO
SELECT sm.object_id, OBJECT_NAME(sm.object_id) AS object_name, o.type, o.type_desc, sm.definition
FROM sys.sql_modules AS sm
JOIN sys.objects AS o ON sm.object_id = o.object_id
where sm.definition like '%SEARCH_WORD_HERE%' collate SQL_Latin1_General_CP1_CI_AS
ORDER BY o.type;
GO
There are much better solutions than modifying the text of your stored procedures, functions, and views each time the linked server changes. Here are some options:
Update the linked server. Instead of using a linked server named with its IP address, create a new linked server with the name of the resource such as Finance or DataLinkProd or some such. Then when you need to change which server is reached, update the linked server to point to the new server (or drop it and recreate it).
While unfortunately you cannot create synonyms for linked servers or schemas, you CAN make synonyms for objects that are located on linked servers. For example, your procedure [10.10.100.50].dbo.SPROCEDURE_EXAMPLE could by aliased. Perhaps create a schema datalinkprod, then CREATE SYNONYM datalinkprod.dbo_SPROCEDURE_EXAMPLE FOR [10.10.100.50].dbo.SPROCEDURE_EXAMPLE;. Then, write a stored procedure that accepts a linked server name, which queries all the potential objects from the remote database and (re)creates synonyms for them. All your SPs and functions get rewritten just once to use the synonym names starting with datalinkprod, and ever after that, to change from one linked server to another you just do EXEC dbo.SwitchLinkedServer '[10.10.100.51]'; and in a fraction of a second you're using a different linked server.
There may be even more options. I highly recommend using the superior techniques of pre-processing, configuration, or indirection rather than changing human-written scripts. Automatically updating machine-created scripts is fine, this is preprocessing. Doing things manually is awful.
select text
from syscomments
where text like '%your text here%'
This one i tried in SQL2008, which can search from all the db at one go.
Create table #temp1
(ServerName varchar(64), dbname varchar(64)
,spName varchar(128),ObjectType varchar(32), SearchString varchar(64))
Declare #dbid smallint, #dbname varchar(64), #longstr varchar(5000)
Declare #searhString VARCHAR(250)
set #searhString='firstweek'
declare db_cursor cursor for
select dbid, [name]
from master..sysdatabases
where [name] not in ('master', 'model', 'msdb', 'tempdb', 'northwind', 'pubs')
open db_cursor
fetch next from db_cursor into #dbid, #dbname
while (##fetch_status = 0)
begin
PRINT 'DB='+#dbname
set #longstr = 'Use ' + #dbname + char(13) +
'insert into #temp1 ' + char(13) +
'SELECT ##ServerName, ''' + #dbname + ''', Name
, case when [Type]= ''P'' Then ''Procedure''
when[Type]= ''V'' Then ''View''
when [Type]= ''TF'' Then ''Table-Valued Function''
when [Type]= ''FN'' Then ''Function''
when [Type]= ''TR'' Then ''Trigger''
else [Type]/*''Others''*/
end
, '''+ #searhString +''' FROM [SYS].[SYSCOMMEnTS]
JOIN [SYS].objects ON ID = object_id
WHERE TEXT LIKE ''%' + #searhString + '%'''
exec (#longstr)
fetch next from db_cursor into #dbid, #dbname
end
close db_cursor
deallocate db_cursor
select * from #temp1
Drop table #temp1
I use this one for work. leave off the []'s though in the #TEXT field, seems to want to return everything...
SET NOCOUNT ON
DECLARE #TEXT VARCHAR(250)
DECLARE #SQL VARCHAR(250)
SELECT #TEXT='10.10.100.50'
CREATE TABLE #results (db VARCHAR(64), objectname VARCHAR(100),xtype VARCHAR(10), definition TEXT)
SELECT #TEXT as 'Search String'
DECLARE #databases CURSOR FOR SELECT NAME FROM master..sysdatabases where dbid>4
DECLARE #c_dbname varchar(64)
OPEN #databases
FETCH #databases INTO #c_dbname
WHILE ##FETCH_STATUS -1
BEGIN
SELECT #SQL = 'INSERT INTO #results '
SELECT #SQL = #SQL + 'SELECT ''' + #c_dbname + ''' AS db, o.name,o.xtype,m.definition '
SELECT #SQL = #SQL + ' FROM '+#c_dbname+'.sys.sql_modules m '
SELECT #SQL = #SQL + ' INNER JOIN '+#c_dbname+'..sysobjects o ON m.object_id=o.id'
SELECT #SQL = #SQL + ' WHERE [definition] LIKE ''%'+#TEXT+'%'''
EXEC(#SQL)
FETCH #databases INTO #c_dbname
END
CLOSE #databases
DEALLOCATE #databases
SELECT * FROM #results order by db, xtype, objectname
DROP TABLE #results
I've used these in the past:
Searching all user stored procedures for a table name
Search and replace SQL Server data in all columns of all tables
In this particular case, where you need to replace a specific string across stored procedures, the first link is probably more relevant.
A little off-topic, the Quick Find add-in is also useful for searching object names with SQL Server Management Studio. There's a modified version available with some improvements, and another newer version also available on Codeplex with some other useful add-ins as well.
Any searching with select statement yield you only object name, where search keyword contains.
Easiest and efficient way is get script of procedure/function and then search in generated text file, I also follows this technique :) So you are exact pinpoint.
You can search within the definitions of all database objects using the following SQL:
SELECT
o.name,
o.id,
c.text,
o.type
FROM
sysobjects o
RIGHT JOIN syscomments c
ON o.id = c.id
WHERE
c.text like '%text_to_find%'
SELECT ROUTINE_TYPE, ROUTINE_NAME, ROUTINE_DEFINITION
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%Your Text%'
Just wrote this for generic full outer cross ref
create table #XRefDBs(xtype varchar(2),SourceDB varchar(100), Object varchar(100), RefDB varchar(100))
declare #sourcedbname varchar(100),
#searchfordbname varchar(100),
#sql nvarchar(4000)
declare curs cursor for
select name
from sysdatabases
where dbid>4
open curs
fetch next from curs into #sourcedbname
while ##fetch_status=0
begin
print #sourcedbname
declare curs2 cursor for
select name
from sysdatabases
where dbid>4
and name <> #sourcedbname
open curs2
fetch next from curs2 into #searchfordbname
while ##fetch_status=0
begin
print #searchfordbname
set #sql =
'INSERT INTO #XRefDBs (xtype,SourceDB,Object, RefDB)
select DISTINCT o.xtype,'''+#sourcedbname+''', o.name,'''+#searchfordbname+'''
from '+#sourcedbname+'.dbo.syscomments c
join '+#sourcedbname+'.dbo.sysobjects o on c.id=o.id
where o.xtype in (''V'',''P'',''FN'',''TR'')
and (text like ''%'+#searchfordbname+'.%''
or text like ''%'+#searchfordbname+'].%'')'
print #sql
exec sp_executesql #sql
fetch next from curs2 into #searchfordbname
end
close curs2
deallocate curs2
fetch next from curs into #sourcedbname
end
close curs
deallocate curs
select * from #XRefDBs

Resources