Search Table for specific column name across multiple Databases - sql-server-2012

I am looking at about 200 databases, each have an, almost, uniform structure.
I am trying to search all the databases for 1 specific column in 1 specific table. If that column does not exist, then return the Database name.
I wrote a cursor to do this, but I am stuck on how to return the Database name.
set nocount on;
DECLARE #db_name NVARCHAR (150)
DECLARE c_db_names CURSOR FOR
SELECT name
FROM sys.databases
WHERE name like ('B1%') --might need to exclude more dbs
OPEN c_db_names
FETCH c_db_names INTO #db_name
WHILE ##Fetch_Status = 0
begin
Exec('
SELECT 'code for returning DB name goes here'
,c.name AS 'ColumnName'
,t.name AS 'TableName'
FROM '+ #db_name + '.sys.columns c
JOIN '+ #db_name + '. sys.tables t ON c.object_id = t.object_id
WHERE 1=1
and c.name like %MyName%'
')
FETCH c_db_names INTO #db_name
END
CLOSE c_db_names
DEALLOCATE c_db_names
Any recommendations here or even thoughts on how to do this more efficiently? i am not a fan of cursors, but they have their uses.
Also, how the heck do I flip that "LIKE" to something more reasonable for what I want?

Related

Creating a Data Dictionary with example data (SQL)

I am looking to run a script on a SQL database to create a Data Dictionary with an example of the data for each field.
To keep it simple I would just like to include the data from the first row of each table along with each table name and column name
So something like this:
Table Name
Field Name
Example Data
Customer
ID
CU1
Customer
Title
Mrs
Customer
Name
Anne
Customer
Order No
ORD1
etc.
Is there an easy way to do this with a SQL script?
Somebody smarter than me could probably optimize this and remove the cursor but the Dynamic SQL was giving me a headache. I think in this scenario, a cursor is acceptable
DROP TABLE IF EXISTS ##DataDictionary
CREATE TABLE ##DataDictionary (TableName SYSNAME, ColumnName SYSNAME, SampleData NVARCHAR(MAX))
DECLARE #TableName SYSNAME
DECLARE #ColumnName SYSNAME
DECLARE #SQL NVARCHAR(MAX)
DECLARE cur CURSOR FOR
SELECT t.name AS TableName,c.Name AS ColumnName
FROM sys.tables t
JOIN sys.columns c ON t.object_id = c.object_id
OPEN cur
FETCH cur INTO #TableName,#ColumnName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = ''
SELECT #SQL = '
INSERT INTO ##DataDictionary(TableName,ColumnName,SampleData)
SELECT '''+#TableName+''','''+#ColumnName+'''
,(SELECT TOP 1 '+QUOTENAME(#ColumnName)+' FROM '+QUOTENAME(#TableName)+' ORDER BY NEWID()) -- NewID randomly selects a sample row
'
print #SQL
EXEC (#SQL)
FETCH cur INTO #TableName,#ColumnName
END
CLOSE cur
DEALLOCATE cur
SELECT * from ##DataDictionary

SQL Remove All Constraints Azure Friendly

I'm doing some DB Admin with an Azure database and I need to perform queries like removing all constraints in the database.
sp_MSForEachTable is not available when working with Azure databases, so I'm working on a different way to do it.
I found a snippet that drops all tables here: http://edspencer.me.uk/2013/02/25/drop-all-tables-in-a-sql-server-database-azure-friendly/ and tried modifying it to remove all constraints like I need to and came up with this result:
while(exists(select 1 from INFORMATION_SCHEMA.TABLES where TABLE_NAME != '__MigrationHistory'))
begin
PRINT ('Disabling' + TABLE_NAME)
declare #constraintOff nvarchar(2000)
SELECT TOP 1 #constraintOff=('ALTER TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME + '] ' + 'NOCHECK CONSTRAINT all')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME != '__MigrationHistory'
exec (#constraintOff)
PRINT #constraintOff
end
It repeatedly tries to operate on the first item in the database, which would work fine if you were dropping everything but I need to loop through each table and disable its constraint like sp_MSForEachTable does.
Any tips? I've seen a few things here and there that claim to do this, but they're usually two or three page long scripts that do a lot of other stuff and they make my brain hurt.
UPDATE
still working on that query, it seems like something to this end might work better but still no dice:
declare #constraintOff nvarchar(2000)
SELECT #constraintOff=('ALTER TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME + '] ' + 'NOCHECK CONSTRAINT all')
FROM INFORMATION_SCHEMA.TABLES
exec (#constraintOff)
PRINT #constraintOff
This one still only operates on one table, but at least it's not an infinite loop :)
While this link is for Amazon RDS, it does provide specific code to disable constraints without sp_MSForEachTable
Importing and Exporting SQL Server Data
-- Manually specify database name - a safeguard in case you paste this into the wrong SSMS window.
USE [staging]
-- Change this line if you want to enable (1) or disable constraints:
DECLARE #enable_constraints bit = 0
--Don't change anything below this line.
DECLARE #schema_name SYSNAME
DECLARE #table_name SYSNAME
DECLARE table_cursor CURSOR FOR
SELECT
schemas.name,
tables.name
FROM
sys.tables
INNER JOIN sys.schemas ON tables.schema_id = schemas.schema_id
OPEN table_cursor
FETCH NEXT FROM table_cursor INTO #schema_name, #table_name
DECLARE #cmd varchar(200)
WHILE ##FETCH_STATUS = 0
BEGIN
SET #cmd = 'ALTER TABLE ' + QUOTENAME(#schema_name) + '.' + QUOTENAME(#table_name) + ' '
SET #cmd = #cmd + (CASE WHEN #enable_constraints = 1 THEN 'CHECK' ELSE 'NOCHECK' END) + ' CONSTRAINT ALL'
PRINT #cmd
EXEC( #cmd )
FETCH NEXT FROM table_cursor INTO #schema_name, #table_name
END
CLOSE table_cursor
DEALLOCATE table_cursor
Extended the script to deal with tables in different schemas, also corrected the above script that is not disabling checks:
-- DISABLE ALL CONSTRAINTS
DECLARE #table_name SYSNAME;
DECLARE #schema_name SYSNAME;
DECLARE #cmd NVARCHAR(MAX);
DECLARE table_cursor CURSOR FOR
SELECT s.name, t.name
FROM sys.tables t
join sys.schemas s on t.schema_id = s.schema_id
OPEN table_cursor;
FETCH NEXT FROM table_cursor INTO #schema_name, #table_name;
WHILE ##FETCH_STATUS = 0 BEGIN
SELECT #cmd = 'ALTER TABLE '+QUOTENAME(#schema_name)+'.'+QUOTENAME(#table_name)+' NOCHECK CONSTRAINT ALL';
EXEC (#cmd);
FETCH NEXT FROM table_cursor INTO #schema_name, #table_name;
END
CLOSE table_cursor;
DEALLOCATE table_cursor;
-- enable all constraints
DECLARE table_cursor CURSOR FOR
SELECT s.name, t.name
FROM sys.tables t
join sys.schemas s on t.schema_id = s.schema_id
OPEN table_cursor;
FETCH NEXT FROM table_cursor INTO #schema_name, #table_name;
WHILE ##FETCH_STATUS = 0 BEGIN
SELECT #cmd = 'ALTER TABLE '+QUOTENAME(#schema_name)+'.'+QUOTENAME(#table_name)+' CHECK CONSTRAINT ALL';
EXEC (#cmd);
FETCH NEXT FROM table_cursor INTO #schema_name, #table_name;
END
CLOSE table_cursor;
DEALLOCATE table_cursor;

SQL Server Select data from table without knowing column names

This is sample data table.
I want to select values in any rows or any column (equals) = 200 with column names.But we don't know column names.
If you know the table name it's possible to interrogate the INFORMATION_SCHEMA.TABLES and INFORMATION_SCHEMA.COLUMNS, with SQLServer 2005 or better, or sysobjects and syscolumns with SQLServer 2000 to retrieve the table columns, after that you can create a fully referenced query for your needs
I think the below T-SQL will get you what you want. It was written against AdventureWorks2012LT. In the future, you can get more specific help by including the SQL create statements with your question (so the responder doesn't have to recreate the tables)
(BTW, My example is looking for any field that contains the letter 'S')
DECLARE #column_name nvarchar(200);
DECLARE #statement nvarchar(max);
DECLARE #results TABLE(
id int,
colname nvarchar(200),
value nvarchar(max)
)
DECLARE col_cursor CURSOR FOR
SELECT C.COLUMN_NAME AS col
FROM INFORMATION_SCHEMA.COLUMNS C WHERE C.TABLE_NAME LIKE 'Address'
OPEN col_cursor
FETCH NEXT FROM col_cursor INTO #column_name
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #column_name
SELECT #statement = N'SELECT AddressID, ''' + #column_name + ''' AS ColName, ' + #column_name + ' AS value FROM SalesLT.[Address] WHERE ' + #column_name + ' LIKE ''%S%''';
INSERT INTO #results
EXEC(#statement);
FETCH NEXT FROM col_cursor INTO #column_name
END
CLOSE col_cursor
DEALLOCATE col_cursor
SELECT * FROM #results

List all columns referenced in all procedures of all databases

Is there a way that I can get all the columns and tables referenced in all the stored procedures in all the databases in an instance? The output should be:
Database Procedure Table Column
-------- --------- ----- ------
This will get the list you're after, however it won't help you if you have such column references embedded in dynamic SQL (and may not find references that rely on deferred name resolution). SQL Server doesn't parse the text of the stored procedure to come up with the DMV output.
Try now with COLLATE clauses to deal with cases where you have databases on the same server with different collations.
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += N'UNION ALL
SELECT
[database] = ''' + REPLACE(name, '''', '''''') + ''',
[procedure] = QUOTENAME(s.name) + ''.'' + QUOTENAME(p.name)
COLLATE Latin1_General_CI_AI,
[table] = QUOTENAME(referenced_schema_name) + ''.''
+ QUOTENAME(referenced_entity_name)
COLLATE Latin1_General_CI_AI,
[column] = QUOTENAME(referenced_minor_name)
COLLATE Latin1_General_CI_AI
FROM ' + QUOTENAME(name) + '.sys.schemas AS s
INNER JOIN ' + QUOTENAME(name) + '.sys.procedures AS p
ON s.[schema_id] = p.[schema_id]
CROSS APPLY ' + QUOTENAME(name)
+ '.sys.dm_sql_referenced_entities'
+ '(QUOTENAME(s.name) + ''.'' + QUOTENAME(p.name), N''OBJECT'') AS d
WHERE d.referenced_minor_id > 0'
FROM sys.databases
WHERE database_id > 4
AND [state] = 0;
SET #sql = STUFF(#sql,1,11,'');
EXEC sp_executesql #sql;
Also the CROSS APPLY syntax won't work if you have databases that are in 80 compatibility mode. Just make sure you don't execute the code in such a database and it should work fine (even if some of the target databases are in 80).
To list all SP Name have contain the specified column name:
SELECT OBJECT_NAME(M.object_id), M.*
FROM sys.sql_modules M
JOIN sys.procedures P
ON M.object_id = P.object_id
WHERE M.definition LIKE '%ColumnName%'
Here is yet another way to do this. This is very DIRTY but I like it. Why? Because I came up with it. Anyway it is using Dynamic SQL inside Dynamic SQL to insert dependency information into temp table that can be queried.
This can be modified into a SP that you can run from time to time to update dependencies information, also temp table can be changes to real table if you want to store it.
IF OBJECT_ID('tempdb.dbo.#SPDependencyDetails') IS NOT NULL
DROP TABLE #SPDependencyDetails
CREATE TABLE #SPDependencyDetails
(
Or_Object_Database NVARCHAR(128)
,Or_Object_Name NVARCHAR(128)
,Ref_Database_Name NVARCHAR(128)
,Ref_Schema_Name NVARCHAR(128)
,Ref_Object_Name NVARCHAR(128)
,Ref_Column_Name NVARCHAR(128)
,Is_Selected BIT
,Is_Updated BIT
,Is_Select_All BIT
,Is_All_Columns_Found BIT
)
DECLARE #database_name VARCHAR(100)
DECLARE database_cursor CURSOR
FOR
SELECT name
FROM sys.databases
WHERE database_id > 4
OPEN database_cursor
FETCH NEXT FROM database_cursor
INTO #database_name
WHILE ##FETCH_STATUS = 0 --Outer Loop begin
BEGIN
DECLARE #WholeLotofSQL NVARCHAR(MAX) = '
DECLARE #object_name VARCHAR(150)
,#sqlstatement NVARCHAR(2500)
DECLARE object_cursor CURSOR --Inner cursor, iterates list of objects that match type
FOR
SELECT name
FROM '+#database_name+'.sys.objects AS o
WHERE o.type = ''P'' --Change Object type to find dependencies of Functions, Views and etc.
ORDER BY 1
OPEN object_cursor
FETCH NEXT FROM object_cursor INTO #object_name
WHILE ##FETCH_STATUS = 0 --Inner Loop Begin
BEGIN
SET #sqlstatement = ''USE '+#database_name+';
INSERT INTO #SPDependencyDetails
SELECT DB_NAME() AS Or_Object_Database
,'''''' + #object_name + '''''' AS Or_Object_Name
,CASE WHEN referenced_database_name IS NULL THEN DB_NAME()
ELSE referenced_database_name
END AS Ref_Database_Name
,referenced_schema_name AS Ref_Schema_Name
,referenced_entity_name AS Ref_Object_Name
,referenced_minor_name AS Ref_Column_Name
,is_selected
,is_updated
,is_select_all
,is_all_columns_found
FROM sys.dm_sql_referenced_entities(''''dbo.'' + #object_name + '''''', ''''OBJECT'''');''
EXEC sys.sp_executesql #sqlstatement
FETCH NEXT FROM object_cursor INTO #object_name
END
CLOSE object_cursor
DEALLOCATE object_cursor'
EXEC sys.sp_executesql #WholeLotofSQL
FETCH NEXT FROM database_cursor INTO #database_name
END
CLOSE database_cursor;
DEALLOCATE database_cursor;
SELECT Or_Object_Database as 'Database'
,Or_Object_Name as 'Procedure'
,Ref_Object_Name as 'Table'
,Ref_Column_Name as 'Column
FROM #SPDependencyDetails

Search sql database for a column name, then search for a value within the retuned columns

This query will search a database for a specific column name. I would like to go one step further and search the returned columns for a specific value.
SELECT t.name AS table_name,
SCHEMA_NAME(schema_id) AS schema_name,
c.name AS column_name,
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE c.name LIKE '%Example%'
Any ideas?
Many thanks
For example, I have a database named Organisation. I have more than one table where tax_id column is present.
Most of the time, we have to find such a column from the whole database.
The solution is provided below:
select table_name,column_name from information_schema.columns
where column_name like '%tax%'
There is no matter in query to database name which ever you just need to change willing Column Name and will found required result
Search any value Like computer in whole database in which column and in which tables value computer exists
For it first we need to write a store procedure then we reuse it for our search i got it from http://vyaskn.tripod.com/search_all_columns_in_all_tables.htm very perfect result.
after executing store procedure we got required result as in given below image.
Image showing complete search result of keyword computer from whole database.
Above was concept to solve it.Exact Query fullfilling above requirment is below
Select tax_id from (select table_name from information_schema.columns
where column_name = 'tax_id') as temp
There is not such system table present for this kind of searching. Whereas you can try this for your purpose
DECLARE #ValueToSearch NVARCHAR(500)
DECLARE #SearchColumn NVARCHAR(100)
DECLARE #TableName NVARCHAR(200)
DECLARE #ColumnName NVARCHAR(200)
SET #ValueToSearch ='YOUR VALUE TP SEARCH'
SET #SearchColumn = 'YOUR COLUMN'
DECLARE #getResult CURSOR
SET #getResult = CURSOR FOR
SELECT t.name AS table_name,c.name AS column_name FROM sys.tables AS t INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID WHERE c.name = #SearchColumn
OPEN #getResult
FETCH NEXT FROM #getResult INTO #TableName,#ColumnName
WHILE ##FETCH_STATUS = 0
BEGIN
SET NOCOUNT ON ;
DECLARE #RESULT INT;
DECLARE #TYPE INT
DECLARE #QUERY NVARCHAR(1000)
SET #QUERY = 'select #RESULT=count(*) from ' + ISNULL(#TableName,'') +' WHERE '+ ISNULL(#ColumnName,'')+'='''+ ISNULL(#ValueToSearch,'') +''''
EXEC sp_executesql #QUERY,
N'#result int OUTPUT, #type int OUTPUT',
#RESULT OUTPUT,
#TYPE OUTPUT
IF(ISNULL(#RESULT,0)>0)
BEGIN
SET NOCOUNT ON;
SELECT ' COLUMN '+ #ColumnName + ' OF TABLE ' +#TableName+ ' HAS THIS VALUE.'
END
FETCH NEXT FROM #getResult INTO #TableName,#ColumnName
END
CLOSE #getResult
DEALLOCATE #getResult
Thanks
Manoj