Is there a way to query INFORMATION_SCHEMA.COLUMNS across all databases? It appears that USE db must be specified.
I tried this, but it returns nothing when using PowerShell Invoke-Sqlcmd.
IF DB_ID('db') IS NOT NULL
BEGIN
SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE 'BID_BY_CPT_SPECIAL'
ORDER BY TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME,ORDINAL_POSITION
;
END
This query is used in a PowerShell script.
$q = #"
DROP TABLE IF EXISTS #Temp;
SELECT DatabaseName=cast('' as varchar(100))
, TABLE_NAME
, COLUMN_NAME
, DATA_TYPE
, ORDINAL_POSITION
Into #Temp
FROM INFORMATION_SCHEMA.COLUMNS
Where 1=0
Declare #SQL varchar(max) = '
USE ? ;
Insert Into #Temp
SELECT DatabaseName=''?''
, TABLE_NAME
, COLUMN_NAME
, DATA_TYPE
, ORDINAL_POSITION
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE ''BID_BY_CPT_SPECIAL''
ORDER BY TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME,ORDINAL_POSITION
'
EXEC sp_MSforeachdb #SQL
Select * From #Temp
"#
foreach ($db in $DatabaseInstances) {
$r = Invoke-Sqlcmd -Query $q -ServerInstance $db
=== Update
This query is working with Invoke-Sqlcmd.
$q = #"
DROP TABLE IF EXISTS #Temp;
SELECT DatabaseName=cast('' as varchar(100))
,TABLE_NAME
,COLUMN_NAME
,DATA_TYPE
,ORDINAL_POSITION
,CHARACTER_MAXIMUM_LENGTH
,NUMERIC_PRECISION
,NUMERIC_SCALE
,IS_NULLABLE
Into #Temp
FROM INFORMATION_SCHEMA.COLUMNS
Where 1=0
Declare #SQL varchar(max) = '
USE ? ;
Insert Into #Temp
SELECT DatabaseName=''?''
,TABLE_NAME
,COLUMN_NAME
,DATA_TYPE
,ORDINAL_POSITION
,CHARACTER_MAXIMUM_LENGTH
,NUMERIC_PRECISION
,NUMERIC_SCALE
,IS_NULLABLE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE ''$TableName''
ORDER BY TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME,ORDINAL_POSITION
'
EXEC sp_MSforeachdb #SQL
Select * From #Temp
"#
Take a look into sp_MSforeachdb
This will collect data into one Temp table. Personally, I would move your WHERE to the final SELECT
Example
SELECT DatabaseName=cast('' as varchar(100))
, TABLE_NAME
, COLUMN_NAME
, DATA_TYPE
, ORDINAL_POSITION
Into #Temp
FROM INFORMATION_SCHEMA.COLUMNS
Where 1=0
Declare #SQL varchar(max) = '
USE ? ;
Insert Into #Temp
SELECT DatabaseName=''?''
, TABLE_NAME
, COLUMN_NAME
, DATA_TYPE
, ORDINAL_POSITION
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE ''BID_BY_CPT_SPECIAL''
ORDER BY TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME,ORDINAL_POSITION
'
EXEC sp_MSforeachdb #SQL
Select * From #Temp
Related
I have a table with records which has 100 columns, I need to get the count of distinct values of all the columns from this table based on some condition (where clause).
Below query is working fine, but I'm not able to use the where clause. So it's giving the result for all the records of the table. But I want it to be based on some condition lets say column file_id = 1;. My question is how to use where clause with the below query. Or if there is any other alternative way to solve this problem.
declare #SQL nvarchar(max)
set #SQL = ''
;with cols as (
select Table_Schema, Table_Name, Column_Name, Row_Number() over(partition by Table_Schema, Table_Name
order by ORDINAL_POSITION) as RowNum
from INFORMATION_SCHEMA.COLUMNS
)
select #SQL = #SQL + case when RowNum = 1 then '' else ' union all ' end
+ ' select ''' + Column_Name + ''' as Column_Name, count(distinct ' + quotename (Column_Name) + ' ) As DistinctCountValue,
count( '+ quotename (Column_Name) + ') as CountValue FROM ' + quotename (Table_Schema) + '.' + quotename (Table_Name)
from cols
where Table_Name = 'table_name' --print #SQL
execute (#SQL)
I am using the dynamic query because I need to reuse this query for other tables also.
First get the columns and use stuff to generate the select in this way:
SELECT COUNT(ColumnA) AS ColumnA, COUNT(ColumnB AS ColumnB), COUNT(ColumnC) AS ColumnC....
That way you only select on your table once to get all counts, After that, use CROSS APPLY to "unpivot" those columns and return the output on one row per column
CROSS APPLY(
VALUES(1, 'ColumnA', ColumnA), (2, 'ColumnB', ColumnB), (3, 'ColumnC', ColumnC)
)(ID, ColumnName, DistinctCountValue)
For the filter, use sp_executesql and send the file_id as parameter
exec SP_executesql #SQL, N'#FID INT', #FID = #FileID
Since you are using all columns of the table Row_Number() over(partition by Table_Schema, Table_Name order by ORDINAL_POSITION) as RowNum becomes redundant, ORDINAL_POSITION already has the value that you are looking for
declare #tablename nvarchar(50) = 'MyTestTable'
declare #fileID int = 1
declare #SQL nvarchar(max)
set #SQL = ''
;with cols as (
select TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = #TableName
)
select #SQL = ';WITH CTE AS (SELECT
' +
STUFF((
SELECT ', COUNT(DISTINCT ' + QUOTENAME(COLUMN_NAME) + ') AS ' + QUOTENAME(COLUMN_NAME)
FROM cols
ORDER BY ORDINAL_POSITION
FOR XML PATH('')
), 1, 1, '')
+ '
FROM ' + #TableName + '
WHERE File_ID = #FID
)
SELECT B.*
FROM CTE
CROSS APPLY (
VALUES ' +STUFF((
SELECT ',( ' + CAST(ORDINAL_POSITION AS VARCHAR) + ',' + QUOTENAME(COLUMN_NAME,'''') + ',' + QUOTENAME(COLUMN_NAME) + ')'
FROM cols
ORDER BY ORDINAL_POSITION
FOR XML PATH('')
), 1, 1, '') + '
)B (ID,ColumnName,DistinctCountValue)
'
from cols
exec SP_executesql #SQL, N'#FID INT', #FID = #FileID
The query below creates a table of all the column names and uses a while loop to select the count for whatever WHERE clause you want to use. This should be pretty flexible for any table; just update the top variables. Note that this will not count a column where its value is null. You can add a case to the #Query parameter if that's what you want. Since it processes each row individually, I added in a temp table so you only hit the db once.
IF OBJECT_ID('tempdb..##SourceValues') IS NOT NULL
DROP TABLE ##SourceValues
DECLARE #Schema VARCHAR(50) = 'SomeSchema'
DECLARE #Table VARCHAR(50) = 'SomeTable'
DECLARE #WhereClause VARCHAR(MAX) = ' Some WHERE clause'
DECLARE #ColumnName VARCHAR(50)
DECLARE #ProcessedRows TABLE(ColumnName VARCHAR(50), DistinctCount INT)
DECLARE #Columns TABLE(RowNumber INT, ColumnName VARCHAR(100))
INSERT INTO #Columns SELECT ROW_NUMBER() OVER(ORDER BY COLUMN_NAME DESC), COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = #Table
DECLARE #Count INT = (SELECT MAX(RowNumber) FROM #Columns)
DECLARE #Counter INT = 0
DECLARE #DistinctCount INT
DECLARE #Query NVARCHAR(MAX)
EXEC('SELECT * INTO ##SourceValues FROM ' + #Table +' (NOLOCK)')
WHILE #Counter < #Count
BEGIN
SET #Counter += 1
SET #ColumnName = (SELECT ColumnName FROM #Columns WHERE RowNumber = #Counter)
SET #Query = 'SELECT #OutPut = COUNT(' + #ColumnName + ') FROM ' + #Schema + '.' + ' ##SourceValues ' + #WhereClause
EXECUTE sp_executesql #Query, N'#Output INT OUT', #DistinctCount OUT
INSERT INTO #ProcessedRows(ColumnName, DistinctCount) VALUES (#ColumnName, #DistinctCount)
END
SELECT * FROM #ProcessedRows
Let's try some different approach.
Get all values unpivoted as Param/Value:
1) Collect list of tables and columns to be used in dynamic SQL:
DROP TABLE IF EXISTS #Base;
;WITH SchemaData AS (
SELECT t.name AS [TableName],c.name AS [ColumnName],c.column_id AS [ColumnOrderID]
FROM sys.tables t
INNER JOIN sys.columns c ON c.object_id = t.object_id
)
SELECT t.TableName
,STUFF((SELECT ',CONVERT(NVARCHAR(MAX),' + QUOTENAME([ColumnName]) + ') AS ' + QUOTENAME([ColumnName])
FROM SchemaData a WHERE (a.TableName = t.TableName) FOR XML PATH(''),TYPE).value('(./text())[1]','NVARCHAR(MAX)'),1,1,'') AS [SelectClause]
,STUFF((SELECT ',' + QUOTENAME([ColumnName]) FROM SchemaData a WHERE (a.TableName = t.TableName) FOR XML PATH(''),TYPE).value('(./text())[1]','NVARCHAR(MAX)'),1,1,'') AS [UnpivotClause]
INTO #Base
FROM SchemaData t
GROUP BY t.TableName
;
2) Get all data inside a temp table
DROP TABLE IF EXISTS #Result;
CREATE TABLE #Result(TableName NVARCHAR(255),ColumnName NVARCHAR(255),[Value] NVARCHAR(MAX));
DECLARE #TableName NVARCHAR(255),#SelectClause NVARCHAR(MAX),#UnpivotClause NVARCHAR(MAX);
DECLARE crPopulateResult CURSOR LOCAL FAST_FORWARD READ_ONLY FOR SELECT b.TableName,b.SelectClause,b.UnpivotClause FROM #Base b;
OPEN crPopulateResult;
FETCH NEXT FROM crPopulateResult INTO #TableName,#SelectClause,#UnpivotClause;
DECLARE #dSql NVARCHAR(MAX);
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #dSql = N' INSERT INTO #Result(TableName,[ColumnName],[Value])
SELECT up.TableName,up.Param AS [ColumnName],up.[Value]
FROM (
SELECT ''' + #TableName + N''' AS [TableName]
,' + #SelectClause + N'
FROM ' + QUOTENAME(#TableName) + N'
) a
UNPIVOT(Value FOR Param IN (' + #UnpivotClause + N')) up
';
EXEC sp_executesql #stmt = #dSql;
FETCH NEXT FROM crPopulateResult INTO #TableName,#SelectClause,#UnpivotClause;
END
CLOSE crPopulateResult;
DEALLOCATE crPopulateResult;
3) Any filters can be applied with #Results, including Table names, column names, data filters, etc:
SELECT r.TableName,r.ColumnName,COUNT(*) AS [CountValue],COUNT(DISTINCT r.[Value]) AS [DistinctCountValue]
FROM #Result r
--
--WHERE r.ColumnName = 'file_id' AND r.[Value] = '1'
--
GROUP BY r.TableName,r.ColumnName
ORDER BY r.TableName,r.ColumnName
;
To use this with a where clause with this query you just have to put the where clause in the construction after the table name so if you wanted to filter on file_id='1' then you would have:
FROM ' + quotename (Table_Schema) + '.' + quotename (Table_Name) +'where file_id =''1'' '
You can add a #where variable and concatenate that with your big union construction (as part of your select ... from cols). For example:
declare #SQL nvarchar(max)
declare #where nvarchar(max) = ' where file_id = 1'
set #SQL = ''
;with cols as (
select Table_Schema, Table_Name, Column_Name, Row_Number() over(partition by Table_Schema, Table_Name
order by ORDINAL_POSITION) as RowNum
from INFORMATION_SCHEMA.COLUMNS
)
select #SQL = #SQL + case when RowNum = 1 then '' else ' union all ' end
+ ' select ''' + Column_Name + ''' as Column_Name, count(distinct ' + quotename (Column_Name) + ' ) As DistinctCountValue,
count( '+ quotename (Column_Name) + ') as CountValue FROM ' + quotename (Table_Schema) + '.' + quotename (Table_Name)
+ #where
from cols
where Table_Name = 'table_name' --print #SQL
execute (#SQL)
Note that you'll need to escape single quotes in #where if you're searching for a string. For example, declare #where nvarchar(max) = ' where state = ''CT'''.
Having a simple query such as:
select * from foo
Where the output has the columns
bar | abc | def
---------------
...............
It is possible to encapsulate this query into another one and give sequential names instead to the columns such as 1|2|3... (mantaining all the rows intact)?
I know this sounds weird and probably it isn't even possible.
Thanks for the help!
Try This
DECLARE #Sql NVARCHAR(max),
#TableName VARCHAR(100) = '<YourTableName>'
;WITH CTE
AS
(
SELECT DENSE_RANK()OVER (ORDER BY COLUMN_NAME) Rno,
TABLE_NAME,
COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_CATALOG='Database'
AND TABLE_NAME = #TableName
)
SELECT 'SELECT '+ STUFF((SELECT ', '+ COLUMN_NAME +' AS '+ QUOTENAME(CAST(Rno AS VARCHAR))
FROM CTE
FOR XML PATH ('')),1,1,'') + ' FROM '+#TableName
PRINT #Sql
EXEC (#Sql)
Try this:
DECLARE #TableName NVARCHAR(100) = 'YOUR TABLENAME HERE',
#Query NVARCHAR(MAX) = 'SELECT '
SELECT #Query = CONCAT(#Query, ' ', COLUMN_NAME, ' AS ', QUOTENAME(ROW_NUMBER() OVER(ORDER BY ORDINAL_POSITION)), ',
')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #TableName
SET #Query = SUBSTRING(#Query, 0, LEN(#Query) - 3) + '
FROM ' + QUOTENAME(#TableName)
You use INFORMATION_SCHEMA.COLUMNS to get all our table's columns,
ROW_NUMBER() window function to generate sequential number for column aliases and sp_ExecuteSQL to execute dynamic generated queries.
I have a set of queries to add 4 different columns in different tables with somewhat similar names. So, I made a union of all 4 queries by calling INFORMATION_SCHEMA.COLUMNS in a set of dynamic sql having names of all tables and for all 4 columns.
Now I want to execute all these queries in one go without executing each query one by one. So how can I achieve it?
This is the query I made:
SELECT * FROM (SELECT
'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =''' + TABLE_NAME + ''' AND COLUMN_NAME = ''FromDays'') ALTER TABLE '+ TABLE_NAME +' ADD FromDays varchar(50) NULL; ' AS qry
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%tbl_PPT_Query_Order%'
UNION ALL
SELECT
'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =''' + TABLE_NAME + ''' AND COLUMN_NAME = ''ToDays'') ALTER TABLE '+ TABLE_NAME +' ADD ToDays varchar(50) NULL; ' AS qry
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%tbl_PPT_Query_Order%'
UNION ALL
SELECT
'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =''' + TABLE_NAME + ''' AND COLUMN_NAME = ''FromDays_Top'') ALTER TABLE '+ TABLE_NAME +' ADD FromDays_Top varchar(50) NULL; ' AS qry
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%tbl_PPT_Query_Order%'
UNION ALL
SELECT
'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =''' + TABLE_NAME + ''' AND COLUMN_NAME = ''ToDays_Top'') ALTER TABLE '+ TABLE_NAME +' ADD ToDays_Top varchar(50) NULL; ' AS qry
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%tbl_PPT_Query_Order%') x
Which is giving me the output as:
DECLARE #SQL NVARCHAR(MAX);
SELECT #SQL = (
(
SELECT
'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =''' + TABLE_NAME + ''' AND COLUMN_NAME = ''MyColumn1'') ALTER TABLE '+ TABLE_NAME +' ADD MyColumn1 varchar(50) NULL; ' AS qry
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%myTable%'
)
+ CHAR(13) +
(
SELECT
'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =''' + TABLE_NAME + ''' AND COLUMN_NAME = ''MyColumn2'') ALTER TABLE '+ TABLE_NAME +' ADD MyColumn2 varchar(50) NULL; ' AS qry
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%myTable%'
)
+ CHAR(13) +
(
SELECT
'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =''' + TABLE_NAME + ''' AND COLUMN_NAME = ''MyColumn3'') ALTER TABLE '+ TABLE_NAME +' ADD MyColumn3 varchar(50) NULL; ' AS qry
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%myTable%'
)
)
;
SELECT #SQL
--EXECUTE SP_ExecuteSQL #SQL
;
If the result is to your liking, remove the SELECT #SQL at the bottom and un-comment the EXECUTE SP_ExecuteSQL #SQL to execute the commands.
First Edit:
Okay, I apologize for having misunderstood the context of the question. How about something like this:
DECLARE #SQL NVARCHAR(MAX);
SELECT #SQL = REPLACE(SUBSTRING(
(
SELECT CHAR(10)
+ 'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ='''
+ TABLE_NAME
+ ''' AND COLUMN_NAME = ''FromDays'') ALTER TABLE '
+ TABLE_NAME
+' ADD FromDays varchar(50) NULL; '
FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_NAME LIKE '%tbl_PPT_Query_Order%'
ORDER BY TABLE_NAME
FOR XML PATH('')
)
,1,4000),'#x0D',CHAR(10))
+
REPLACE(SUBSTRING(
(
SELECT CHAR(10)
+ 'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ='''
+ TABLE_NAME
+ ''' AND COLUMN_NAME = ''ToDays'') ALTER TABLE '
+ TABLE_NAME
+' ADD ToDays varchar(50) NULL; '
FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_NAME LIKE '%tbl_PPT_Query_Order%'
ORDER BY TABLE_NAME
FOR XML PATH('')
)
,1,4000),'#x0D',CHAR(10))
+
REPLACE(SUBSTRING(
(
SELECT CHAR(10)
+ 'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ='''
+ TABLE_NAME
+ ''' AND COLUMN_NAME = ''FromDays_Top'') ALTER TABLE '
+ TABLE_NAME
+' ADD FromDays_Top varchar(50) NULL; '
FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_NAME LIKE '%tbl_PPT_Query_Order%'
ORDER BY TABLE_NAME
FOR XML PATH('')
)
,1,4000),'#x0D',CHAR(10))
+
REPLACE(SUBSTRING(
(
SELECT CHAR(10)
+ 'IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ='''
+ TABLE_NAME
+ ''' AND COLUMN_NAME = ''ToDays_Top'') ALTER TABLE '
+ TABLE_NAME
+' ADD ToDays_Top varchar(50) NULL; '
FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_NAME LIKE '%tbl_PPT_Query_Order%'
ORDER BY TABLE_NAME
FOR XML PATH('')
)
,1,4000),'#x0D',CHAR(10))
SELECT #SQL
--EXECUTE SP_ExecuteSQL #SQL
;
I run this query to get all the tables that include a specific column name
SELECT COLUMN_NAME, TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%myColumn%'
Then, for every single table, I want to run a query like this one:
SELECT * FROM table WHERE myColumn = xxx
Is there any way to do it automatically and run the second query to all the tables from the first query?
I have a fairly big database and I want to check if there is anywhere stored something about the specific Id on myColumn. And this column is used in about 200 tables.
I guess you need to use dynamic query for this. in this I saved the Schema result in a table variable and then loop through them to generate the required query. please try the below:
DECLARE #Template varchar(max)='SELECT * FROM [TABLE_NAME] WHERE [COLUMN_NAME] = ''xxx''';
DECLARE #CMD varchar(max);
DECLARE #id int=1, #TABLE_NAME varchar(255), #COLUMN_NAME varchar(255)
declare #Table table(id int identity(1,1), COLUMN_NAME varchar(255), TABLE_NAME varchar(255))
INSERT INTO #Table (TABLE_NAME, COLUMN_NAME)
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%Label%'
SELECT #id=ID, #TABLE_NAME = TABLE_NAME, #COLUMN_NAME = COLUMN_NAME FROM #Table WHERE ID = #id
While ##ROWCOUNT>0 BEGIN
SET #CMD = REPLACE(#Template, '[TABLE_NAME]', #TABLE_NAME)
SET #CMD = REPLACE(#CMD, '[COLUMN_NAME]', #COLUMN_NAME)
Print #cmd
EXEC (#CMD)
SELECT #id=ID, #TABLE_NAME = TABLE_NAME, #COLUMN_NAME = COLUMN_NAME FROM #Table WHERE ID = #id + 1
End
You could do this as follows. The script builds all the SELECT statements in a VARCHAR and then executes dynamically. Works when you for integers as well as varchars.
DECLARE #col_name SYSNAME='myColumn';
DECLARE #expected_value NVARCHAR(256)='xxx';
DECLARE #sel_stmts NVARCHAR(MAX) = (
SELECT
';SELECT '+
'* '+
'FROM '+
QUOTENAME(t.TABLE_SCHEMA)+'.'+QUOTENAME(t.TABLE_NAME) +
'WHERE '+
QUOTENAME(c.COLUMN_NAME)+'='''+REPLACE(#expected_value,'''','''''')+''''
FROM
INFORMATION_SCHEMA.TABLES AS t
INNER JOIN INFORMATION_SCHEMA.COLUMNS AS c ON
c.TABLE_SCHEMA=t.TABLE_SCHEMA AND
c.TABLE_NAME=t.TABLE_NAME
WHERE
t.TABLE_TYPE='BASE TABLE' AND
c.COLUMN_NAME LIKE '%'+#col_name+'%'
FOR
XML PATH('')
)+';';
--SELECT #sel_stmts; -- review
EXEC sp_executesql #sel_stmts; -- execute it
I made a couple changes to Ahmed Saeed's answer that were helpful for me so posting them here
Adding the schema name for dbs with more than one schema
Adding extra [] around the schema/db names in case one of those names is also a keyword
Printing the tablename with the results
DECLARE #Template varchar(max)='SELECT ''[TABLE_NAME]'' as TableName, * FROM [[DBSCHEMA_NAME]].[[TABLE_NAME]] WHERE [COLUMN_NAME] = ''xxx''';
DECLARE #CMD varchar(max);
DECLARE #id int=1, #DBSCHEMA_NAME varchar(255), #TABLE_NAME varchar(255), #COLUMN_NAME varchar(255)
declare #Table table(id int identity(1,1), COLUMN_NAME varchar(255), TABLE_NAME varchar(255), DBSCHEMA_NAME varchar(255))
INSERT INTO #Table (TABLE_NAME, COLUMN_NAME, DBSCHEMA_NAME)
SELECT TABLE_NAME, COLUMN_NAME, TABLE_SCHEMA
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%colname%'
SELECT #id=ID, #DBSCHEMA_NAME = DBSCHEMA_NAME, #TABLE_NAME = TABLE_NAME, #COLUMN_NAME = COLUMN_NAME FROM #Table WHERE ID = #id
While ##ROWCOUNT>0 BEGIN
SET #CMD = REPLACE(#Template, '[TABLE_NAME]', #TABLE_NAME)
SET #CMD = REPLACE(#CMD, '[COLUMN_NAME]', #COLUMN_NAME)
SET #CMD = REPLACE(#CMD, '[DBSCHEMA_NAME]', #DBSCHEMA_NAME)
Print #cmd
EXEC (#CMD)
SELECT #id=ID, #DBSCHEMA_NAME = DBSCHEMA_NAME, #TABLE_NAME = TABLE_NAME, #COLUMN_NAME = COLUMN_NAME FROM #Table WHERE ID = #id + 1
End
I have tables like lg-010-a..., lg-010-ac..., and so on, I have abc database,
I have a command window:
drop table from abc where Table_Name like 'lg-010-%'
Will this drop all the tables starting with lg-010-?
Try something like this:
declare #sql varchar(max)
declare #tablenames varchar(max)
select #tablenames = coalesce(#tablenames + ', ','') + Table_Name from INFORMATION_SCHEMA.TABLES
where Table_Name like ('lg-010-%')
set #sql = 'drop table ' + #tablenames
exec (#sql)
This queries the INFORMATION_SCHEMA.TABLES table to retrieve table names that match your criteria, then concatenates them together into a comma delimited string.
This string is than added to a 'Drop table ' statement and executed.
Drop table can take multiple comma delimited table names.
(I had originally had this query sys.tables but some research revealed that while they are currently equivalent, the Information_Schema method is quaranteed to work in future versions)
Unfortunately you can't do it like that. One way is:
SELECT 'DROP TABLE ' + name FROM sysobjects WHERE name LIKE '%lg-010-a%' AND [type] IN ('P')
This will just print out the DROP TABLE statement for each table - you can then copy and paste this output and run it. You can just put an EXECUTE in the loop instead of the PRINT, but I've done it this way so you can see what's going on/check the output first.
I had an issue where the accepted answer was not doing anything. I discovered that I had to add the prefix name of the database to the code to get it to work. If your tables are not dbo.tablename try this.
declare #sql varchar(max)
declare #tablenames varchar(max)
SELECT
#tablenames = COALESCE(#tablenames + ', ','') + 'YourDatabaseName.' + Table_Name
FROM
INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME LIKE 'AP2%'
AND (RIGHT(TABLE_NAME, 6) < 201708)
SET #sql = 'drop table ' + #tablenames
EXEC (#sql)
GO
Unfortunately you can't do it like that.
One way is:
DECLARE #TableName NVARCHAR(128)
SELECT TOP 1 #TableName = TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'lg-010-%'
ORDER BY TABLE_NAME ASC
WHILE (##ROWCOUNT > 0)
BEGIN
PRINT 'DROP TABLE [' + #TableName + ']'
SELECT TOP 1 #TableName = TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'lg-010-%'
AND TABLE_NAME > #TableName
ORDER BY TABLE_NAME ASC
END
This will just print out the DROP TABLE statement for each table - you can then copy and paste this output and run it. You can just put an EXECUTE in the loop instead of the PRINT, but I've done it this way so you can see what's going on/check the output first.
CREATE PROCEDURE dbo.drop_MsSqlTables1 #createDate smalldatetime
AS
declare #flag int =1
declare #tname varchar(50)
declare #sql varchar(max)
select row_number() over (order by name) as num, '[dbo].[' + name +']' as table_name into #temp from sys.tables where name like ('EmpInfo_%') and create_date<#createDate
declare #count int = (select count(*) from #temp)
select * from #temp
while #flag <= #count
begin
set #tname = (select table_name from #temp where num = #flag)
set #sql = 'drop table ' + #tname
exec (#sql)
set #flag = #flag+1
end