SQL Server: Alternative for using Exec in Functions - sql

I am trying to create a Function that I could call to check which is the next ID in key of each table in my database. I figure out how to do it, but I can not create the function because I get this error:
"Invalid use of a side-effecting operator 'INSERT EXEC' within a function."
It seems that I can not use Exec in Functions. Which alternatives could I have to get this information?
This is my code:
CREATE FUNCTION FCN_ProximoID()
RETURNS #TablaID Table (Tabla nvarchar(370), ID int)
AS
BEGIN
-- Fill the table variable with the rows for your result set
DECLARE #Row INT
DECLARE #Filas INT
DECLARE #MaxID INT
DECLARE #Query As varchar(max)
DECLARE #TableName nvarchar(256), #ColumnName nvarchar(128)
SET #Filas = (SELECT MAX(Fila)
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY A.TABLE_NAME) AS 'Fila',
A.TABLE_NAME As Tabla, A.COLUMN_NAME As Columna,
A.ORDINAL_POSITION As Indice, B.DATA_TYPE As TipoDato
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE A
LEFT JOIN INFORMATION_SCHEMA.COLUMNS B
ON A.COLUMN_NAME = B.COLUMN_NAME AND A.TABLE_NAME=B.TABLE_NAME
WHERE LEFT(A.TABLE_NAME,3)='EXT' AND OBJECTPROPERTY(OBJECT_ID
(constraint_name), 'IsPrimaryKey')=1 AND B.DATA_TYPE='int'
) As Tablas)
SET #Row = 1
WHILE (#Row <= #Filas)
BEGIN
BEGIN
SET #TableName = (SELECT Tabla
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY A.TABLE_NAME) AS 'Fila',
A.TABLE_NAME As Tabla, A.COLUMN_NAME As Columna,
A.ORDINAL_POSITION As Indice, B.DATA_TYPE As TipoDato
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE A
LEFT JOIN INFORMATION_SCHEMA.COLUMNS B
ON A.COLUMN_NAME = B.COLUMN_NAME AND
A.TABLE_NAME=B.TABLE_NAME
WHERE LEFT(A.TABLE_NAME,3)='EXT' AND OBJECTPROPERTY(OBJECT_ID
(constraint_name), 'IsPrimaryKey')=1 AND B.DATA_TYPE='int'
) As Tablas WHERE Fila=#Row)
SET #ColumnName = (SELECT Columna
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY A.TABLE_NAME) AS 'Fila',
A.TABLE_NAME As Tabla, A.COLUMN_NAME As Columna,
A.ORDINAL_POSITION As Indice, B.DATA_TYPE As TipoDato
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE A
LEFT JOIN INFORMATION_SCHEMA.COLUMNS B
ON A.COLUMN_NAME = B.COLUMN_NAME AND
A.TABLE_NAME=B.TABLE_NAME
WHERE LEFT(A.TABLE_NAME,3)='EXT' AND
OBJECTPROPERTY(OBJECT_ID
(constraint_name), 'IsPrimaryKey')=1
AND B.DATA_TYPE='int'
) As Tablas WHERE Fila=#Row)
INSERT INTO #TablaID
EXEC('SELECT ''' + #TableName + ''', ISNULL(MAX(' + #ColumnName + '),0)+1 FROM ' + #TableName )
SET #Row = #Row + 1
END
END
RETURN
END
GO

Exec is not allowed in functions, but it is allowed in stored procedures, so you can just rewrite the function as a stored procedure which retuns a resultset.

Related

Dynamic SQL stored procedure not populating temporary table

I am using a stored procedure with one parameter (#tablename) to generate a table of attributes about the table named via the parameter.
I call the stored procedure as follows
EXEC sp_Schema_Presentation #tablename = 'UserID'
And run the stored procedure (at the bottom of this post).
I have created a #DynamicSQL string in order to use my #tablename parameter. However, the SELECT statement, in which it's used, also creates the #TEMP table.
The rest of the query uses this #TEMP table so I DECLARE its structure at the top.
However, when I run the stored procedure, the #TEMP table is empty
If I hard code the #tablename, the query will work. Any ideas how I can fix this?
Thanks
CREATE TABLE #TEMP
(
SampleKey nvarchar(MAX),
SampleData nvarchar(MAX)
)
DECLARE #DynamicSQL NVARCHAR(MAX)
SET #DynamicSQL = N'SELECT B.*
INTO dbo.#TEMP
FROM (
SELECT * FROM ' + #Tablename + N' ORDER BY 1 DESC
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY
) A
CROSS APPLY (
SELECT [Key] AS SampleKey
,Value AS SampleData
FROM OpenJson( (SELECT A.* FOR JSON Path, Without_Array_Wrapper,INCLUDE_NULL_VALUES ) )
) B'
Full stored procedure in SQL Server 2016:
ALTER PROCEDURE [dbo].[sp_Schema_Presentation]
#TableName nvarchar(MAX)
AS
BEGIN
CREATE TABLE #TEMP
(
SampleKey nvarchar(MAX),
SampleData nvarchar(MAX)
)
DECLARE #DynamicSQL NVARCHAR(MAX)
SET #DynamicSQL = N'SELECT B.*
INTO dbo.#TEMP
FROM (
SELECT * FROM ' + #Tablename + N' ORDER BY 1 DESC
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY
) A
CROSS APPLY (
SELECT [Key] AS SampleKey
,Value AS SampleData
FROM OpenJson( (SELECT A.* FOR JSON Path, Without_Array_Wrapper,INCLUDE_NULL_VALUES ) )
) B'
DECLARE #Columns as NVARCHAR(MAX)
SELECT #Columns = COALESCE(#Columns + ', ','') + QUOTENAME(COLUMN_NAME)
FROM
(
SELECT COLUMN_NAME FROM PRESENTATION_PP.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = N''' + #TableName + '''
) AS B
EXECUTE sp_executesql #DynamicSQL
SELECT a.COLUMN_NAME,
CASE WHEN a.COLUMN_NAME LIKE '%[_]_key' THEN a.COLUMN_NAME
ELSE REPLACE(a.COLUMN_NAME,'_',' ') END AS DISPLAY_NAME,
a.DATA_TYPE, COALESCE(a.CHARACTER_MAXIMUM_LENGTH, a.NUMERIC_PRECISION) AS SIZE,
CASE WHEN NUMERIC_SCALE IS NULL THEN 0
ELSE NUMERIC_SCALE END AS SCALE,
a.IS_NULLABLE AS NULLABLE,
CASE WHEN i.is_primary_key IS NOT NULL THEN 'YES'
ELSE 'NO' END AS PK,
#TEMP.SampleData
FROM PRESENTATION_PP.INFORMATION_SCHEMA.COLUMNS a
LEFT JOIN
sys.columns c ON a.COLUMN_NAME = c.name
LEFT JOIN
sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
LEFT JOIN
sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
LEFT JOIN
#TEMP ON a.COLUMN_NAME COLLATE SQL_Latin1_General_CP1_CI_AI = #TEMP.SampleKey COLLATE SQL_Latin1_General_CP1_CI_AI
WHERE TABLE_NAME = #TableName AND c.object_id = OBJECT_ID(#TableName)
SELECT * FROM #TEMP
DROP TABLE #TEMP
END
Create the #Temp table first, and then INSERT INTO not Select ... Into #Temp
CREATE TABLE #TEMP (SampleKey nvarchar(MAX), SampleData nvarchar(MAX))
DECLARE #DynamicSQL NVARCHAR(MAX)
SET #DynamicSQL = N'
Insert Into #Temp
SELECT B.*
FROM (
SELECT * FROM ' + #Tablename + N' ORDER BY 1 DESC
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY
) A
CROSS APPLY (
SELECT [Key] AS SampleKey
,Value AS SampleData
FROM OpenJson( (SELECT A.* FOR JSON Path, Without_Array_Wrapper,INCLUDE_NULL_VALUES ) )
) B
'
Exec(#DynamicSQL)
Select * from #Temp

Dynamic SQL to get rows from information_schema

Let’s say I’m looking for a specific column in my database so I have something like this
SELECT COLUMN_NAME, TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME like ‘%employeeid%’
But I also want to know how many rows each table has, I was told I can do this using Dynamic SQL so I have this now
DECLARE
#tableName NVARCHAR(MAX),
#sql NVARCHAR(MAX),
#colName NVARCHAR(MAX);
DECLARE CUR_TABLE CURSOR FOR
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS
OPEN CUR_TABLE
FETCH NEXT FROM CUR_TABLE
INTO #tableName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #colName = '%employeeid%'
SET #sql = 'SELECT COLUMN_NAME, TABLE_NAME, (SELECT COUNT(*) FROM ' + #tableName +') AS ROWS FROM INFORMATION_SCHEMA.COLUMNS where column_name like ' + ''' + #colName + ''';
FETCH NEXT FROM CUR_TABLE
INTO #tableName
END;
CLOSE CUR_TABLE
DEALLOCATE CUR_TABLE
EXEC sp_executesql #sql
But this doesn't work, What I'm trying to do is query a table with the column I am looking for, with the table name, and number of rows in the table.
How can I fix this?
You can make use of SQL Server's dynamic management views to quickly obtain the row counts*.
Find all tables with a column named 'MyColumn' and their current rows:
select Schema_Name(t.schema_id) schemaName, t.name TableName, s.row_count
from sys.columns c
join sys.tables t on t.object_id = c.object_id
join sys.dm_db_partition_stats s on s.object_id = c.object_id and s.index_id <= 1
where c.name='MyColumn';
* Accurate except for frequently updated tables where there could be some lag
The following uses INFORMATION_SCHEMA, dynamic SQL, and STRING_AGG() to build a query that will return a single result set.
DECLARE #ColumnName sysname = 'ProductID'
DECLARE #Newline VARCHAR(2) = CHAR(13) + CHAR(10)
DECLARE #SqlTemplate NVARCHAR(MAX) =
+ 'SELECT'
+ ' ColumnName = <ColumnNameString>,'
+ ' TableName = <TableSchemaAndNameString>,'
+ ' Rows = (SELECT COUNT(*) FROM <TableSchemaAndName>)'
+ #Newline
DECLARE #UnionSql NVARCHAR(100) = 'UNION ALL ' + #Newline
DECLARE #Sql NVARCHAR(MAX) = (
SELECT STRING_AGG(
REPLACE(REPLACE(REPLACE(
#SqlTemplate
, '<ColumnNameString>', QUOTENAME(C.COLUMN_NAME, ''''))
, '<TableSchemaAndNameString>', QUOTENAME(C.TABLE_SCHEMA + '.' + C.TABLE_NAME, ''''))
, '<TableSchemaAndName>', QUOTENAME(C.TABLE_SCHEMA) + '.' + QUOTENAME(C.TABLE_NAME))
, #UnionSql)
WITHIN GROUP(ORDER BY C.TABLE_SCHEMA, C.TABLE_NAME)
FROM INFORMATION_SCHEMA.TABLES T
JOIN INFORMATION_SCHEMA.COLUMNS C
ON C.TABLE_SCHEMA = T.TABLE_SCHEMA
AND C.TABLE_NAME = T.TABLE_NAME
WHERE T.TABLE_TYPE = 'BASE TABLE' -- Omit views
AND C.COLUMN_NAME = #ColumnName
)
SET #Sql = #Sql + 'ORDER BY Rows DESC, TableName' + #Newline
--PRINT #Sql
EXEC (#Sql)
I generalized it a bit by adding TABLE_SCHEMA so that it could be used with the AdventureWorks database. See this db<>fiddle for a working demo. Also included is equivalent logic that uses FOR XML instead of STRING_AGG for older SQL Server versions.
Assuming that you are using SQL Server, here is a shorthand way using sp_msforeachtable.
DECLARE #ColumnName NVARCHAR(200) = 'ContactID'
CREATE TABLE #T
(
ColumnName NVARCHAR(200),
TableName NVARCHAR(200),
RecordCount INT
)
INSERT INTO #T (ColumnName, TableName)
SELECT
ColumnName = C.COLUMN_NAME,
TableName = '['+C.TABLE_SCHEMA+'].['+C.TABLE_NAME+']'
FROM
INFORMATION_SCHEMA.COLUMNS C
WHERE
C.COLUMN_NAME LIKE '%' + #ColumnName + '%'
EXEC SP_MSFOREACHTABLE 'IF EXISTS(SELECT * FROM #T WHERE TableName = ''?'') UPDATE #T SET RecordCount = (SELECT COUNT(*) FROM ? ) WHERE TableName = ''?'''
SELECT
ColumnName,TableName,
TableType = CASE
WHEN RecordCount IS NULL
THEN 'View'
ELSE 'Table'
END,
RecordCount
FROM
#T
ORDER BY
CASE WHEN RecordCount IS NULL THEN 'View' ELSE 'Table' END
DROP TABLE #T

How to find List Tables using columns value

I have 500+ tables in database. All tables have several columns. Among them Some tables have 'CMDFLAG' column and value of the columns may have 'C'or'D' or 'M'.
My requirement is to find the list of tables where CMDFLAG is 'C'or'D' or 'M'.
Table Name Column Name Value
---------- ----------- -----
Table_A CMDFLAG C
Table_A CMDFLAG D
Table_A CMDFLAG M
Table_B CMDFLAG C
Table_B CMDFLAG D
Table_C CMDFLAG M
so on ...
I can find list of tables these have CMDFLAG column using INFORMATION_SCHEMA.COLUMNS. But I Want to find list of tables where CMDFLAG columns have value 'C'or'D' or 'M'.
I have gone through several questions but can't fulfill my requirement. Moreover I want to use simple query not procedure.
Try this. I have to use dynamic query and temp tables as EXEC does not work for common table expressions.
CREATE TABLE #t1
(
tableName varchar(30),
RN INT
)
CREATE TABLE #t2
(
tableName varchar(30),
columnName varchar(30),
value char(1)
)
INSERT INTO #t1
SELECT C.TABLE_NAME, ROW_NUMBER() OVER(ORDER BY TABLE_NAME) AS RN
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.COLUMN_NAME = 'CMDFLAG'
DECLARE #COUNT AS INT = (SELECT COUNT(1) FROM #t1)
DECLARE #Iterator AS INT = 1
DECLARE #tableName AS VARCHAR(30)
DECLARE #script AS VARCHAR(200)
WHILE #Iterator <= #COUNT
BEGIN
SELECT #tableName = (SELECT tableName FROM #t1 WHERE RN = #Iterator)
SELECT #script = 'SELECT '''+#tableName+''', ''CMDFLAG'', CMDFLAG FROM '+#tableName+' GROUP BY CMDFLAG'
INSERT INTO #t2
EXEC(#script)
SELECT #Iterator = #Iterator + 1
END
SELECT * FROM #t2
DROP TABLE #t1
DROP TABLE #t2
You can do it as follows.
SET NOCOUNT ON;
DECLARE #colname SYSNAME='CMDFLAG';
CREATE TABLE #tablenames(tablename SYSNAME,colname SYSNAME,colval NVARCHAR(128));
DECLARE #dsql NVARCHAR(MAX)= (
SELECT
N'INSERT INTO #tablenames(tablename,colname,colval)'+
N'SELECT DISTINCT ' +
'tablename='''+REPLACE(t.TABLE_NAME,N'''',N'''''')+N''','+
'colname='''+REPLACE(#colname,N'''',N'''''')+N''','+
'colval='+QUOTENAME(#colname)+N' '+
N'FROM '+QUOTENAME(t.TABLE_SCHEMA)+N'.'+QUOTENAME(t.TABLE_NAME)+N' '+
N'WHERE '+QUOTENAME(#colname)+N' IN (''C'',''D'',''M'');'
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=#colname
FOR
XML PATH('')
);
EXECUTE sp_executesql #dsql;
SELECT * FROM #tablenames ORDER BY tablename;
DROP TABLE #tablenames;
How about something like this:
DECLARE #ColumnName sysname = 'CMDFLAG', #Sql NVARCHAR(MAX)
IF OBJECT_ID(N'TempDB.dbo.#Results', N'U') IS NULL
CREATE TABLE #Results(TableName SYSNAME, RowCounts INT)
ELSE
TRUNCATE TABLE #Results
SELECT
#Sql = 'INSERT INTO #Results '
+ STUFF((
SELECT
'UNION ALL SELECT Table_Name = '
+ QUOTENAME(C.TABLE_SCHEMA + '.' + C.TABLE_NAME, '''')
+ ', NumRows = COUNT(*)'
+ ' FROM '
+ QUOTENAME(C.TABLE_SCHEMA) + '.'
+ QUOTENAME(C.TABLE_NAME )
+ ' WHERE ' + QUOTENAME(C.COLUMN_NAME) + ' IN(''C'', ''D'', ''M'') '
+ ' GROUP BY ' + QUOTENAME(C.COLUMN_NAME)
+ ' HAVING COUNT(*) > 0 '
FROM
INFORMATION_SCHEMA.COLUMNS C
CROSS APPLY
(
SELECT
T.TABLE_SCHEMA, T.TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES T
WHERE
T.TABLE_TYPE = 'BASE TABLE'
AND T.TABLE_SCHEMA = C.TABLE_SCHEMA
AND T.TABLE_NAME = C.TABLE_NAME
) T
WHERE
C.COLUMN_NAME = #ColumnName
FOR XML PATH(''), type).value('.', 'nvarchar(max)'), 1, 10, '')
EXEC(#Sql)
SELECT * FROM #Results
UPDATE
Ok this should do what you want:
DECLARE #ColumnName sysname = 'CMDFLAG', #Sql NVARCHAR(MAX)
IF OBJECT_ID(N'TempDB.dbo.#Results', N'U') IS NULL
CREATE TABLE #Results(TableName SYSNAME, ColumnName sysname, Value NVARCHAR(25))
ELSE
TRUNCATE TABLE #Results
SELECT
#Sql = 'INSERT INTO #Results '
+ STUFF((
SELECT
'UNION ALL SELECT DISTINCT Table_Name = '
+ QUOTENAME(C.TABLE_SCHEMA + '.' + C.TABLE_NAME, '''')
+ ', ' + QUOTENAME(C.COLUMN_NAME, '''')
+ ', ' + QUOTENAME(C.COLUMN_NAME)
+ ' FROM '
+ C.TABLE_SCHEMA + '.'
+ C.TABLE_NAME
+ ' WHERE ' + QUOTENAME(C.COLUMN_NAME) + ' IN(''C'', ''D'', ''M'') '
FROM
INFORMATION_SCHEMA.COLUMNS C
CROSS APPLY
(
SELECT
T.TABLE_SCHEMA, T.TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES T
WHERE
T.TABLE_TYPE = 'BASE TABLE'
AND T.TABLE_SCHEMA = C.TABLE_SCHEMA
AND T.TABLE_NAME = C.TABLE_NAME
) T
WHERE
C.COLUMN_NAME = #ColumnName
FOR XML PATH(''), type).value('.', 'nvarchar(max)'), 1, 10, '')
EXEC(#Sql)
SELECT * FROM #Results

Max(ID) of each table on a database

I am trying to get the maximum value MAX(ID) for each table I have which contains ID on my DB "Table_Example" and one schema_name in specific.
A single example:
SELECT MAX(ID) FROM Schema_name.Table_name1
This retrieve the maximum ID value that is located on Table_name1, but I have 84 tables. I would like to know the max of each table only in one column.
This is the code where I am working on currently:
I am using information_schema.columns to get the names of the tables automatic and the schema each table belongs to in order to get the whole DB IDs max(id) in one column.
USE TABLE_EXAMPLE
GO
DECLARE #ID NVARCHAR(MAX) --int
SET #ID = (SELECT DISTINCT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'SCHEMA_NAME' AND COLUMN_NAME IN ('ID') AND DATA_TYPE = 'INT')
SELECT #ID FROM (SELECT ('SCHEMA_NAME'+'.'+TABLE_NAME) AS TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'SCHEMA_NAME' AND COLUMN_NAME = 'ID' AND DATA_TYPE='INT') AS W
This Script retrieve wrong data but I think I am a bit closed to get the values, but I am not sure what I am doing wrong.
Could someone give me any good approach? Or any better option to get it done?
If you are wanting the max value in your identity columns, regardless of the names of those columns, then this is a very simple way of doing it. This will give you the Table Name, the name of the Identity Column, and the max value of that column:
SELECT sys.tables.name AS [Table Name],
sys.identity_columns.name AS [Column Name],
last_value AS [Last Value]
FROM sys.identity_columns
INNER JOIN sys.tables
ON sys.identity_columns.object_id = sys.tables.object_id
ORDER BY last_value DESC
This enumerate all tables with column Id and MAX value of this ID:
DECLARE #query nvarchar(MAX);
SELECT #query = COALESCE(#query + char(10)+'UNION ALL '+char(10)+'SELECT '''+QUOTENAME(s.name)+'.'+QUOTENAME(T.name)+''' [Table], MAX(Id) [Max] FROM '+QUOTENAME(s.name)+'.'+QUOTENAME(T.name),
'SELECT '''+QUOTENAME(s.name)+'.'+QUOTENAME(T.name)+''' [Table], MAX(Id) [Max] FROM '+QUOTENAME(s.name)+'.'+QUOTENAME(T.name))
FROM sys.schemas S
JOIN sys.tables T ON S.schema_id=T.schema_id
JOIN sys.columns C ON T.object_id=C.object_id
WHERE C.name='Id';
EXEC(#query);
Try like this,
This would give you the script.
SELECT DISTINCT 'SELECT MAX(' + + COLUMN_NAME + ') as ' + table_name + 'MaxId FROM ' + table_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dbo'
AND COLUMN_NAME IN ('ID')
CREATE TABLE #MaxValues (SchemaName SYSNAME , TableName SYSNAME , MaxID INT)
GO
Declare #SchemaName SYSNAME = 'dbo' --<-- Pass you schema name to this variable
,#ColumnName SYSNAME = 'ID' --<-- Column Name
,#DataType SYSNAME = 'INT' --<-- Data type
DECLARE #TableName SYSNAME , #SchmaName SYSNAME
, #Sql NVARCHAR(MAX) , #ColName SYSNAME;
Declare Cur CURSOR LOCAL FAST_FORWARD FOR
SELECT s.name , t.name , c.name
FROM sys.columns c
Inner join sys.tables t on c.object_id = t.object_id
Inner join sys.schemas s on s.schema_id = t.schema_id
Inner join sys.types tp on tp.user_type_id = c.user_type_id
WHERE s.name = #SchemaName
AND c.name = #ColumnName
AND tp.name = #DataType
OPEN Cur
FETCH NEXT FROM Cur INTO #SchmaName , #TableName , #ColName
WHILE (##FETCH_STATUS =0)
BEGIN
SET #Sql = N'INSERT INTO #MaxValues (SchemaName, TableName, MaxID )'
+ N' SELECT #SchmaName ,#TableName, MAX(' + QUOTENAME(#ColName) + N') '
+ N' FROM ' + QUOTENAME(#SchmaName) + '.' + QUOTENAME(#TableName)
Exec sp_executesql #Sql
,N'#SchmaName SYSNAME , #TableName SYSNAME'
,#SchmaName
,#TableName
FETCH NEXT FROM Cur INTO #SchmaName , #TableName , #ColName
END
CLOSE Cur
DEALLOCATE Cur
SELECT * FROM #MaxValues
Perhaps a little dynamic SQL
Edit This will return the Table Name(s) and Max ID in one dataset
Declare #SQL varchar(max) = '>>>'
Select #SQL = #SQL + SQL
From (
Select SQL='Union All Select TableName='''+concat('[',Table_Schema,'].[',Table_Name,']')+''',MaxID=max(ID) From '+concat('[',Table_Schema,'].[',Table_Name,'] ')
From INFORMATION_SCHEMA.COLUMNS
Where Column_Name = 'ID'
) A
Set #SQL=Replace(#SQL,'>>>Union All ','')
Exec(#SQL)
This script will list all the max ids. It is assuming your first column is the ID, regardless of its name.
DECLARE #Script AS VARCHAR(MAX) = ''
SELECT #Script = #Script + 'SELECT MAX(' + COLUMN_NAME + ') AS ID FROM ' + c.TABLE_NAME + ' UNION ALL ' + CHAR(13)+CHAR(10)
FROM INFORMATION_SCHEMA.COLUMNS c
INNER JOIN INFORMATION_SCHEMA.TABLES t ON c.TABLE_NAME = t.TABLE_NAME
WHERE c.ORDINAL_POSITION = 1 and t.TABLE_TYPE = 'BASE TABLE' and c.TABLE_SCHEMA = 'dbo' and c.DATA_TYPE = 'int'
SELECT #Script = LEFT(#Script, LEN(#Script) - 12)
EXEC (#Script)

SQL server 2012 select row counts from a variable number of tables

I have the following query
select count(*) as row_count
, UN_PART
, 'ABC_PARAM_DETA' as TABLE_NAME
from ABC_PARAM_DETA
group by UN_PART
what I would like to do is extend this to use it from a select list rather than a single table as I have multiple tables with UN_PART eg
select count(*) as row_count
, UN_PART
, '#var_table' as TABLE_NAME
from (Select TABLE_NAME from INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME = 'UN_PART')
group by UN_PART
Anyone any ideas on how to achieve this
Try this
IF OBJECT_ID('tempdb..#Output') IS NOT NULL
DROP TABLE #Output
CREATE TABLE #Output
(ID INT IDENTITY(1, 1),
TableName NVARCHAR(MAX),
RowCnt INT)
INSERT INTO #Output (TableName)
Select C.TABLE_NAME from INFORMATION_SCHEMA.COLUMNS C
INNER JOIN INFORMATION_SCHEMA.TABLES T ON C.TABLE_NAME = T.TABLE_NAME
WHERE COLUMN_NAME = 'UN_PART' AND T.TABLE_TYPE = 'BASE TABLE'
DECLARE #Step AS INT = 1
WHILE #Step <= (SELECT COUNT(*) FROM #Output) BEGIN
DECLARE #TableName NVARCHAR(MAX)
DECLARE #SQL NVARCHAR(MAX)
SELECT #TableName = TableName FROM #Output WHERE ID = #Step
SET #SQL = 'UPDATE #Output SET RowCnt = (SELECT COUNT(*) FROM ' + #TableName + ') WHERE TableName = ''' + #TableName + ''''
EXEC sys.sp_executesql #SQL
SET #Step = #Step + 1
END
SELECT * FROM #Output
DROP TABLE #Output
Haven't tested but I think this should work
Exec sp_MSforeachtable
#command1 ='select ''?'', un_part, count(1) from ? group by un_part'
,#whereand = ' and object_id in (select o.object_id from sys.objects o
inner join sys.columns c
on o.object_id = c.object_id
and c.name = ''UN_PART'')'