Get data from all tables ending with a specific string - sql

I'm looking for a query that gets the nextval column from a lot of different tables ending with "_seq".
I know how to get the names of the tables...
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME LIKE '%seq'
But i couldn't find how to get the values from all those tables at once...
All those tables have the same column.

You can only achieve this with dynamic SQL. As you're using SQL Sevrer 2012, you'll need to use the "old" FOR XML PATH method to create the "delimited" UNION ALL query. I've also added the name of the schema and table into the query's dataset, as I assume this would be valuable information:
DECLARE #SQL nvarchar(MAX),
#CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SET #SQL = STUFF((SELECT N'UNION ALL' + #CRLF +
N'SELECT N' + QUOTENAME(s.[name],'''') + N' AS SchemaName,' + #CRLF +
N' N' + QUOTENAME(t.[name],'''') + N' AS TableName,' + #CRLF +
N' NextVal' + #CRLF +
N'FROM ' + QUOTENAME(s.[name]) + N'.' + 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 t.[name] LIKE '%[_]seq'
AND c.[name] = N'NextVal'
FOR XML PATH(''),TYPE).value('.','nvarchar(MAX)'),1,11,N'') + N';'
--PRINT #SQL; --Your best friend.
EXEC sys.sp_executesql #SQL;
As there's no data to test with, you'll need to use your "best friend" to debug if it doesn't work.

Related

Search for a value in all column and all tables of a database

I want to find the column name that contain the value "Commerciale", but i do not know the column name or the table so I need to search in the whole database. How can i do that with a query?
I'm using SQL SERVER
If you are looking for columns where the name is Commerciale then you can simply use the sys objects:
SELECT s.[name] AS SchemaName,
t.[name] AS TableName,
c.[name] AS ColumnName
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] = N'Commerciale';
If, however, you need to search the contents of the values in the rows, you'll need to use dynamic SQL. This will return a dataset for every table in your database which has at least 1 string type column, and will return any rows where the value of one of those columns has the value 'Commerciale'. If it needs to contain the value, change the WHERE to use a LIKE in it's clauses instead (note the query will be horrifically slow with that):
DECLARE #SQL nvarchar(MAX),
#CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SET #SQL = STUFF((SELECT #CRLF +
N'SELECT N' + QUOTENAME(s.[name],'''') + N' AS SchemaName,' + #CRLF +
N' N' + QUOTENAME(t.[name],'''') + N' AS TableName,' + #CRLF +
N' *' + #CRLF +
N'FROM ' + QUOTENAME(s.[name]) + N'.' + QUOTENAME(t.[name]) + #CRLF +
N'WHERE ' +
STUFF((SELECT #CRLF +
N' AND ' + QUOTENAME(c.[name]) + N' = ''Commerciale'''
FROM sys.columns c
JOIN sys.types ct ON c.system_type_id = ct.system_type_id
WHERE c.object_id = t.object_id
AND ct.[name] IN (N'char',N'varchar',N'nchar',N'nvarchar')
FOR XML PATH(''),TYPE).value('(./text())[1]','nvarchar(MAX)'),1,8,N'') + N';'
FROM sys.schemas s
JOIN sys.tables t ON s.schema_id = t.schema_id
FOR XML PATH(''),TYPE).value('(./text())[1]','nvarchar(MAX)'),1,2,N'');
--PRINT #SQL; --YOu best friend
EXEC sp_executesql #SQL;
This won't tell you what column has the value, you'll need to use your own eyes to do that, but I wasn't entertaining writing a dynamic table dynamic pivot.
you can use system tables :
SELECT
c.name ColumnName
, t.name TableName
FROM sys.columns AS c
JOIN sys.tables AS t
ON c.object_id = t.object_id
WHERE c.name like '%Commerciale%'

How to use sp_MSforeachdb

