I'm trying to count the rows of all tables called tblDoc from every database in my SQL Server instance.
I tried this but apparently you can't access or declare variables in cursors:
DECLARE #dbname nvarchar(1000);
DECLARE #sqlCommand NVARCHAR(1000)
DECLARE #results TABLE(numberOfDocuments bigint);
DECLARE c1 CURSOR READ_ONLY
FOR
SELECT '[' + name + ']' FROM sys.databases WHERE name <> 'tempdb'
OPEN c1
FETCH NEXT FROM c1
INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sqlCommand = 'INSERT INTO results SELECT COUNT(ID) FROM ' + #dbname + '.dbo.tblDoc;';
print #sqlCommand;
EXECUTE sp_executesql #sqlCommand
FETCH NEXT FROM c1
INTO #dbname
END
CLOSE c1
DEALLOCATE c1
SELECT COUNT(numberOfDocuments) from #results;
Use Temp table instead
DECLARE #dbname nvarchar(1000);
DECLARE #sqlCommand NVARCHAR(1000)
CREATE TABLE #results (numberOfDocuments bigint);
DECLARE c1 CURSOR READ_ONLY
FOR
SELECT '[' + name + ']' FROM sys.databases WHERE name <> 'tempdb'
OPEN c1
FETCH NEXT FROM c1
INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sqlCommand = 'INSERT INTO #results SELECT COUNT(ID) FROM ' + #dbname + '.dbo.tblDoc;';
print #sqlCommand;
EXECUTE sp_executesql #sqlCommand
FETCH NEXT FROM c1
INTO #dbname
END
CLOSE c1
DEALLOCATE c1
SELECT COUNT(numberOfDocuments) from #results;
Raj
If you are looking for All table counts from All DB's in a given server then below solution is very simplified.
DECLARE #dbname nvarchar(1000);
DECLARE #sqlCommand NVARCHAR(1000)
drop table if exists ##temp
create table ##temp (dbname varchar(500),schemaname varchar(500),tablename varchar(500),counts int)
DECLARE c1 CURSOR READ_ONLY
FOR
SELECT name FROM master.sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb');
OPEN c1
FETCH NEXT FROM c1
INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sqlCommand = 'INSERT INTO ##temp'+'
SELECT
'''+#dbname+''' as databasename,
s.name AS schemaname,
t.name AS tablename,
p.rows AS rowcounts
FROM '+#dbname+'.sys.tables t
INNER JOIN '+#dbname+'.sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN '+#dbname+'.sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN '+#dbname+'.sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN '+#dbname+'.sys.schemas s ON t.schema_id = s.schema_id
WHERE t.NAME NOT LIKE ''dt%''
AND t.is_ms_shipped = 0
AND i.OBJECT_ID > 255
GROUP BY
t.name, s.name, p.Rows
'
;
print #sqlCommand;
EXECUTE sp_executesql #sqlCommand
FETCH NEXT FROM c1
INTO #dbname
END
CLOSE c1
DEALLOCATE c1
select * from ##temp
Related
hi I am trying to search all the columns and tables in a data server that contain a specific date value e.g. '2021-07-22' in SQL server database.
Please notice is NOT a string type, but a datetime type.
I googled and did quite a bit research but could not find anything available. Can anyone provide some help please?
Thanks
DECLARE #SearchDate DATE = '2022-01-01'
DECLARE #SQL NVARCHAR(MAX) = ''
DECLARE #SchemaName SYSNAME
DECLARE #TableName SYSNAME
DECLARE #ColumnName SYSNAME
DECLARE #RowIDName SYSNAME
DECLARE #Results TABLE(ColumnName SYSNAME,RowIDName SYSNAME,RowIDValue NVARCHAR(255), ColumnValue DATETIME)
DECLARE #TableCols CURSOR
SET #TableCols = CURSOR FOR
SELECT QUOTENAME(s.name) AS SchemaName,QUOTENAME(t.name) AS TableName,QUOTENAME(c.name) AS ColumnName,QUOTENAME(Ids.ID) AS RowIDName
FROM sys.tables t
JOIN sys.columns c ON t.object_id = c.object_id
JOIN sys.schemas s ON s.schema_id = t.schema_id
CROSS APPLY (SELECT TYPE_NAME(c.system_type_id))TypeNames(TypeName)
CROSS APPLY (SELECT c2.Name FROM sys.Columns c2 WHERE c2.column_id = 1 AND c2.object_id = c.object_id)IDs(ID)
WHERE t.is_ms_shipped = 0
AND TypeNames.TypeName IN ('date','datetime','datetime2','smalldatetime')
OPEN #TableCols
FETCH NEXT FROM #TableCols INTO #SchemaName,#TableName, #ColumnName,#RowIDName
WHILE ##fetch_status = 0
BEGIN
INSERT INTO #Results(ColumnName,RowIDName,RowIDValue,ColumnValue)
EXEC
(
'SELECT ''' + #SchemaName+'.'+#TableName + '.' + #ColumnName + ''','''+#RowIDName+''','+#RowIDName+' ,' + #ColumnName + '
FROM ' + #TableName +
' WHERE ' + #ColumnName + ' = ''' + #SearchDate+''''
)
FETCH NEXT FROM #TableCols INTO #SchemaName,#TableName, #ColumnName,#RowIDName
END
CLOSE #TableCols
DEALLOCATE #TableCols
SELECT * FROM #Results
Is there a way to select columns of a table then assign the top 1 value of that column.
For example
TABLENAME | COLUMNNAME | VALUE
----------+------------+---------------
TABLE 1 | COLUMN 1 | COLUMN 1 VALUE
TABLE 1 | COLUMN 2 | COLUMN 2 VALUE
UPDATE
DECLARE #tableCOLS TABLE (tablename varchar(255) , colname varchar(255));
BEGIN
SET #MyCursor = CURSOR FOR
SELECT DISTINCT tablename FROM #tableid
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #MyField2
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #tableCOLS
SELECT #MyField2 , COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #MyField2
FETCH NEXT FROM #MyCursor
INTO #MyField2
END;
CLOSE #MyCursor ;
DEALLOCATE #MyCursor;
END;
SELECT * from #tableCOLS
END;
I fetch the table columns to my dynamic table then i want to insert the value of a certain data in the columns that i fetch in my table
I just tested this and it works a treat
DECLARE #Result TABLE (TableName VARCHAR(50), Col VARCHAR(50), MaxValue VARCHAR(50), MaxSQL NVARCHAR(4000));
DECLARE #TableName VARCHAR(50), #Col VARCHAR(50), #MaxSQL NVARCHAR(4000), #MaxValue VARCHAR(50)
-- Load all tables and columns of interest
INSERT INTO #Result
(TableName, Col, MaxSQL)
select
object_name(object_id),
name,
'SELECT #C = MAX(' + name + ') FROM ' + object_name(object_id)
from sys.columns where object_name(object_id) = 'Table1'
-- For each row, run the dynamic SQL and update back into table
DECLARE c CURSOR FOR
SELECT TableName, Col, MaxSQL FROM #Result
OPEN c
FETCH NEXT FROM C INTO #TableName, #Col, #MaxSQL
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC sp_ExecuteSQL #MaxSQL, N'#C VARCHAR(50) OUTPUT', #C = #MaxValue OUTPUT
UPDATE #Result SET MaxValue = #MaxValue WHERE TableName = #TableName AND Col = #Col;
FETCH NEXT FROM C INTO #TableName, #Col, #MaxSQL
END
CLOSE c;
DEALLOCATE c;
-- Show the results
SELECT * FROM #Result;
There's no need to use loops or cursors to do this. Have a look at the following...
SET NOCOUNT ON;
DECLARE #Object_id INT = OBJECT_ID('DataBaseName.Schema.TableName');
IF OBJECT_ID('tempdb..#TableCols', 'U') IS NOT NULL
DROP TABLE #TableCols;
CREATE TABLE #TableCols (
SchemaName sysname,
TableName sysname,
ColumnName sysname,
ColumnID INT NOT NULL,
Value NVARCHAR(MAX) NULL
);
INSERT #TableCols (SchemaName, TableName, ColumnName, ColumnID)
SELECT
s.name,
o.name,
c.name,
c.column_id
FROM
sys.objects o
JOIN sys.schemas s
ON o.schema_id = s.schema_id
JOIN sys.columns c
ON o.object_id = c.object_id
WHERE
o.type = 'U'
AND o.object_id = #Object_id
ORDER BY
c.column_id;
DECLARE
#CrossCols VARCHAR(MAX) = N'',
#TopVal NVARCHAR(10) = N'',
#Table sysname = N'',
#sql NVARCHAR(MAX) = N'',
#DeBug BIT = 0; -- 1 = PRINT ; 0 = EXECUTE
SELECT
#CrossCols = CONCAT(#CrossCols, N',
(', tc.ColumnID, N', CAST(t.[', tc.ColumnName, N'] AS NVARCHAR(MAX)))'),
#TopVal = tc.ColumnID,
#Table = CONCAT(tc.SchemaName, '.', tc.TableName)
FROM
#TableCols tc
ORDER BY
tc.ColumnID;
SET #sql = CONCAT(N'
UPDATE tc SET
tc.Value = t.ColumnValue
FROM
#TableCols tc
JOIN (
SELECT TOP (', #TopVal, N')
x.*
FROM
', #Table, N' t
CROSS APPLY ( VALUES', STUFF(#CrossCols, 1, 1, ''), N'
) x (ColumnID, ColumnValue)
) t
ON tc.ColumnID = t.ColumnID;')
IF #DeBug = 1
BEGIN
EXEC dbo.LongPrint #sql;
END;
ELSE
BEGIN
EXEC(#sql);
SELECT * FROM #TableCols tc;
END;
Give this a shot...
DECLARE #Table VARCHAR(MAX) = 'Customer'
SELECT t.name AS [Table]
, c.name AS [Column]
, cmd.mycmd
, TYPE_NAME(c.user_type_id) AS [Type]
, c.max_length AS [Size]
, CASE WHEN c.is_nullable = 1 THEN ''
ELSE 'No Nulls' END AS Nullable
, ROW_NUMBER() OVER ( PARTITION BY t.name ORDER BY c.name ASC ) AS rnk
, CASE WHEN EXISTS ( SELECT 1
FROM sys.columns c2
WHERE c2.object_id = t.object_id
AND c2.name IN ( SELECT *
FROM dbo.fnSplit('Fieldnames,ToSkip', ',') ) ) THEN 'Y'
ELSE 'N' END AS [CreModDeLs]
into #MyTempTable
FROM sys.columns AS c
JOIN sys.tables AS t ON c.object_id = t.object_id
cross apply (Select 'Select top 1 #Val = cast(' + c.name + ' as varchar(max)) from ' + t.name + ' Order by 1 desc' as mycmd) cmd
WHERE t.name LIKE #Table
ORDER BY t.name
, c.name
alter table #MyTempTable add [Id] integer identity(1,1)
alter table #MyTempTable add [Top1Val] Varchar(max)
Declare #DynamicSQL as nvarchar(1000);
Declare #dynamicparamdec nvarchar(1000) = '#val Varchar(max) Output'
Declare #valueofid as int
Declare #returnval as varchar(max)
Declare #Id integer
DECLARE #MyCursor CURSOR FAST_FORWARD
FOR
SELECT id
, mycmd
FROM #MyTempTable
where type <> 'image'
OPEN #MyCursor
FETCH #MyCursor INTO #id, #DynamicSQL
WHILE ##fetch_status = 0
BEGIN
print #dynamicsql
execute sp_executesql #DynamicSQL
, #dynamicparamdec
, #returnval output
update #MyTempTable
set Top1Val = #returnval
where id = #id
FETCH #MyCursor INTO #id, #DynamicSQL
END
--Close the cursor, if it is empty then deallocate it:
IF ( SELECT CURSOR_STATUS('global', '#MyCursor') ) >= -1
BEGIN
IF ( SELECT CURSOR_STATUS('global', '#MyCursor') ) > -1
BEGIN
CLOSE #MyCursor
END
DEALLOCATE #MyCursor
END
select * from #MyTempTable
Here is my script grab from net
declare #col varchar(255), #cmd varchar(max)
DECLARE getinfo cursor for
SELECT c.name
FROM sys.tables t JOIN sys.columns c
ON t.Object_ID = c.Object_ID
WHERE t.Name = 'tblDeductions'
AND c.name like 'fld%name' OPEN getinfo
FETCH NEXT FROM getinfo into #col
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #cmd = 'IF EXISTS (SELECT top 1 * FROM tblDeductions WHERE ['
+ #col + '] IS NOT NULL) BEGIN print ''
' + #col + ''' end' exec (#cmd)
FETCH NEXT FROM getinfo into #col
END CLOSE getinfo
DEALLOCATE getinfo
The above query will display column names that are null values. But I need to save them into another variable with comma separated values.
Thanks in advance.
This should work, although there's almost certainly a more efficient way to do what you're trying to do.
IF OBJECT_ID('tempdb..#t') IS NOT NULL
DROP TABLE #t
CREATE TABLE #t
(columnName VARCHAR(255))
DECLARE #col VARCHAR(255), #cmd VARCHAR(MAX)
DECLARE getinfo CURSOR FOR
SELECT c.name
FROM sys.tables t JOIN sys.columns c
ON t.Object_ID = c.Object_ID
WHERE t.Name = 'tblDeductions'
AND c.name LIKE 'fld%name' OPEN getinfo
FETCH NEXT FROM getinfo INTO #col
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #cmd = 'IF EXISTS (SELECT top 1 * FROM tblDeductions WHERE ['
+ #col + '] IS NOT NULL) BEGIN INSERT #t VALUES (''' + #col + ''') end'
EXEC (#cmd)
FETCH NEXT FROM getinfo INTO #col
END CLOSE getinfo
DEALLOCATE getinfo
DECLARE #columnsWithNull VARCHAR(MAX)
SET #columnsWithNull = (SELECT columnName + ','
FROM #t FOR XML PATH(''))
SET #columnsWithNull = LEFT(#columnsWithNull,LEN(#columnsWithNull) - 1)
SELECT #columnsWithNull
I'm running the following query to list size and fragmentation of the indexes:
SELECT object_name(object_id, database_id) as objectname), index_id, *
FROM sys.dm_db_index_usage_stats
Is there an SQL function I can use to convert the index_id to the index name?
I found a function on this page that should help you out:
CREATE FUNCTION dbo.index_name (#object_id int, #index_id int)
RETURNS sysname
AS
BEGIN
RETURN(SELECT name FROM sys.indexes WHERE object_id = #object_id and index_id = #index_id)
END;
Or better yet:
SELECT OBJECT_NAME(d.object_id, d.database_id) AS objectname ,
d.index_id ,
i.name ,
*
FROM sys.dm_db_index_usage_stats AS d
LEFT OUTER JOIN sys.indexes AS i ON i.object_id = d.object_id
AND i.index_id = d.index_id
I have come with this solution, works great:
create table dbo.IndexNames
(database_id int not null, object_id int not null, index_id int not null, index_name sysname not null)
go
create procedure dbo.GatherIndexNames
as
begin
declare #cur cursor
,#name varchar(128)
,#sql varchar(max)
truncate table dbo.IndexNames
set #cur = cursor for select name from sys.databases
where database_id >= 5
open #cur
fetch next from #cur into #name
while ##fetch_status = 0
begin
set #sql = '
insert into dbo.IndexNames
(database_id, object_id, index_id, index_name)
select db_id(''' + #name + '''),t.object_id, i.index_id, i.name
from [' + #name + '].[sys].[tables] t
inner join [' + #name + '].[sys].[indexes] i
on t.OBJECT_ID = i.object_id
where i.index_id <> 0'
exec (#sql)
fetch next from #cur into #name
end
SNAHi
anyone please suggest a query in sql to find the unused tables.
I have a legacy application migrated to .net from coldfusion.But lots of tables are unused now
What is the best way to find all the unused objects from database. (sql 2005)
thanks
SNA
In SQL Server, the acutal table data IS the clustered index. Using this query on the Dynamic Management Views (DMV) in SQL Server 2005 and up, you can find unused indices - if you find any clustered index (index_id=1) being unused over an extended period of time, the table is not being used anymore:
DECLARE #dbid INT
SELECT #dbid = DB_ID(DB_NAME())
SELECT
OBJECTNAME = OBJECT_NAME(I.OBJECT_ID),
INDEXNAME = I.NAME,
I.INDEX_ID
FROM
SYS.INDEXES I
JOIN
SYS.OBJECTS O ON I.OBJECT_ID = O.OBJECT_ID
WHERE
OBJECTPROPERTY(O.OBJECT_ID, 'IsUserTable') = 1
AND I.INDEX_ID NOT IN
(SELECT S.INDEX_ID
FROM SYS.DM_DB_INDEX_USAGE_STATS S
WHERE S.OBJECT_ID = I.OBJECT_ID
AND I.INDEX_ID = S.INDEX_ID
AND DATABASE_ID = #dbid)
ORDER BY
OBJECTNAME,
I.INDEX_ID,
INDEXNAME ASC
Another option would be to temporarily rename a table if you suspect it's not being used, and then see if your app(s) still work as expected. If they do for e.g. 30 days or so, then you're pretty sure you don't need that table anymore.
Marc
-- Query to find the tables not used by any stored procedure, function nor view
-- Using SQL 2005 system tables, all programatical objects for dependencies, and one&only query:
select tables.name, progr.name
from sys.objects tables (nolock)
left join sys.syscomments comm (nolock) on comm.text like '%' + tables.name +'%'
left join sys.objects progr (nolock) on progr.object_id = comm.id and progr.type in ('P', 'FN', 'TR', 'V' )
where tables.type = 'U'
and comm.id is null
Here is a query i have written to find the tables not used by any store procedures..
......................................................................................
Declare #tablename nvarchar(40)
Declare tablecursor cursor for
Select name from sysobjects where xtype = 'U'
DECLARE #sqlCommand nvarchar(1000)
declare #rowCount int
DECLARE #searchstring varchar(50)
DECLARE #ParmDefinition nvarchar(500);
create table #temp
(
UnusedTables nvarchar(40)
)
open tablecursor
fetch next from tablecursor into #tablename
while ##fetch_status = 0
begin
set #searchstring='p'
SET #sqlCommand = N'SELECT #rows = count(o.name) from sysobjects o ,
syscomments c where o.type='+char(39)+#searchstring + char(39)+' and
o.id=c.id and c.text like '+ char(39)+'%' + #tablename +'%'+char(39);
SET #ParmDefinition = N'#rows int OUTPUT';
EXECUTE sp_executesql #sqlCommand, #ParmDefinition,#rows=#rowCount OUTPUT;
if #rowCount = 0
begin
insert into #temp values (#tablename)
end
fetch next from tablecursor into #tablename
end
close tablecursor
deallocate tablecursor
select UnusedTables from #temp
drop table #temp
thanks
SA
Try something like below
DECLARE #TableNameTemp TABLE
(
id INT IDENTITY (1, 1),
tablename VARCHAR(1000)
)
INSERT INTO #TableNameTemp
SELECT table_name
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
ORDER BY table_name
DECLARE #CursorTestID INT = 1;
DECLARE #TotalCount INT = (SELECT Count(1)
FROM #TableNameTemp)
DECLARE #FinalResult TABLE
(
unsedtables VARCHAR(max)
)
DECLARE #TemExecInsert TABLE
(
testvalue VARCHAR(max),
type VARCHAR(max)
)
DECLARE #TableaName VARCHAR(max) = ''
WHILE #CursorTestID <= #TotalCount
BEGIN
DELETE FROM #TemExecInsert
SET #TableaName = (SELECT tablename
FROM #TableNameTemp
WHERE id = #CursorTestID)
INSERT INTO #TemExecInsert
EXEC Sp_depends
#objname = #TableaName
SET #CursorTestID = #CursorTestID + 1
IF ( (SELECT Count(1)
FROM #TemExecInsert) = 0 )
BEGIN
INSERT INTO #FinalResult
VALUES (#TableaName)
END
END
SELECT *
FROM #FinalResult
PS: Sorry, I am not certain how to bring the answer in shape. Hope this helps