check user account ad_SSmith does not have dbo on multiple database (SQL server 2008 R2) - sql

I have about 100+ databases, and I want to check which database user ad_SSMith does not have dbo in. I ran EXEC sp_MSforeachdb to check which database he HAS dbo, but I would like to see which one he does not rather then doing a check off list and going back.
Is there away I can check all the databases to see in which ones the user does not have dbo?
Thank you so much.

How about something like this?
declare #sql varchar(281);
set #sql = 'use [?];
if exists (select 1 from sys.database_principals p
inner join sys.database_role_members r on p.principal_id = r.member_principal_id
where p.Name = ''domain\ad_SSMith''
and r.role_principal_id = 16384)
select DB_NAME(), ''db_owner''
else
select DB_NAME(), ''Not db_owner'''
exec sp_msforeachdb #sql;

Related

SQL Server iterative 'sp_droprolemember' execution

In SQL Server, I'm looking for a way to remove all role assignments for a specified database user. To put it another way, I'd like to drop the user from all roles in the database.
I've looked into the use of 'sp_droprolemember' to remove the user from a single specified role but what I'm looking for is a way to iterate through all database roles and drop the user from each.
Can this be done?
You can achieve this with a dynamic statement. Rather than using a loop, create the full dynamic statement, as that's more efficient. Also, don't use sp_droprolemember, as that's been deprecated for years and is due to be removed from SQL Sevrer; use ALTER ROLE.
As we don't know the version of SQL Server you're using, I'm using the "old" FOR XML PATH solution here, however, STRING_AGG would be a shorter and easier to understand query if you have a more recent version:
DECLARE #SQL nvarchar(MAX);
SET #SQL = STUFF((SELECT NCHAR(13) + NCHAR(10) +
N'ALTER ROLE ' + QUOTENAME(r.[name] ) + N' DROP MEMBER ' + QUOTENAME(u.[name]) + N';'
FROM sys.database_principals u
JOIN sys.database_role_members drm ON U.principal_id = drm.member_principal_id
JOIN sys.database_principals r ON drm.role_principal_id = r.principal_id
WHERE u.name = N'Your Login'
AND u.type IN ('U','S')
FOR XML PATH(N''),TYPE).value('(./text())[1]','nvarchar(MAX)'),1,2,N'')
PRINT #SQL; --Your best friend. Always check its value before running the dynamic statement.
--EXEC sys.sp_executesql #SQL; --Uncomment to run

Set IDENTITY_INSERT OFF for all tables

I have a script which creates an entire database and inserts all records to a few dozen tables.
It works great, unless there is some issue during the processing, and a table gets left with IDENTITY_INSERT ON, when the script fails during insertion and before it can be set to OFF again.
When this happens, the script automatically fails when attempting to run it again, with the error "IDENTITY_INSERT is already ON for table xx" as we go into the insertion for the first table.
As a failsafe I would like to make sure that IDENTITY_INSERT is set to OFF for all tables, before running the rest of the processing in the setup script.
As an alternative, we could perhaps close the MS SQL connection and open it again, which, as I understand it, would clear all IDENTITY_INSERT values for the connection session.
What's the best way to do this, and prevent the "already on" errors?
Dynamic SQL:
select 'set identity_insert ['+s.name+'].['+o.name+'] off'
from sys.objects o
inner join sys.schemas s on s.schema_id=o.schema_id
where o.[type]='U'
and exists(select 1 from sys.columns where object_id=o.object_id and is_identity=1)
Then copy & paste the resulting SQL into another query window and run
EXEC sp_MSforeachtable #command1="SET IDENTITY_INSERT ? OFF"
EXEC sp_MSforeachtable #command1="PRINT '?'; SET IDENTITY_INSERT ? OFF",
#whereand = ' AND EXISTS (SELECT 1 FROM sys.columns WHERE object_id = o.id AND is_identity = 1)'
Building on Lynn's answer, in case you're too lazy to perform this in more than one step - this should run on all tables where there is an identity column.
Caveat is only tested in 2012 and sp_MSforeachtable is of course entirely unsupported...
Building on #KevD's answer - It was working fine for disabling but here is more for enabling as well.
To disable all identity inserts where they need to be disabled, use -
EXEC sp_MSforeachtable #command1="PRINT '?'; SET IDENTITY_INSERT ? OFF",
#whereand = ' AND EXISTS (SELECT 1 FROM sys.columns WHERE object_id = o.id
AND is_identity = 1) and o.type = ''U'''
To enable all identity inserts where they need to be enabled, use -
EXEC sp_MSforeachtable #command1="PRINT '?'; SET IDENTITY_INSERT ? ON",
#whereand = ' AND EXISTS (SELECT 1 FROM sys.columns WHERE object_id = o.id
AND is_identity = 1) and o.type = ''U'''
Tested on Sql server 2014 and 2016
I had a similar issue but I'd rather not use undocumented stored procedures in production. To automate this I built on to #John Dewey's answer and put it into a cursor. This iterates over 699 tables in 407 ms.
DECLARE #sql NVARCHAR(500) -- SQL command to execute
DECLARE sql_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT 'SET identity_insert ['+s.name+'].['+o.name+'] OFF'
FROM sys.objects o
INNER JOIN sys.schemas s on s.schema_id=o.schema_id
WHERE o.[type]='U'
AND EXISTS(SELECT 1 FROM sys.columns WHERE object_id=o.object_id AND is_identity=1)
OPEN sql_cursor
FETCH NEXT FROM sql_cursor INTO #sql
WHILE ##FETCH_STATUS = 0
BEGIN
EXECUTE sp_executesql #sql --> Comment this out to test
-- PRINT #sql --> Uncomment to test or if logging is desired
FETCH NEXT FROM sql_cursor INTO #sql
END
CLOSE sql_cursor
DEALLOCATE sql_cursor
If you are against cursors, it could also be easily transformed into a while loop.

Find a database with a particular table OR Find a table in every database of SQL Server

I have a SQL Server with hundreds of databases and each database having hundreds of tables.
Now I would like to find where in these databases is a table that I am looking for.
I could find if a table existed in individual database using
use myDatabase
select * from sys.tables where name = 'mytable'
GO
but using this means I have to manually change the database for hundreds of times .
I would like to find the database name only.
Is there a way out ?
Okay, if you're just wanting to find each database that contains a particular table, and aren't going to be querying the table, then you can just do:
create table #t (
DBName sysname not null
)
go
exec sp_MSforeachdb 'use [?]; if OBJECT_ID(''dbo.mytable'') is not null insert into #t (DBName) select ''?'''
go
select * from #t
go
drop table #t
(If you're not using multiple schemas in your databases, you won't need to specify dbo in the OBJECT_ID call, otherwise I use it to avoid finding tables in the wrong schema)
This should do what you are looking for:
EXEC sp_MSforeachdb "use [?];select * from sys.tables where name='TableName' "
To include the name of the current database in the output use:
EXEC sp_MSforeachdb "use [?];select '[?]' as DatabaseName, * from sys.tables where name='TableName' "
SELECT DISTINCT DB_NAME(database_id)
FROM [sys].[dm_db_index_operational_stats](NULL,NULL,NULL,NULL)
WHERE OBJECT_NAME(object_id,database_id) = 'mytable'
I know this is an old thread but was high on my google search. So I wanted to contribute for others looking to find a database with a certain table in it. These apply to SQL Server 2008 - Current.
I started with this, which worked for my SA level login, but gave me issues with users that did not have permissions to all databases.
SELECT name
FROM sys.databases
WHERE CASE
WHEN state_desc = 'ONLINE' THEN OBJECT_ID( QUOTENAME( name ) + '.[dbo].[mytablename]','U' )
END IS NOT NULL;
But ended up with this adding the HAS_DBACCESS(name) = 1 in restriction so that the query would not fail with a security error.
SELECT name
FROM sys.databases
WHERE HAS_DBACCESS(name) = 1 and
CASE
WHEN state_desc = 'ONLINE' THEN OBJECT_ID( QUOTENAME( name ) + '.[dbo].[mytablename]','U' )
END IS NOT NULL;
exec sp_msforeachdb #command1='
USE ?;
select * from sys.tables where name = ''CLIENTS'''
this is also one of the way, similar with solution of #Jonathan :
exec sp_MSforeachdb 'SELECT "?" AS DB, * FROM [?].sys.tables WHERE name like ''%YourTableName%'''
exec 'select ''?'', name from [?].sys.tables where name = ''yourTable'''

