Query number of records across all databases - sql-server

I have multiple databases in my SQL Server. All databases are the same in structure but have different data. These databases are used to store sensor data so each sensor has it's own seperate DB in the SQL Server.
I want a query to Select the Database name and number of records in a specific table of each DB.
I tried with a cursor. I get error saying the name {query} is not a valid identifier. My Cursor is as follows:
Declare #dbname Varchar (50), #sql Varchar(1000)
Declare db_cursor CURSOR FOR
SELECT name
FROM master.dbo.sysdatabases
WHERE name LIKE 'EP505-%' -- All sensors of EP505
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql= 'SELECT Count(*) FROM [' + #dbname + '].dbo.TimeLine'
EXEC #sql
FETCH NEXT FROM db_cursor INTO #dbname
END
CLOSE db_cursor
DEALLOCATE db_cursor
In the output I require the db name and the number of records for the TimeLine table.
What's the best way to achieve what I am trying.

Use parentheses when executing a SQL query string like so:
EXEC (#sql). Without parentheses, SQL Server will interpret #sql as a stored procedure or user-defined function.

your attempt looks quite good so far.
Please try adding a fetch next below the exec-line and try putting the #SQL variable after the exec brackets. That worked in my SQL Server environment.
hope this helps
br
Patrik

You can use sp_executeSQL to execute your dynamic query instead of exec statement which will help you to solve your issue
Here is the modified version
Declare #dbname Varchar (50), #sql nVarchar(1000)
Declare db_cursor CURSOR FOR
SELECT name
FROM master.dbo.sysdatabases
WHERE name LIKE 'kodyaz' -- All sensors of EP505
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql= N'SELECT Count(*) FROM [' + #dbname + '].dbo.Kontaktpersonen'
exec sp_executesql #sql
FETCH NEXT FROM db_cursor INTO #dbname
END
CLOSE db_cursor
DEALLOCATE db_cursor
I change #sql data type to nvarchar() and use
exec sp_executesql #sql

Related

Can i use sp_msforeachDB for registration procedure in all databese

I must resister the same stored procedure in many - over 200 - databases.
I tried this:
-------------------------------------------------------------
DECLARE DB_CURSOR CURSOR FOR
SELECT name
FROM sys.databases
OPEN DB_CURSOR
FETCH NEXT FROM DB_CURSOR INTO #DB_NAME
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql1 = '---' ←Create Procedure
SET #sql0 = 'USE [' + #DB_NAME + ']; EXEC(''' + #sql1 + ''')'
EXEC(#sql0)
END
-------------------------------------------------------------
I checked escape sequence and my query are normal. However, this code valid in only first database.
And it can repeat while number of database, but run at first database.
Is it why?
I searched many website, haven't prove yet.
Please help me.
If possible I want to solve it by a method that does not use sysobject.
Thanks for your advice.

How to declare a variable that lists all the existing databases on my server with the Microsoft SQL Server Management Studio

I need to create a variable that lists all the existing databases in my system, because I need it and I don't know how to do it. I have tried to create variables like this one:
DECLARE #nombreBD INT;
SET #nombreBD = (SELECT [database_id] FROM sys.databases Where name = 'model' )
SELECT #nombreBD AS Database_ID
PRINT #nombreBD
GO
This variable gets me only the name I put in the "WHERE" parameter but I need to get them all.
The table sys.databases shows you all the existing databases in the system and I need to get a boolean value from it, I thought to get it from the column "database_id" that's why I declared this variable.
This creates a table name #DBList with a column nombreBD
and inserts the database_id to the column,
then it shows all your sql-server database database_id
BEGIN
DECLARE #DBList TABLE (nombreBD INT)
INSERT INTO #DBList(nombreBD) SELECT database_id FROM sys.databases
SELECT * FROM #DBList
END
Is that what you need ?
To achieve what you want, you will need to use some dynamic SQL. Something like this ought to work for your case:
DECLARE #DBList TABLE (nombre varchar(50));
INSERT INTO #DBList(nombre) SELECT name FROM sys.databases
WHERE name NOT IN ('master','tempdb','msdb');
declare #name nvarchar(50);
declare #sql nvarchar(2000);
DECLARE db_Cursor CURSOR FOR
SELECT nombre FROM #DBList;
OPEN db_Cursor;
FETCH NEXT FROM db_Cursor INTO #name;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = N'USE ' + #name + N';'
exec sp_executesql #sql;
SET #sql = N'SELECT DB_NAME() AS DatabaseName, ''guest'' AS Database_User, [permission_name], [state_desc]
FROM sys.database_permissions WHERE [grantee_principal_id] = DATABASE_PRINCIPAL_ID(''guest'') AND [state_desc] LIKE ''GRANT%'' AND [permission_name] = ''CONNECT'';';
exec sp_executesql #sql;
FETCH NEXT FROM db_Cursor INTO #name;
END;
CLOSE db_Cursor;
DEALLOCATE db_Cursor;
Notice that I have changed the table variable to hold the database names, not their ids. This is because the USE statement takes the name not the id.
The cursor loops through the values, builds the various sql statements and executes them.

Not displaying select results from dynamic SQL within Cursor

I'm currently learning SQL and trying to think of exercises for myself and I can't seem to make this one work even though it seems simple:
I'm trying to run a cursor through all the filtered tables within my db so that then I could pass that table name to a variable which will be used within a DynamicSQL inside the cursor. The end result should be all values from every column that has the column 'empid' in them.
However, the message returns as "Commands completed successfully" but I get to see no results despite my select statement.
I'm trying to run something like this:
declare #tablename nvarchar(200);
declare #empid int;
declare #sql nvarchar(200) = N'select * from ' + #tablename + N' where empid = ' +#empid;
declare tablecursor cursor for select table_name from information_schema.tables where col_length(table_name, 'empid') is not null;
open tablecursor;
fetch next from tablecursor into #tablename;
while ##fetch_status = 0
begin
execute sp_executesql #sql, 825
fetch next from tablecursor into #tablename;
end
close tablecursor;
deallocate tablecursor;
I've been searching everywhere for answers to make this work but can't find anything. I've tried putting into a stored procedure and then executing it from there but that didn't work either.
Help would be highly appreciated.
DECLARE #SQL Should be outside but assigning the Variable inside the while loop
SET #SQL = N'SELECT * FROM ' + #tableName
Should be in while loop.
The other thing is to increase the length of #SQL Variable.
Thank you kindly for the help. After I listened to your advice I've encountered more errors but at least for these I was able to find answers online. What I also learnt is that you can't have your sql string in quotes when you execute it as that will make SSMS treat #SQL as an actual string and not a variable. I've managed to get it working and my code now looks something like this:
create proc cdr #empid nvarchar(5) as
declare #tablename nvarchar(200);
declare tablecursor cursor for select table_name from information_schema.tables where col_length(table_name, 'empid') is not null;
open tablecursor;
fetch next from tablecursor into #tablename;
declare #sql nvarchar(max)
while ##fetch_status = 0
begin
set #sql = N'select * from ' + #tablename + N' where empid = ' + #empid;
execute sp_executesql #sql
fetch next from tablecursor into #tablename;
end
close tablecursor;
deallocate tablecursor;

Saving image in database field to file on server

I am trying to save data from a table directly to the servers file system using this t-sql:
DECLARE #ID int
DECLARE #command varchar(1000)
DECLARE #Name varchar(100)
DECLARE #FileName varchar(100)
DECLARE MyCursor CURSOR FOR
SELECT Id, [FileName] FROM FilesTable
OPEN MyCursor
FETCH NEXT FROM MyCursor
INTO #ID, #Name
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #FileName = 'd:\Temp\' + convert(varchar(200), #Name)
SET #command = 'bcp "SELECT FileBytes FROM FilesTable WHERE ID = ' + convert(varchar(18), #Id) + '" queryout "' + #FileName + '" -T -n'
EXEC master..xp_cmdshell #command, no_output
FETCH NEXT FROM MyCursor
INTO #Id, #Name
END
CLOSE MyCursor
DEALLOCATE MyCursor
The table is filled with solid data. accessing this data with a C# program works.
I did configure advanced options gave permission to use xp_cmdshell
When I run this query i don't get any error but no file was written.
I also don't see anything in the logs, (maybe I am looking in the wrong location?)
What am I doing wrong? Or what can I do to checdk 'under the hood'?
Based on the comment from Patrick and the answer in fastest way to export blobs from table into individual files I was able to store the images on my fileserver.
we ended up writing a CLR function something like the one given.

TSQL to know database role members

I am using SQL 2000 and SQL 2005.
I want to know which logins have db_owner or db_accessadmin rights to which databases.
I can click on users or database roles in every database to see that.
Could this be done in an easier way using TSQL?
Thanks in advance
For SQL 2000 and still works for SQL 2005 too
SELECT
USER_NAME(memberuid), USER_NAME(groupuid)
FROM
sys.sysmembers
WHERE
USER_NAME(groupuid) IN ('db_owner', 'db_accessadmin')
It's sloppy and there is probably a better way, but this should get it done if this is a one-time thing:
DECLARE
#db_name SYSNAME,
#sql VARCHAR(1000)
DECLARE db_cursor CURSOR FOR SELECT Name FROM sys.databases
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #db_name
WHILE (##FETCH_STATUS = 0)
BEGIN
SET #sql =
'SELECT
''' + #db_name + ''' AS [Database],
USER_NAME(role_principal_id) AS [Role],
USER_NAME(member_principal_id) AS [User]
FROM
' + #db_name + '.sys.database_role_members
WHERE
USER_NAME(role_principal_id) IN (''db_owner'', ''db_accessadmin'')'
EXEC(#sql)
FETCH NEXT FROM db_cursor INTO #db_name
END
CLOSE db_cursor
DEALLOCATE db_cursor
The SQL 2000 version should be:
DECLARE
#db_name SYSNAME,
#sql VARCHAR(1000)
DECLARE db_cursor CURSOR FOR SELECT Name FROM master..sysdatabases
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #db_name
WHILE (##FETCH_STATUS = 0)
BEGIN
SET #sql =
'SELECT
''' + #db_name + ''' AS [Database],
USER_NAME(memberuid) AS [Role],
USER_NAME(groupuid) AS [User]
FROM
sysmembers
WHERE
USER_NAME(groupuid) IN (''db_owner'', ''db_accessadmin'')'
EXEC(#sql)
FETCH NEXT FROM db_cursor INTO #db_name
END
CLOSE db_cursor
DEALLOCATE db_cursor

Resources