You need to do this with dynamic SQL. You will need to query all 1000 tables, and make sure you are converting the values correctly if the columsn are different types.
You don't need a temp table for this, you can just script one giant UNION ALL
query. You must make sure to quote all dynamic names correctly using QUOTENAME
.
To be able to return data for multiple items, you should create a Table Valued Parameter, which you can pass in using sp_executesql
.
First create a table type
CREATE TYPE dbo.IntList (Id int PRIMARY KEY);
Then you create a table variable containing them, and pass it in. You can also do this in a client application and pass in a TVP.
SET NOCOUNT ON;
DECLARE @Items dbo.IntList;
INSERT @Items (Id) VALUES(350),(465);
DECLARE @Sql nvarchar(max);
SELECT
@Sql = STRING_AGG(CONVERT(nvarchar(max), N'
SELECT
' + QUOTENAME(t.name, '''') + ' AS TableName,
t.ItemNumber,
COUNT(*) AS ItemCount
FROM ' + QUOTENAME(t.Name) + ' t
JOIN @items i ON i.Id = t.ItemNumber
GROUP BY
t.ItemNumber
HAVING COUNT(*) > 0
' ),
N'
UNION ALL
' )
FROM
sys.tables t
WHERE t.object_id IN (
SELECT c.object_id
FROM sys.columns c
WHERE
c.Name = 'ItemNumber'
);
PRINT @sql; -- your friend
EXEC sp_executesql
@sql,
N'@items dbo.IntList',
@items = @items READONLY;
If you don't need to know the count, and only want to know if a value exists, you can change the dynamic SQL to an EXISTS
....
SELECT
@Sql = STRING_AGG(CONVERT(nvarchar(max), N'
SELECT
' + QUOTENAME(t.name, '''') + ' AS TableName,
t.ItemNumber
FROM @items i
WHERE i.Id IN (
SELECT t.ItemNumber
FROM ' + QUOTENAME(t.Name) + ' t
)
' ),
N'
UNION ALL
' )
....