Loop through multiple Float columns in a DB using Dynamic SQL - sql

How do I loop through multiple columns from different tables in a database?. I am finding the result I need by querying one column at a time which takes lot of time.
SELECT MAX
(CASE Charindex('.', COLUMN1)
WHEN 0 THEN 0
ELSE
Len (Cast(Cast(Reverse(CONVERT(VARCHAR(50), COLUMN1, 128)
) AS FLOAT) AS BIGINT))
END) AS MAX_LENGTH
FROM DB1.dbo.TABLE1
My code is here but it won't work because I am sending more than one value
DECLARE #cols NVARCHAR(MAX)
,#sql NVARCHAR(MAX)
SET #cols = (SELECT quotename(COLUMN_NAME) FROM BRSDATA.INFORMATION_SCHEMA.COLUMNS A
inner join BRSDATA.INFORMATION_SCHEMA.TABLES B
on A.TABLE_NAME = B.TABLE_NAME
where TABLE_TYPE = 'BASE TABLE'
and DATA_TYPE = 'Float')
Set #sql = 'SELECT MAX(CASE Charindex(''.'',' + #cols + ')
WHEN 0 THEN 0
ELSE
Len (Cast(Cast(Reverse(CONVERT(VARCHAR(50), ' + #cols + ', 128)
) AS FLOAT) AS BIGINT))
END) AS MAX_LENGTH'
print(#sql)
Msg 512, Level 16, State 1, Line 101
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I also tried using a cursor and the 'query executed successfully' but I don't see the results even when not closing and deallocating the cursor.
DECLARE #SchemaName SYSNAME = 'dbo'
DECLARE #TableName SYSNAME
DECLARE #ColumnName SYSNAME
DECLARE FLOAT_COLUMNS CURSOR FOR
SELECT t.name,c.name
FROM BRSDATA.sys.tables AS t
INNER JOIN BRSDATA.sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
inner join BRSDATA.sys.columns AS c
on c.object_id = t.object_id
WHERE s.name = 'dbo'
and type_desc = 'USER_TABLE';
OPEN FLOAT_COLUMNS
FETCH NEXT FROM FLOAT_COLUMNS
INTO #TableName, #ColumnName
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #Columns NVARCHAR(MAX)
SET #Columns =
STUFF(
(SELECT
',' + QUOTENAME(name)
FROM
sys.columns
WHERE
object_id = OBJECT_ID(QUOTENAME(#TableName) + '.' + QUOTENAME(#ColumnName))
FOR XML PATH(''))
,1,1,'')
DECLARE #SQL AS NVARCHAR(MAX)
SET #SQL = 'SELECT' + QUOTENAME(#TableName) + ',' + QUOTENAME(#ColumnName) + ', MAX(CASE Charindex(''.'',' + #Columns + ')
WHEN 0 THEN 0
ELSE
Len (Cast(Cast(Reverse(CONVERT(VARCHAR(50), ' + #Columns + ', 128)
) AS FLOAT) AS BIGINT))
END) AS MAX_LENGTH'
--use print to view and copy your dynamic sql string to see if you have formed it correctly
PRINT #SQL
--EXECUTE (#SQL)
FETCH NEXT FROM FLOAT_COLUMNS
INTO #TableName, #ColumnName
END
CLOSE FLOAT_COLUMNS
DEALLOCATE FLOAT_COLUMNS

not sure if this is what you need,but this is how i would do it:
DECLARE #cols NVARCHAR(MAX)
,#table NVARCHAR(MAX)
,#sql NVARCHAR(MAX)
,#X INT = 1
WHILE #X < (
SELECT MAX(ROWID) FROM
(
SELECT quotename(COLUMN_NAME) col
,ROW_NUMBER()over(ORDER BY COLUMN_NAME) ROWID
FROM INFORMATION_SCHEMA.COLUMNS A
inner join INFORMATION_SCHEMA.TABLES B
on A.TABLE_NAME = B.TABLE_NAME
where TABLE_TYPE = 'BASE TABLE'
and DATA_TYPE = 'Float'
) AS X
WHERE ROWID < 10
)
BEGIN
SET #cols =
(SELECT col FROM
(
SELECT quotename(COLUMN_NAME) col
,ROW_NUMBER()over(ORDER BY COLUMN_NAME) ROWID
FROM INFORMATION_SCHEMA.COLUMNS A
inner join INFORMATION_SCHEMA.TABLES B
on A.TABLE_NAME = B.TABLE_NAME
where TABLE_TYPE = 'BASE TABLE'
and DATA_TYPE = 'Float'
) AS X
WHERE ROWID = #X
)
SET #table =
(SELECT tablename FROM
(
SELECT quotename(A.TABLE_NAME) tablename
,ROW_NUMBER()over(ORDER BY COLUMN_NAME) ROWID
FROM INFORMATION_SCHEMA.COLUMNS A
inner join INFORMATION_SCHEMA.TABLES B
on A.TABLE_NAME = B.TABLE_NAME
where TABLE_TYPE = 'BASE TABLE'
and DATA_TYPE = 'Float'
) AS X
WHERE ROWID = #X
)
Set #sql = 'SELECT MAX(CASE Charindex(''.'',' + #cols + ')
WHEN 0 THEN 0
ELSE
Len (Cast(Cast(Reverse(CONVERT(VARCHAR(50), ' + #cols + ', 128)
) AS FLOAT) AS BIGINT))
END) AS MAX_LENGTH
,MAX(CASE Charindex(''.'',' + #table + ')
WHEN 0 THEN 0
ELSE
Len (Cast(Cast(Reverse(CONVERT(VARCHAR(50), ' + #table + ', 128)
) AS FLOAT) AS BIGINT))
END) AS MAX_LENGTH'
PRINT(#sql)
SET #X = #X +1
END

I believe this script can help you :
DECLARE #Query TABLE (SchemaName VARCHAR(100)
,TableName VARCHAR(100)
,ColumnName VARCHAR(1000)
)
INSERT INTO #Query
SELECT A.TABLE_SCHEMA,A.TABLE_NAME,' MAX(CASE Charindex(''.'',' + QUOTENAME(COLUMN_NAME) + ')
WHEN 0 THEN 0
ELSE Len (Cast(Cast(Reverse(CONVERT(VARCHAR(50), ' + QUOTENAME(COLUMN_NAME) + ', 128) ) AS FLOAT) AS BIGINT))
END) AS ['+COLUMN_NAME+'_MAX_LENGTH]'
FROM INFORMATION_SCHEMA.COLUMNS A
INNER JOIN INFORMATION_SCHEMA.TABLES B
ON A.TABLE_NAME = B.TABLE_NAME
WHERE TABLE_TYPE = 'BASE TABLE'
AND DATA_TYPE = 'FLOAT'
SELECT 'SELECT '+
STUFF((
SELECT ',' + ColumnName
FROM #Query Q2
WHERE Q1.SchemaName=q2.SchemaName AND Q1.TableName=q2.TableName
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 2, '')
+' FROM '+Q1.SchemaName+'.'+Q1.TableName
FROM
(SELECT DISTINCT SchemaName,TableName FROM #Query) Q1

use BRSDATA;
begin try drop table #temp end try begin catch end catch ;
DECLARE #TableName nvarchar(250);
DECLARE #ColumnName nvarchar(250);
declare #x int;
DECLARE #FLOATV as float = 3.141592653;--searching for this in all float vals in all tables
SELECT t.name,c.name colname
into #temp
FROM sys.tables AS t
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
inner join sys.columns AS c
on c.object_id = t.object_id
WHERE s.name = 'dbo'
and type_desc = 'USER_TABLE'
and exists(select * from sys.types where name = 'float' and system_type_id = c.system_type_id);
SET Nocount on;
DECLARE FLOAT_TAB CURSOR FOR
SELECT DISTINCT [name] from #temp;
OPEN FLOAT_TAB;
FETCH NEXT FROM FLOAT_TAB
INTO #TableName;
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #SQL nvarchar(max) = '';
DECLARE #COND nvarchar(max) = '';
SET #SQL = 'SELECT ';
DECLARE COL_TAB CURSOR FOR
SELECT colname from #temp where name = #TableName;
OPEN COL_TAB;
FETCH NEXT FROM COL_TAB
INTO #ColumnName;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = #SQL + ' ' + #ColumnName + ',';
SET #COND = #COND + #ColumnName + ' = ' + cast(#floatv as nvarchar(60)) + ' OR ' ;
FETCH NEXT FROM col_tab INTO #ColumnName
END
SET #SQL = LEFT(#SQL, len(#sql) - 1) + ' FROM ' + #TableName + ' WHERE ' + LEFT(#COND, LEN(#COND) - 3);
print #sql;
EXECUTE ( #SQL);
close col_tab;
deallocate col_tab;
--waitfor delay '00:05';
FETCH NEXT FROM FLOAT_TAB into #tablename;
END
close float_tab
deallocate float_tab;

Related

Dynamic Insert statement need to return the ID that was inserted

I have a trigger I've completed and during the trigger operation I insert into a Master table some records then I need to use the ID from the master table to insert some records into a detail table.
I'm not sure how to get the ID from the master table after insert so that I can use in detail table. This is my trigger code:
IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME= 'DATA_HIL_Master')
BEGIN
DECLARE #sql NVARCHAR(MAX),
#TABLE_NAME sysname
SET NOCOUNT ON
SELECT #TABLE_NAME = MIN(TABLE_NAME)
FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME != 'sysdiagrams'
AND TABLE_NAME != 'Audit'
AND TABLE_NAME = 'ADM_Gate'
WHILE #TABLE_NAME IS NOT NULL
BEGIN
EXEC('IF OBJECT_ID (''' + #TABLE_NAME + '_ChangeTracking'', ''TR'') IS NOT NULL DROP TRIGGER ' + #TABLE_NAME + '_ChangeTracking')
SELECT #sql =
'create trigger ' + #TABLE_NAME + '_ChangeTracking on ' + #TABLE_NAME + ' for insert, update, delete
as
declare #bit int ,
#field int ,
#maxfield int ,
#char int ,
#fieldname varchar(128) ,
#TableName varchar(128) ,
#PKCols varchar(1000) ,
#sql nvarchar(max),
#Type int ,
#PKFieldSelect varchar(1000),
#PKValueSelect varchar(1000),
#MasterId nvarchar(1)
select #TableName = ''' + #TABLE_NAME + '''
if exists (select * from inserted)
if exists (select * from deleted)
select #Type = 2
else
select #Type = 3
else
select #Type = 1
select * into #ins from inserted
select * into #del from deleted
select #PKCols = coalesce(#PKCols + '' and'', '' on'') + '' i.'' + c.COLUMN_NAME + '' = d.'' + c.COLUMN_NAME
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE c on c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME and c.TABLE_NAME = pk.TABLE_NAME
where pk.TABLE_NAME = #TableName
and CONSTRAINT_TYPE = ''PRIMARY KEY''
select #PKFieldSelect = coalesce(#PKFieldSelect + ''+'', '''') + '''''''' + COLUMN_NAME + ''''''''
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE c on c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME and c.TABLE_NAME = pk.TABLE_NAME
WHERE pk.TABLE_NAME = #TableName
AND CONSTRAINT_TYPE = ''PRIMARY KEY''
select #PKValueSelect = coalesce(#PKValueSelect+''+'','''') + ''convert(varchar(100), coalesce(i.'' + COLUMN_NAME + '',d.'' + COLUMN_NAME + ''))''
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE c on c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME and c.TABLE_NAME = pk.TABLE_NAME
where pk.TABLE_NAME = #TableName
and CONSTRAINT_TYPE = ''PRIMARY KEY''
select #sql = ''insert DATA_HIL_Master (OperationType, ReferenceTable, ReferenceId, Last_UserId_Log, Last_WorkstationId_Log, Last_DateTime_Log)''
if #Type = 1
select #sql = #sql + '' select 1 ''
if #Type = 2
select #sql = #sql + '' select 2 ''
if #Type = 3
select #sql = #sql + '' select 3''
select #sql = #sql + '', '''''' + #TableName + ''''''''
select #sql = #sql + '','' + #PKValueSelect
select #sql = #sql + '',convert(varchar(1000),i.Last_UserId_Log)''
select #sql = #sql + '',convert(varchar(1000),i.Last_WorkstationId_Log)''
select #sql = #sql + '',convert(varchar(1000),i.Last_DateTime_Log)''
select #sql = #sql + '' from #ins i full outer join #del d''
select #sql = #sql + #PKCols
EXECUTE sp_executesql #sql
select #MasterId
select #field = 0,
#maxfield = max(ORDINAL_POSITION)
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = #TableName
while #field < #maxfield
begin
select #field = min(ORDINAL_POSITION)
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = #TableName
and ORDINAL_POSITION > #field
select #bit = (#field - 1 )% 8 + 1
select #bit = power(2,#bit - 1)
select #char = ((#field - 1) / 8) + 1
if substring(COLUMNS_UPDATED(),#char, 1) & #bit > 0 or #Type in (1,3)
begin
select #fieldname = COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = #TableName and ORDINAL_POSITION = #field
select #sql = ''insert data_HIL_Detail (MasterId, ColumnName, OriginalValue, ModifiedValue)''
select #sql = #sql + '' select convert(varchar(1000),'' + #MasterId + '')''
select #sql = #sql + '','''''' + #fieldname + ''''''''
select #sql = #sql + '', convert(varchar(1000),d.'' + #fieldname + '')''
select #sql = #sql + '', convert(varchar(1000),i.'' + #fieldname + '')''
select #sql = #sql + '' from #ins i full outer join #del d''
select #sql = #sql + #PKCols
select #sql = #sql + '' where i.'' + #fieldname + '' <> d.'' + #fieldname
select #sql = #sql + '' or (i.'' + #fieldname + '' is null and d.'' + #fieldname + '' is not null)''
select #sql = #sql + '' or (i.'' + #fieldname + '' is not null and d.'' + #fieldname + '' is null)''
select #sql
end
END '
SELECT #sql
EXEC(#sql)
SELECT #TABLE_NAME = MIN(TABLE_NAME)
FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_NAME> #TABLE_NAME
AND TABLE_TYPE= 'BASE TABLE'
AND TABLE_NAME!= 'sysdiagrams'
AND TABLE_NAME!= 'Audit'
AND TABLE_NAME = 'ADM_Gate'
END
END
WEI_DBA mentions SCOPE_IDENTITY() above, but there is a complexity that will affect you, because the code executed by the sp_executeSQL statement is not actually in the same scope as the trigger. However, this issue is easy to work around by using an OUTPUT parameter on your sp_executeSQL call. Your use of an NVARCHAR(1) data type for your ID, and then casting it to a VARCHAR(1000) doesn't make a lot of sense, but I'll work with it for this example. Consider this code excerpt from your trigger. I have rewritten it to use an output parameter also called #MasterID:
select #sql = #sql + '' from #ins i full outer join #del d''
select #sql = #sql + #PKCols + ''; SET #MasterId = SCOPE_IDENTITY() -- Or whatever your ID is''
DECLARE #Parms nvarchar(40)
SET #Parms = N''#MasterId Nvarchar(1) OUTPUT'';
EXECUTE sp_executesql #sql, #Parms, #MasterId = #MasterId Output
-- select #MasterId -- #MasterId is set to the #MasterId returned by sp_executesql
At this point, your #MasterId has the value returned by your code in the dynamic SQL statement.

Creating a column loop within a table loop to calculate fill rate for all fields in a database

I have 2 databases with over 400 tables for which I have to calculate fill rates. I have a loop for calculating fill rates for all columns in a table, but how can I do it for all tables in a database?? Please help!
I am using SQL Server.
Here is the code for looping through all columns in a table for calculating fill rate-
DECLARE #Table NVARCHAR(max) = 'dbo.[TableName]'
,#MetaTable NVARCHAR(128) = '#TempTable'
,#ColumnName NVARCHAR(128)
,#Iterator INT = 1
,#SQL1 NVARCHAR(MAX)
SELECT c.NAME
,c.COLUMN_ID
,ROW_NUMBER() OVER (ORDER BY COLUMN_ID) AS RN
INTO #Cols
FROM SYS.COLUMNS c
WHERE c.OBJECT_ID = OBJECT_ID(#Table);
WHILE #Iterator <= (SELECT ISNULL(MAX(RN),0) FROM #Cols)
BEGIN
SET #ColumnName = (SELECT NAME FROM #Cols WHERE RN = #Iterator)
SET #SQL1 = 'INSERT INTO ' + #MetaTable + ' (Table_Name, Column_Name,
Fill_Rate) '
+ 'SELECT ''' + REPLACE(#Table,'DBO.','') + ''', ''' +
#ColumnName + ''', 100 * CONVERT(DECIMAL(8,3), SUM(CASE WHEN [' +
#ColumnName + '] IS NULL THEN 0 ELSE 1 END)) / COUNT(1) AS [' +
#ColumnName + '_fill]' + ' FROM ' + #Table
EXEC sp_executesql #SQL1
SET #Iterator += 1
END
I suggest to use a cursor for this neat little task:
CREATE TABLE #MetaTable (
TABLE_SCHEMA sysname,
TABLE_NAME sysname,
COLUMN_NAME sysname,
fill_rate float NULL);
DECLARE
#schema sysname,
#table sysname,
#column sysname,
#sql nvarchar(max);
DECLARE column_cusor CURSOR FAST_FORWARD FOR
SELECT s.name, t.name, c.name
FROM sys.schemas s
INNER JOIN sys.tables t ON s.schema_id = t.schema_id
INNER JOIN sys.columns c ON t.object_id = c.object_id;
OPEN column_cusor;
FETCH NEXT FROM column_cusor INTO #schema, #table, #column;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'SELECT ' + QUOTENAME(#schema, '''')
+ ', ' + QUOTENAME(#table, '''')
+ ', ' + QUOTENAME(#column, '''')
+ ', ' + '100.0 * SUM(CASE WHEN ' + QUOTENAME(#column)
+ ' IS NULL THEN 0 ELSE 1 END) /'
+ ' CASE WHEN COUNT(*) = 0 THEN 1 ELSE COUNT(*) END'
+ ' FROM ' + QUOTENAME(#schema) + '.' + QUOTENAME(#table);
INSERT INTO #MetaTable (TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, fill_rate)
EXEC (#sql);
FETCH NEXT FROM column_cusor INTO #schema, #table, #column;
END
CLOSE column_cusor;
DEALLOCATE column_cusor;
SELECT * FROM #MetaTable;

How to get Max Date Value of Date column in Multiple tables

For example I have 2 tables in Database.
Ex :
Table T :
declare #t table (name varchar(20),DOB date)
Insert into #t (name,DOB) values ('Mohan','2001-07-19')
Insert into #t (name,DOB) values ('Minu','1998-06-19')
Table : TT
declare #tt table (name varchar(20),DOB date)
Insert into #tt (name,DOB) values ('Raju','2010-07-19')
Insert into #tt (name,DOB) values ('Rani','2001-06-19')
Now I have a Query to get Table name and column names of multiple tables basing on Date type filter .
SELECT C.TABLE_SCHEMA, c.TABLE_NAME,c.COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS c
JOIN sys.objects o ON o.name = c.TABLE_NAME
WHERE o.type = 'U' AND C.DATA_TYPE = 'Datetime'
Output :
T_Schema T_name T_column
dbo T DOB
dbo TT DOB
But how can I get max Date of both tables like below output :
T_Schema T_name T_column Max_dt
dbo T DOB 2001-07-19
dbo TT DOB 2010-07-19
Suggest me the best way to achieve this.
Here is another option that doesn't use a cursor. I doubt it will be any better from a performance perspective because you still need a subquery for every row. But I really hate cursors. I also used the system tables instead of the information schema views as those can sometimes be a bit odd. https://sqlblog.org/2011/11/03/the-case-against-information_schema-views
declare #SQL nvarchar(max) = N''
select #SQL = #SQL +
N'select SCHEMA_NAME = ''' + QUOTENAME(s.name) + ''', TABLE_NAME = '''
+ QUOTENAME(o.name) + ''', COLUMN_NAME = '''
+ QUOTENAME(c.name) + ''', MaxDate = '
+ '(select MAX(' + QUOTENAME(c.name) + ') from ' + QUOTENAME(s.name) + '.' + QUOTENAME(o.name) + ') UNION ALL '
from sys.columns c
join sys.systypes st on st.type = c.system_type_id
join sys.objects o on o.object_id = c.object_id and o.type = 'U'
join sys.schemas s on s.schema_id = o.schema_id
where st.name = 'datetime'
order by s.name
, o.name
, c.name
set #SQL = left(#SQL, len(#SQL) - 10) --removes final UNION ALL
select #SQL
--uncomment below when you are satisfied the dynamic sql is correct
--exec sp_executesql #SQL
Here's some dynamic SQL that should do what you want, via a cursor.
I'd caution using this if you have a lot of tables, or run this in test first. Cursors are not great performs generally speaking. You can run this against a system database, like master, which would have fewer values to see how it works.
create table #MaxDate (tname varchar(256), cname varchar(256), mdate datetime)
declare cur cursor local fast_forward
for
SELECT C.TABLE_SCHEMA, c.TABLE_NAME,c.COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS c
JOIN sys.objects o ON o.name = c.TABLE_NAME
WHERE o.type = 'U' AND C.DATA_TYPE = 'Datetime'
declare #schema varchar(64), #table varchar(256), #column varchar(256)
declare #sql varchar(max)
open cur
fetch next from cur into #schema, #table, #column
while ##FETCH_STATUS = 0
begin
set #sql = 'select ''' + #table + '''' + ',''' + '' + #column + '''' + ',' + 'max(' + #column + ') from ' + #schema + '.' + #table
print #sql
insert into #MaxDate
exec (#sql)
fetch next from cur into #schema, #table, #column
end
close cur
deallocate cur
select * from #MaxDate
drop table #MaxDate
Here's an answer using a cursor, dynamic SQL and a temporary table:
DECLARE table_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT
C.TABLE_SCHEMA,
c.TABLE_NAME,
c.COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS c
JOIN sys.objects o
ON o.name = c.TABLE_NAME
WHERE o.type = 'U'
AND C.DATA_TYPE = 'Datetime'
DECLARE #schema SYSNAME
DECLARE #table SYSNAME
DECLARE #column SYSNAME
DECLARE #sql NVARCHAR(1000)
CREATE TABLE #Data (SchemaName SYSNAME, TableName SYSNAME, ColumnName SYSNAME, MaxDate DATETIME)
OPEN table_cursor
FETCH NEXT FROM table_cursor INTO #schema, #table, #column
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'INSERT INTO #Data (SchemaName, TableName, ColumnName, MaxDate) SELECT '''+#schema+''', '''+#table+''', '''+#column+''', MAX(['+#column+']) FROM ['+#schema+'].['+#table+']'
EXEC sp_executesql #sql
FETCH NEXT FROM table_cursor INTO #schema, #table, #column
END
CLOSE table_cursor
DEALLOCATE table_cursor
SELECT * FROM #Data
DROP TABLE #Data
SQL to BUILD SQL for you
DECLARE #SQL as nvarchar(max) ='';
select #SQL = #SQL + 'SELECT ' + Column_Name + ' adate, ''' + Column_Name + ''' colname, ''' + Table_name + ''' tabname FROM ' + Table_name + ' UNION ' FROM INFORMATION_SCHEMA.COLUMNS where data_type like '%date%'
select #SQL = 'SELECT TOP 100 * FROM (' + LEFT(#SQL, LEN(#SQL) -6) + ') IQ WHERE IQ.adate IS NOT null ORDER BY IQ.adate DESC';
--cut n paste the sql below, see what it does for you
select #SQL
mark II - executes sql for you, and sorts out names with spaces in them
DECLARE #SQL as nvarchar(max) ='';
select #SQL = #SQL + 'SELECT [' + Column_Name + '] adate, ''' + Column_Name + ''' colname, ''' + Table_name + ''' tabname FROM [' + Table_name + '] UNION ' FROM INFORMATION_SCHEMA.COLUMNS where data_type like '%date%'
select #SQL = 'SELECT TOP 100 * FROM (' + LEFT(#SQL, LEN(#SQL) -6) + ') IQ WHERE IQ.adate IS NOT null ORDER BY IQ.adate DESC';
select #SQL;
EXEC sp_executesql #sql;

select columns with value NA

How to select columns in a table that only contain a specific value for all the rows? I am trying to find these columns to do an update on those values with a NULL value. In my columns I have varied range of values including NA
I am using SQL Server 2012.
I've tried doing: thsi only gives me column names. Can i add to this condition for columns with value 'NA'?
SELECT COLUMN_NAME AS NAMES,COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'ABC'
I am a beginner in SQL. Trying to figure out how to do this.
If min of column equals to max then that column contains same values:
Select
case when min(col1) = max(col1) then 1 else 0 end as Col1IsSame,
case when min(col2) = max(col2) then 1 else 0 end as Col2IsSame,
...
from Table
With dynamic query:
declare #s nvarchar(max) = 'select '
select #s = #s + 'case when min(' + COLUMN_NAME + ') = max(' +
COLUMN_NAME + ') then 1 else 0 end as ' + COLUMN_NAME + ','
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'Table'
Set #s = substring(#s, 1, len(#s) - 1) + ' from Table'
exec(#s)
TRY THIS QUERY
DECLARE #SQLQUERY NVARCHAR(MAX)
declare #tableName varchar(50)
DECLARE #NAME VARCHAR(50)
Declare #ParamDefinition AS NVarchar(2000)
Set #ParamDefinition = '#OIM VARCHAR(20)'
SELECT NAME
FROM sys.objects
WHERE [object_id]=#OIM
set #tableName= (SELECT NAME
FROM sys.objects
WHERE [object_id]=#OIM)
SET #NAME=(SELECT C.NAME
FROM sys.columns c
JOIN
sys.tables t ON c.object_id = t.object_id
WHERE c.name in (select distinct name
from sys.columns
where object_id=#OIM))
SET #SQLQUERY = ''
SELECT #SQLQUERY = #SQLQUERY + 'UPDATE ' + #tableName + ' SET ' + #NAME + ' = NULL WHERE ' + #NAME + ' = NA ; '
PRINT #SQLQUERY
Execute sp_Executesql #SQLQUERY , #ParamDefinition, #OIM
end

SELECT REPLACE on every column

I have a table containing around 100 columns, is it to possible to do a Select Replace on every column at the same time rather than typing out each column individually, i'm trying to trim the '"' of each field in the table.
SELECT
REPLACE(*, '"', '')
DECLARE #tablename nvarchar(100)= 'Test'
DECLARE #col nvarchar(max)
SELECT #col = coalesce(#col + ',', 'select ' ) +
case when data_type in ('varchar', 'char','nvarchar', 'nchar') then
'replace('+column_name+' , ''"'', '''') '+' as [' + column_name + ']' else '[' + column_name + ']' end
FROM INFORMATION_SCHEMA.COLUMNS a
WHERE table_name = #tablename
SET #col += ' from ' + #tablename
EXEC (#col)
Since you're using SQL Server, you can retrieve the names of all columns on a table using the INFORMATION_SCHEMA, e.g.
select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'yourTable'
You can then use a cursor to iterate over each column name, build some dynamic SQL and execute this using 'exec sp_executesql'.
Here's my solution:
declare #isString bit
declare #tableName nvarchar(256) = N'MyTableName'
declare #columnName nvarchar(max)
declare #sql nvarchar(max) = ''
declare c cursor local forward_only read_only for
select column_name, case when CHARACTER_SET_NAME is null then 0 else 1 end as IsString
from information_schema.COLUMNS WHERE table_name = #tableName
open c
fetch next from c into #columnName, #isString
set #sql = N'select '
declare #first bit = 1
while ##FETCH_STATUS = 0
begin
select #columnName
if #isString <> 0
begin
if #first = 0
begin
set #sql = #sql + ', '
end
set #sql = #sql + N'REPLACE(' + #columnName + ', ''"'', '''')'
set #first = 0
end
fetch next from c into #columnName, #isString
end
close c
deallocate c
set #sql = #sql + ' from ' + #tableName
exec sp_executesql #sql
Here is a recursive version:
declare #TABLE_NAME sysname = 'MyTableName'
declare #Prefix nvarchar(128) = 'REPLACE('
declare #Suffix nvarchar(128) = ', ''"'', '''')'
declare #Sql nvarchar(max)
;with Cols (TABLE_NAME, SELECT_LIST, ITERATION) as
(
select TABLE_NAME
, cast('' as nvarchar(max)) as SELECT_LIST
, 0 as ITERATION
from INFORMATION_SCHEMA.TABLES
where TABLE_NAME = #TABLE_NAME
union all
select c.TABLE_NAME
, c.SELECT_LIST
+ case when len(c.SELECT_LIST) > 0 then ', ' else '' end
+ case when i.DATA_TYPE like '%char' then #Prefix else '' end
+ cast(i.COLUMN_NAME as nvarchar(128))
+ case when i.DATA_TYPE like '%char' then #Suffix + ' as ' + cast(i.COLUMN_NAME as nvarchar(128)) else '' end
, c.ITERATION + 1
from INFORMATION_SCHEMA.COLUMNS i
join Cols c on i.TABLE_NAME = c.TABLE_NAME
where i.ORDINAL_POSITION = c.ITERATION + 1
)
select #Sql = ('select ' + a.SELECT_LIST + ' from ' + a.TABLE_NAME)
from Cols a
join (
select TABLE_NAME, max(ITERATION) as ITERATION
from Cols
group by TABLE_NAME
) as b on a.TABLE_NAME = b.TABLE_NAME
and a.ITERATION = b.ITERATION
exec (#sql)