Using user defined assemblies from Powershell - sql-server

I am trying to extract list of user defined assemblies through PowerShell for one of SQL Server administration for automation.
When I open SSMS and execute this query as
Select name, permission_set_desc
From sys.assemblies
I am able to get the output as 2 rows as below
Name
Permission_Set_Desc
Microsoft.SqlServer.Types
UNSAFE_ACCESS
StairwayToSQLCLR-02-Example
SAFE_ACCESS
When I execute the same T-SQL through PowerShell using Invoke-SQLCMD command, I do not get any user defined assemblies rather only system defined assembly.
This is the command I used in PowerShell:
$query = "Select name, permission_Set_Desc from sys.assemblies"
Invoke-Sqlcmd -Query $query -AbortOnError -OutputSQLErrors $true
I get the below only which is system defined assembly.
Name
Permission_Set_Desc
Microsoft.SqlServer.Types
UNSAFE_ACCESS
I am unable to get the user defined assemblies from PowerShell.
Did I miss something here?

As #Vijayanand A said, assemblies are defined at database level. However, you can iterate all databases and display all of them with attached assemblies:
DECLARE #sql nvarchar(MAX) = '';
SELECT #sql += 'SELECT '+
QUOTENAME(DB.Name, '''') + ' COLLATE database_default db, '+
'name COLLATE database_default name, '+
'permission_set_desc COLLATE database_default permission_set_desc '+
'FROM ' + QUOTENAME(DB.Name) + '.sys.assemblies UNION ALL '
FROM sys.databases DB
SET #sql = LEFT(#sql, LEN(#sql)-LEN(' UNION ALL'))
EXEC(#sql)

Related

How to execute below T-SQL script into PowerShell

Hi I am struggling into writing a PowerShell script to drop the database, based on some conditions.I have SQL script running but facing too many syntax error when converting same script to PowerShell
DECLARE #Sql as NVARCHAR(MAX) = (SELECT 'DROP DATABASE ['+ name + ']; ' FROM sys.databases WHERE name like '%Dev%'
and database_id < (SELECT max(database_id) FROM sys.databases where source_database_id IS NOT NULL and name like '%Dev%' )
FOR XML PATH('')) EXEC sys.sp_executesql #Sql
I am new to PowerShell script so any help would be great.
I tried something like below but getting a syntax error in PowerShell
$query= 'DECLARE #Sql as NVARCHAR(MAX) = (SELECT 'DROP DATABASE ['+ name + ']; ' FROM sys.databases WHERE name like '%Dev%'
and database_id < (SELECT max(database_id) FROM sys.databases where source_database_id IS NOT NULL and name like '%Dev%' )
FOR XML PATH('')) EXEC sys.sp_executesql #Sql '
echo $query
Invoke-Sqlcmd -ServerInstance ''XXXX' -Username 'XX' -Password 'XXXXX' -Query $query -QueryTimeout 600 -Verbose
I Just putted everything in "" and it worked.

Get all the table names that are available in all the schemas

I do not have names of the schema that are available. According to my finding all the queries that i am using are specific to a schema name. I need name of all the tables irrespective of the schema name.
Can anyone help me with that.
I have used the following queries:
SELECT sch.name AS SchemaName , tbl.name AS TableName FROM sys.tables tbl INNER JOIN sys.schemas sch ON tbl.SCHEMA_ID = sch.SCHEMA_ID ORDER BY tbl.name;
select * from information.schema.tables where TABLE_TYPE='BASE TABLE';
select * from sys.tables;
select * from sysobjects where xtype='U';
All of these queries are schema specific. If we want to switch between schema we have to use USE %SCHEMA_NAME%. but i need to get all the table names irrespective of the schema name.
Apologies, but i meant to say databases
A database and a schema, in SQL Server, are very different objects. A schema is an object within a database, where as a database is on "object" in an instance. The sys and INFORMATION_SCHEMA objects are also database objects and so will only list the objects within the database context they are referenced in.
For example the below 2 examples would both return details of tables in the MyDB database:
USE master;
SELECT *
FROM MyDB.sys.tables;
GO
USE MyDB;
SELECT *
FROM sys.tables;
If you want to get the details of tables in every Database you'll either need to query them separately, or generate and run a dynamic statement. The dynamic approach would be something like this:
USE master;
GO
DECLARE #SQL nvarchar(MAX),
#CRLF nchar(2) = NCHAR(13) + NCHAR(10);
DECLARE #Delimiter nvarchar(30) = #CRLF + N'UNION ALL' + #CRLF;
SET #SQL = (SELECT STRING_AGG(N'SELECT N' + QUOTENAME(d.[name],'''') + N' AS DatabaseName, t.[name] AS TableName FROM ' + QUOTENAME(d.[name]) + N'.sys.tables t', #Delimiter) WITHIN GROUP (ORDER BY d.database_id)
FROM sys.databases d
WHERE d.database_id > 4) + N';' --skip system databases
--PRINT #SQL; --Your best friend
EXEC sys.sp_executesql #SQL;
If you're using an older version of SQL Server, you'll need to use the "old" FOR XML PATH method, rather than STRING_AGG.

Get all stored procedures where table is being used in SQL Server