Find stored procedure by name

Is there any way I can find in SQL Server Management Studio stored procedure by name or by part of the name? (on active database context)
Thanks for help
You can use:
select *
from
sys.procedures
where
name like '%name_of_proc%'
if you need the code you can look in the syscomments table
select text
from
syscomments c
inner join sys.procedures p on p.object_id = c.object_id
where
p.name like '%name_of_proc%'
Edit Update:
you can can also use the ansi standard version
SELECT *
FROM
INFORMATION_SCHEMA.ROUTINES
WHERE
ROUTINE_NAME LIKE '%name_of_proc%'
Assuming you're in the Object Explorer Details (F7) showing the list of Stored Procedures, click the Filters button and enter the name (or partial name).
This will work for tables and views (among other things) as well, not just sprocs:
SELECT
'[' + s.name + '].[' + o.Name + ']',
o.type_desc
FROM
sys.objects o
JOIN sys.schemas s ON s.schema_id = o.schema_id
WHERE
o.name = 'CreateAllTheThings' -- if you are certain of the exact name
OR o.name LIKE '%CreateAllThe%' -- if you are not so certain
It also gives you the schema name which will be useful in any non-trivial database (e.g. one where you need a query to find a stored procedure by name).
When I have a Store Procedure name, and do not know which database it belongs to, I use the following -
Use [master]
GO
DECLARE #dbname VARCHAR(50)
DECLARE #statement NVARCHAR(max)
DECLARE db_cursor CURSOR
LOCAL FAST_FORWARD
FOR
--Status 48 (mirrored db)
SELECT name FROM MASTER.dbo.sysdatabases WHERE STATUS NOT LIKE 48 AND name NOT IN ('master','model','msdb','tempdb','distribution')
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #statement = 'SELECT * FROM ['+#dbname+'].INFORMATION_SCHEMA.ROUTINES WHERE [ROUTINE_NAME] LIKE ''%name_of_proc%'''+';'
print #statement
EXEC sp_executesql #statement
FETCH NEXT FROM db_cursor INTO #dbname
END
CLOSE db_cursor
DEALLOCATE db_cursor
You can use this query:
SELECT
ROUTINE_CATALOG AS DatabaseName ,
ROUTINE_SCHEMA AS SchemaName,
SPECIFIC_NAME AS SPName ,
ROUTINE_DEFINITION AS SPBody ,
CREATED AS CreatedDate,
LAST_ALTERED AS LastModificationDate
FROM INFORMATION_SCHEMA.ROUTINES
WHERE
(ROUTINE_DEFINITION LIKE '%%')
AND
(ROUTINE_TYPE='PROCEDURE')
AND
(SPECIFIC_NAME LIKE '%AssessmentToolDegreeDel')
As you can see, you can do search inside the body of Stored Procedure also.
For SQL Server version 9.0 (2005), you can use the code below:
select *
from
syscomments c
inner join sys.procedures p on p.object_id = c.id
where
p.name like '%usp_ConnectionsCount%';
Option 1: In SSMS go to View > Object Explorer Details or press F7. Use the Search box. Finally in the displayed list right click and select Synchronize to find the object in the Object Explorer tree.
Option 2: Install an Add-On like dbForge Search. Right click on the displayed list and select Find in Object Explorer.
Very neat trick I stumble upon trying some SQL injection, in object explorer in the search box just use your percentage characters, and this will search EVERYTHING stored procedures, functions, views, tables, schema, indexes...I tired of thinking of more :)
Search Pattern