I have a code that returns all indexes with a fragmentation % greater than 30
Iwant this code to run through all my databases and add the resultset to a table I have called IndexesToRebuild
is there a way I can use the sp_MSforeachdb to run this query thoughout all databases and insert the resultset to the IndexesToRebuild table
here is the code I have so far
if(not exists(select 1 from Utility..dtlIndexesToRebuild))
begin
insert into utility..dtlIndexesToRebuild
select
DB_NAME(),
dbschemas.[name],
dbtables.[name],
dbindexes.[name],
indexstats.avg_fragmentation_in_percent
from
sys.dm_db_index_physical_stats (DB_ID(), null, null, null, null) as indexstats
inner join sys.tables dbtables on dbtables.[object_id] = indexstats.[object_id]
inner join sys.schemas dbschemas on dbtables.[schema_id] = dbschemas.[schema_id]
inner join sys.indexes as dbindexes on dbindexes.[object_id] = indexstats.[object_id]
and indexstats.index_id = dbindexes.index_id
where
indexstats.database_id = DB_ID()
and avg_fragmentation_in_percent > 30
end
sp_msforeachdb has some "features". For something as simple as this, it'll likely be easier to simply leverage some dynamic SQL:
USE master;
GO
DECLARE #SQL nvarchar(MAX),
#CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SET #SQL = STUFF((SELECT #CRLF + #CRLF +
N'USE ' + QUOTENAME([name]) + N';' + #CRLF +
N'INSERT INTO utility.dbo.dtlIndexesToRebuild (DatabaseName, SchemaName, TableName, IndexName, Fragmentation)' + #CRLF + --Guessed names of your columns
N'SELECT DB_NAME(),' + #CRLF +
N' dbschemas.[name],' + #CRLF +
N' dbtables.[name],' + #CRLF +
N' dbindexes.[name],' + #CRLF +
N' indexstats.avg_fragmentation_in_percent' + #CRLF +
N'FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) indexstats' + #CRLF +
N' INNER JOIN sys.tables dbtables ON dbtables.[object_id] = indexstats.[object_id]' + #CRLF +
N' INNER JOIN sys.schemas dbschemas ON dbtables.[schema_id] = dbschemas.[schema_id]' + #CRLF +
N' INNER JOIN sys.indexes dbindexes ON dbindexes.[object_id] = indexstats.[object_id]' + #CRLF +
N' AND indexstats.index_id = dbindexes.index_id' + #CRLF +
N'WHERE indexstats.database_id = DB_ID()' + #CRLF +
N' AND avg_fragmentation_in_percent > 30;'
FROM sys.databases d
WHERE d.database_id > 4
--AND d.[name] != N'utility' --Don't know if you want to skip this
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,4,N'');
--PRINT #SQL; --Your best friend. Use SELECT for over 4,000 characters.
EXEC sys.sp_executesql #SQL;
Your best friend will help you debug any errors, but I've assumed the statement you supplied is valid.

Loop through different tables for count

I have a table that has thousands of records. Usually 100k-200k records. There is a field in this table (MATCH_ID). I have to get count of this ID from 100 different tables whose field(TABLE_ID) value matches with MATCH_ID.
I think implementing this using cursors would be a bad idea here. How can I achieve this with better performance.
This makes a couple of a couple of assumptions, but you could create a dynamic UNION ALL query; which'll be far faster than a CURSOR:
DECLARE #MatchID int; --Guessed data type; will need a value
DECLARE #SQL nvarchar(MAX),
#CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SET #SQL = STUFF((SELECT #CRLF +
N'UNION ALL' + #CRLF +
N'SELECT N' + QUOTENAME(s.[name],'''') + N' AS SchemaName,' + #CRLF +
N' N' + QUOTENAME(t.[name],'''') + N' AS TableName,' + #CRLF +
N' COUNT(*) AS RowCount' + #CRLF +
N'FROM ' + QUOTENAME(s.[name]) + N'.' + QUOTENAME(t.[name]) + #CRLF +
N'WHERE MATCH_ID = #MatchID'
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] = N'MATCH_ID'
ORDER BY t.[name]
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,13,N'') + N';';
--SELECT #SQL; --Your best friend
EXEC sp_executesql #SQL, N'#MatchID int', #MatchID;
As I can't test this, use your "best friend" if you get any syntax errors, or you don't quite get the results you expect.

dropping multiple tables ending with "1617"

I need to drop multiple tables ending with the string "1617"
I have come across massive procedures to do this but is there an easy way
My tables look like mytable1617 and I have loads of them
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += '
DROP TABLE '
+ QUOTENAME(s.name)
+ '.' + QUOTENAME(t.name) + ';'
FROM sys.tables AS t
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
WHERE t.name LIKE '1617%';
PRINT #sql;
-- EXEC sp_executesql #sql;
This:
WHERE t.name LIKE '1617%';
is looking for tables starting with 1617. You wanted:
WHERE t.name LIKE '%1617';
Just change the search pattern
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += '
DROP TABLE '
+ QUOTENAME(s.name)
+ '.' + QUOTENAME(t.name) + ';'
FROM sys.tables AS t
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
WHERE t.name LIKE '%1617'; --tables ending with 1617
PRINT #sql;

Drop Several Tables at Once

I have some tables that I need to drop on a regular basis. The names of the tables sometimes change but the table names always begin with 'db_comp_temp'. Is it possible to write some SQL that will in effect do something like:
DROP TABLE db_comp_temp*
Thanks in advance,
No, there is no wildcard support in DDL.
DECLARE #sql nvarchar(max) = N'';
SELECT #sql += N'DROP TABLE ' + QUOTENAME(s.name)
+ '.' + QUOTENAME(t.name) + ';
' FROM sys.tables AS t
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
WHERE t.name LIKE N'db[_]comp[_]temp%';
PRINT #sql;
-- EXEC sys.sp_executesql #sql;
Or:
DECLARE #sql nvarchar(max) = N'';
SELECT #sql += N'
,' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name)
FROM sys.tables AS t
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
WHERE t.name LIKE N'db[_]comp[_]temp%';
SET #sql = N'DROP TABLE ' + STUFF(#sql, 1, 1, '');
PRINT #sql;
-- EXEC sys.sp_executesql #sql;
You could also do it with FOR XML PATH but I don't think it's necessary when you're not grouping the result into another outer query.