I need the query or code in SQL Server to get all the stored procedures in which table is being used in the server (need all stored procedures in all databases on that server).
SELECT *
FROM sys.procedures
WHERE OBJECT_DEFINITION(OBJECT_ID) LIKE '%[dbo].[Batch]%.
Above query will give in the current database but I need the query to get from all the databases in that server.
Thanks. Sandeep
Try this:
select * from sysobjects where id in
(select id from syscomments where text like '%myquery%')
order by [name]
where "myquery" is the name of the table. You need to run this on each database on the server individually.
EXECUTE master.sys.sp_MSforeachdb
"USE [?]; SELECT * FROM sys.procedures WHERE OBJECT_DEFINITION(OBJECT_ID) LIKE '%[dbo].[Batch]%'"
Just consider your permutations of the code that references the Batch object (dbo.batch, [dbo].[batch], dbo.[batch], etc)
Thanks for the help. I got that below query will give all Stored Procedures that are dependent on any table or view for all the databases in the server.
DECLARE #SQL NVARCHAR(max)
SELECT #SQL = STUFF((SELECT ' UNION ALL SELECT ' + quotename(NAME, '''') + ' AS Db_Name, Routine_Name collate SQL_Latin1_General_CP1_CI_AS as SP_Name FROM ' + quotename(NAME) + '.INFORMATION_SCHEMA.Routines WHERE ROUTINE_Definition like ''%Replace_Table_Name_Here%'' AND ROUTINE_TYPE = ''PROCEDURE''' FROM sys.databases ORDER BY NAME FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 11, '')
EXECUTE sp_executeSQL #SQL

Is is possible to find an equivalent Login in a 2nd database via a single query?

A database-level Login can be associated with zero to one server-instance-level Logins. And if it exists, that in turn can be associated with zero to one database-level Logins on another database.
Is it possible to retrieve the matching Login using a single query?
Given the answer to this question, I suspect it's not. But it's worth asking.
Assuming you have a local database user named foo, you can use this query to find out if there is a related user in database [splunge]:
SELECT [local].[name], [remote].[name]
FROM sys.database_principals AS [local]
INNER JOIN [splunge].sys.database_principals AS [remote]
ON [local].[sid] = [remote].[sid]
WHERE [local].[name] = 'foo';
If you don't know which other database(s) the related login may be found in, then no, there isn't a simple way without constructing a query like the answer in the other question you pointed to. If you are going to use sp_msForEachDB, please use caution:
Making a more reliable and flexible sp_MSforeachdb
Execute a Command in the Context of Each Database in SQL Server
One way to do this a little easier would be:
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql = #sql + '
UNION ALL SELECT ''' + QUOTENAME(name)
+ ''', name COLLATE SQL_Latin1_General_CP1_CI_AS
FROM ' + QUOTENAME(name) + '.sys.database_principals
WHERE sid IN (SELECT sid FROM x)'
FROM sys.databases
WHERE database_id > 4; -- assume ignore system dbs
SET #sql = ';WITH x AS (SELECT sid FROM sys.database_principals
WHERE name = ''foo'')' + STUFF(#sql, 1, 12, '') + ';';
PRINT #sql;
--EXEC sp_executesql #sql;
This doesn't meet your requirement of "a single query" but maybe you could explain why that is a requirement.

Undocumented System Procedure 'sp_MSforeachtable' and the #whereand parameter

I'm attempting to use the undocumented system procedure sp_MSforeachtable. But I need to restrict the affected tables to those that start with "smp" and that are in the "dbo" schema. I was able to find how to find procedures that start with "smp". I simply do:
sp_MSforeachtable #command1=' print ''?''', #whereand=' and name like ''smp%'' '
but how do I filter for a given schema using the #whereand parameter?
UPDATE: I tried the following but it didn't work:
sp_MSforeachtable #command1=' print ''?''', #whereand=' and name like ''smp%'' and Left(''?'', 5)=''[dbo]'' '
Update 2: I'm running on SQL Server 2000.
Update for SQL2000:
declare #s nvarchar(1000)
set #s = ' and uid = ' + convert(nvarchar, user_id('my_schema'))
exec sp_msforeachtable #command1='print ''?''', #whereand = #s
This should works in SQL Server 2000 (can't test now):
#whereand = '
AND name like ''smp%'' AND
OBJECTPROPERTY(OBJECT_ID(''name''), ''OwnerID'') = USER_ID(''dbo'')'
Use OBJECTPROPERTY to find the schema owner id.
Edit: OK, tested it on a SQL 2000 box:
#whereand = ' AND name LIKE ''smp%'' AND uid = 1'
OR
#whereand = ' AND name LIKE ''smp%'' AND USER_ID(''dbo'')'
I could not get OBJECTPROPERTY to work
From here:
---------------------
--Drop table of particular shcemaID/shemaName and with name starting with 'Temp_'
Exec sp_MSforeachtable #command1 = "DROP TABLE ? PRINT '? dropped'"
,#whereand = "and uid = (SELECT schema_id FROM sys.schemas WHERE name = 'dbo')
and o.name LIKE 'Temp_%'"
---------------------
This verion works in Sql Server 2005:
exec sp_MSforeachtable
#command1=' print ''?''',
#whereand=' and schema_name(schema_id) = ''dbo'' '
Not exactly sure for Sql Server 2000, but this version might work:
exec sp_MSforeachtable
#command1=' print ''?''',
#whereand=' and user_name(uid) = ''dbo'' '
This worked in 2008 R2
#whereand='and uid = (SELECT schema_id FROM sys.schemas WHERE name = ''dbo'') and o.name LIKE ''TEMP_%'''

Resources