SQL Server - Return SCHEMA for sysobjects

How to I get the SCHEMA when doing a select on sysobjects?
I am modifing a stored procedure called SearchObjectsForText which returns only the Name but I would also like to include the SCHEMA.
Right now it is doing something similar to this:
SELECT DISTINCT name
FROM sysobjects
I would like to know what tables need to be joined to return the SCHEME for each 'name'.
If you mean SQL Server 2005 or higher, use sys.objects instead of sysobjects:
SELECT sys.objects.name, sys.schemas.name AS schema_name
FROM sys.objects
INNER JOIN sys.schemas ON sys.objects.schema_id = sys.schemas.schema_id
2005 introduced schemas. up to 2000, users equaled schemas. The same query for SQL Server 2000:
SELECT sysusers.name AS OwnerName, sysobjects.name
FROM sysobjects
INNER JOIN sysusers ON sysobjects.uid = sysusers.uid
On Sql Server 2005 (and above) you can use the sys.objects view:
select
name as ObjectName,
schema_Name(schema_id) as SchemaName
from
sys.objects
In Sql Server 2000 (and below), "schema" had a different conceptual meaning. Note from MSDN:
In earlier releases of SQL Server, databases could contain an entity called a "schema", but that entity was effectively a database user. SQL Server 2005 is the first release of SQL Server in which a schema is both a container and a namespace.
Could you use the Information_Schema view(s) instead?
SELECT DISTINCT table_name, table_schema
FROM INFORMATION_SCHEMA.TABLES
According to the MSDN page (for SQL Server 2008 and above),
Do not use INFORMATION_SCHEMA views to determine the schema of an object. The only reliable way to find the schema of a object is to query the sys.objects catalog view.
However, it seems that they're probably referring to an issue where you have a table name and are trying to find its schema, which wouldn't work if there were multiple tables with the same name (in different schemas). If you're querying for multiple results (not just trying to find the schema for a specific table), then it should be fine.
I would favor using the more focused "sys" views - sys.procedures instead of sys.objects. You'll need to join it with the sys.schemas view to get schema name and such.
select
p.name,
s.name 'Schema',
p.type_desc, p.create_date, p.modify_date
from
sys.procedures p
inner join
sys.schemas s ON p.schema_id = s.schema_id
I would start to get away from using "sysobjects" since Microsoft clearly states in Books Online that "sysobjects" is subject to removal in a future release:
This SQL Server 2000 system table is included as a view for backward compatibility. We recommend that you use the current SQL Server system views instead. To find the equivalent system view or views, see Mapping SQL Server 2000 System Tables to SQL Server 2005 System Views. This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature.
Marc
Just to repeat what's already been suggested here, here's what I've used, to get a list of Tables, Stored Procedures, Views and Functions in my database:
SELECT schema_Name(schema_id) as SchemaName,
[name], -- Name of the Table, Stored Procedure or Function
[type] -- 'V' for Views, 'U' for Table, 'P' for Stored Procedure, 'FN' for function
FROM sys.objects
WHERE [type_desc] IN ( 'USER_TABLE', 'SQL_STORED_PROCEDURE', 'VIEW', 'SQL_SCALAR_FUNCTION')
AND [name] NOT LIKE 'sp_%'
AND [name] NOT LIKE 'fn_%'
ORDER BY 3 DESC, -- type first
1 ASC, -- then schema
2 ASC -- then function/table name
...and here's what our good friend Northwind would return...
In SQL 200:
select DISTINCT
name as ObjectName,
USER_NAME(uid) as SchemaName
from
sysobjects
In earlier releases of SQL Server, databases could contain an entity called a "schema", but that entity was effectively a database user.
Have included an option to delete all objects starting with certain prefix and optionally from certain schema.
By the way, I added extra query to get all types which are not stored on sysobjects by default.
I have uploaded entire sample script to GitHub:
DropAll_Dnn_Objects.sql
Part 1: Temporary Stored Procedure:
IF OBJECT_ID('_temp_DropAllDnnObjects') IS NOT NULL
DROP PROCEDURE _temp_DropAllDnnObjects;
GO
CREATE PROCEDURE _temp_DropAllDnnObjects
#object_prefix NVARCHAR(30),
#schema_name sysname = NULL
AS
BEGIN
DECLARE #sname sysname, #name sysname, #type NVARCHAR(30)
DECLARE #object_type NVARCHAR(255), #sql NVARCHAR(2000), #count INT = 0
DECLARE curs CURSOR FOR
SELECT sname, [name], xtype
FROM (
SELECT SCHEMA_NAME(schema_id) as sname, [name], [type] as xtype
FROM sys.objects
WHERE [type] IN ('U', 'P', 'FN', 'IF', 'TF', 'V', 'TR')
AND name LIKE #object_prefix + '%'
AND (#schema_name IS NULL OR schema_id = SCHEMA_ID(#schema_name))
UNION ALL
SELECT SCHEMA_NAME(schema_id) as sname, [name], 'TYPE' as xtype
FROM sys.types
WHERE is_user_defined = 1
AND [name] LIKE #object_prefix + '%'
AND (#schema_name IS NULL OR schema_id = SCHEMA_ID(#schema_name))
) a
ORDER BY CASE xtype
WHEN 'P' THEN 1
WHEN 'FN' THEN 2
WHEN 'IF' THEN 3
WHEN 'TF' THEN 4
WHEN 'TR' THEN 5
WHEN 'V' THEN 6
WHEN 'U' THEN 7
WHEN 'TYPE' THEN 8
ELSE 9
END, name
OPEN curs;
FETCH NEXT FROM curs INTO #sname, #name, #type;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #count = #count + 1
-- Configuration point 2
SET #object_type = CASE #type
WHEN 'P' THEN 'PROCEDURE'
WHEN 'FN' THEN 'FUNCTION'
WHEN 'IF' THEN 'FUNCTION'
WHEN 'TF' THEN 'FUNCTION'
WHEN 'TR' THEN 'TRIGGER'
WHEN 'V' THEN 'VIEW'
WHEN 'U' THEN 'TABLE'
WHEN 'TYPE' THEN 'TYPE'
END
SET #sql = REPLACE(REPLACE(REPLACE('DROP <TYPE> [<SCHEMA>].[<NAME>];',
'<TYPE>', #object_type),
'<SCHEMA>', #sname),
'<NAME>', #name)
BEGIN TRY
PRINT #sql
EXEC(#sql)
END TRY
BEGIN CATCH
PRINT 'ERROR: ' + ERROR_MESSAGE()
END CATCH
FETCH NEXT FROM curs INTO #sname, #name, #type;
END;
PRINT CONCAT('Objects Found: ', #Count)
PRINT ''
PRINT '------------------------------------------------------'
PRINT ''
CLOSE curs;
DEALLOCATE curs;
RETURN #Count
END;
GO
It will continue on errors (and display the error message). It will return a count of all objects found.
Part 2: Call Stored Procedure with parameters:
You can create a WHILE loop in order to run the command until no object is left (dependencies), as follows:
DECLARE #count INT = 1
WHILE #count > 0 EXEC #count = _temp_DropAllDnnObjects 'dnn';
SET #count = 1
WHILE #count > 0 EXEC #count = _temp_DropAllDnnObjects 'aspnet';
SET #count = 1
WHILE #count > 0 EXEC #count = _temp_DropAllDnnObjects 'vw_aspnet';
GO
Part 3: Finally, get rid of the procedure:
IF OBJECT_ID('_temp_DropAllDnnObjects') IS NOT NULL
DROP PROCEDURE _temp_DropAllDnnObjects;
GO
Instead of a view, why not use this to populate a temporary table you can use?
This is the solution I use in stored procedures
This is the best way to get a schema dynamically and add it to the different tables within a database in order to get other information dynamically
select #sql = 'insert #tables SELECT ''[''+SCHEMA_NAME(schema_id)+''.''+name+'']'' AS SchemaTable FROM sys.tables'
exec (#sql)
of course #tables is a dynamic table in the stored procedure