TSQL to know database role members - sql-server

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

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.

Query number of records across all databases

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

how to delete only Windows Login in SQL Server

I am using below code to delete SQL Logins
declare #name varchar(1000)
declare #xtype varchar(20)
declare #sqlstring nvarchar(4000)
declare SPViews_cursor cursor for
SELECT QUOTENAME(NAME) AS name
FROM sys.server_principals
open SPViews_cursor
fetch next from SPViews_cursor into #name
while ##fetch_status = 0
begin
set #sqlstring = 'drop LOGIN ' + #name
exec sp_executesql #sqlstring
set #sqlstring = ' '
fetch next from SPViews_cursor into #name
end
close SPViews_cursor
deallocate SPViews_cursor
but it is dropping all logins, I just need to drop Windows login so only SQL auth. can be possible. Any suggestion? And can this code be made shorter?
Change your query to this:
SELECT QUOTENAME(NAME) AS name
FROM sys.server_principals
WHERE type = 'U'
U means Window Login. You can find more info here.
USE type_desc or type column to filter 'Windows Login'
SELECT QUOTENAME(NAME) AS name
FROM sys.server_principals
where type_desc = 'WINDOWS_LOGIN'

Msg 5011, Level 14, State 5, Line 11 ALTER DATABASE statement failed

I ran the below scripts
DECLARE #name VARCHAR(50)
DECLARE #Statment VARCHAR(500)
DECLARE DB_cursor CURSOR
FOR
SELECT name
FROM sys.databases
WHERE name NOT IN ( 'master', 'tempdb', 'model', 'msdb',
'ReportServer$SQLEXPRESS',
'ReportServer$SQLEXPRESSTempDB' )
OPEN DB_cursor
FETCH NEXT FROM DB_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #name
ALTER DATABASE [#name] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
SET #Statment = 'Backup database ' + #name + ' To disk =N' + ''''
+ 'C:\Mas\' + #name + '.bak' + ''''
PRINT #Statment
EXEC(#Statment)
-- ALTER DATABASE [#name] SET MULTI_USER WITH ROLLBACK IMMEDIATE
-- EXEC sp_dboption #name, N'offline', N'false'
FETCH NEXT FROM DB_cursor INTO #name
END
CLOSE DB_cursor
DEALLOCATE DB_cursor
I got the error below
Msg 5011, Level 14, State 5, Line 11
User does not have permission to alter database '#name', the database does not exist, or the database is not in a state that allows access checks.
Msg 5069, Level 16, State 1, Line 11
ALTER DATABASE statement failed.
Please let me know where I am stuck on how to resolve this issue.
Note:- I ran this script in sa login.
Error message clearly states the reason. It's because Alter database command treats [#name] as a database and not a placeholder. You can include both the statements in dynamic query and then execute. Following should work:
DECLARE #name VARCHAR(50)
DECLARE #Statment VARCHAR(500)
DECLARE #Statment1 VARCHAR(500)
DECLARE #Statment2 VARCHAR(500)
select name from sys.databases where name NOT IN('master','tempdb','model','msdb','ReportServer$SQLEXPRESS','ReportServer$SQLEXPRESSTempDB')
OPEN DB_cursor
FETCH NEXT FROM DB_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
Print #name
SET #Statment = 'ALTER DATABASE ' + #name + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE; '
EXEC(#Statment)
SET #Statment1 = 'BACKUP DATABASE ' + #name + ' To disk =N' +''''+ 'C:\Mas\'+ #name +'.bak'+''''
EXEC(#Statment1)
SET #Statment2 = 'ALTER DATABASE ' + #name + ' SET MULTI_USER WITH ROLLBACK IMMEDIATE; '
EXEC(#Statment2)
EXEC(#Statment)
-- ALTER DATABASE [#name] SET MULTI_USER WITH ROLLBACK IMMEDIATE
-- EXEC sp_dboption #name, N'offline', N'false'
FETCH NEXT FROM DB_cursor INTO #name
END
CLOSE DB_cursor
DEALLOCATE DB_cursor
I change your T-SQL and this worked.
you most change destination of back up file in the anther path like this sample .
DECLARE #name VARCHAR(50)
DECLARE #Statment VARCHAR(500)
DECLARE DB_cursor CURSOR
FOR
SELECT name
FROM sys.databases
WHERE name NOT IN ( 'master', 'tempdb', 'model', 'msdb',
'ReportServer$SQLEXPRESS',
'ReportServer$SQLEXPRESSTempDB' )
OPEN DB_cursor
FETCH NEXT FROM DB_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #name
-- DECLARE #A NVARCHAR(800) = ' ALTER DATABASE [' + #name + '] SET Multi_USER WITH ROLLBACK IMMEDIATE '
DECLARE #A NVARCHAR(800) = ' ALTER DATABASE [' + #name + '] SET SINGLE_USER WITH ROLLBACK IMMEDIATE '
EXECUTE Sp_ExecuteSQL #A
SET #Statment = 'Backup database ' + #name + ' To disk =N' + ''''
+ 'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER2012\MSSQL\Backup\'
+ #name + '.bak' + ''''
PRINT #Statment
EXEC(#Statment)
-- ALTER DATABASE [#name] SET MULTI_USER WITH ROLLBACK IMMEDIATE
-- EXEC sp_dboption #name, N'offline', N'false'
FETCH NEXT FROM DB_cursor INTO #name
END
CLOSE DB_cursor
DEALLOCATE DB_cursor
Like down picture
you most grate access to SQL Server user in your path of Back up
The SQL command ALTER DATABASE does not allow a parameter hence it is treating #name as being the actual name and not as a parameter.
ALTER DATABASE
NAME
Specifies a logical name for the file.
logical_file_name
Is the name used in Microsoft SQL Server when referencing the file. The name must be unique within the database and conform to the rules for identifiers. The name can be a character or Unicode constant, a regular identifier, or a delimited identifier. For more information, see Using Identifiers.
You most use SP_ExecuteSQL for change state of Database
DECLARE #A NVARCHAR(800) = ' ALTER DATABASE [' +
#name +
'] SET SINGLE_USER WITH ROLLBACK IMMEDIATE '
EXECUTE Sp_ExecuteSQL #A
And then you can set database in single user mode.

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.

Resources