<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Chris Schmidt’s Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/chriss/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/chriss/feed.xml</link>
    <description>thoughts on all things data</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:47:12 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Find users under a specific database role for all the servers in my environment</title>
      <link>https://docs.microsoft.com/archive/blogs/chriss/find-users-under-a-specific-database-role-for-all-the-servers-in-my-environment</link>
      <pubDate>Mon, 06 Jun 2016 13:59:29 GMT</pubDate>
      <dc:creator><![CDATA[Christopher M Schmidt]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chriss/?p=45</guid>
      <description><![CDATA[Recently I was working with a customer who wanted to know all the users in their environment who had...]]></description>
      <content:encoded><![CDATA[<p>Recently I was working with a customer who wanted to know all the users in their environment who had ssis_admin permissions within their Integration Services environment. In SQL Server 2008 R2, a new catalog view was introduced that allows us to bridge between database_roles and their associated members, under sys.database_role_members. With this simple bridge table, we can do some quick joins to the sys.database_principals catalog view and get a nice report of who has permissions under a specific database role. Here is a very straight forward SQL query that allows us to see all the users who have ssis_admin on our server:
</p><p style="margin-left: 36pt"><em>SELECT dr.name [DatabaseRoleName]
</em></p><p style="margin-left: 36pt"><em>    ,ISNULL(pr.Name, 'No Members Found!') [DatabaseUserName]
</em></p><p style="margin-left: 36pt"><em>FROM sys.database_role_members drm
</em></p><p style="margin-left: 36pt"><em>RIGHT JOIN sys.database_principals dr
</em></p><p style="margin-left: 36pt"><em>    ON drm.role_principal_id=dr.principal_id
</em></p><p style="margin-left: 36pt"><em>LEFT JOIN sys.database_principals pr
</em></p><p style="margin-left: 36pt"><em>    ON drm.member_principal_id=pr.principal_id
</em></p><p style="margin-left: 36pt"><em>WHERE dr.name = 'ssis_admin'</em>
	</p><p>You could easily change this to pull for any database role on any database. In this example I'm using it for ssis_admin under the SSISDB database. We can extend this in order to loop over a list of all servers in the environment by using PowerShell. In my environment, I have a centralized admin database that contains a list of all the servers that I want to track in my lab. I can query this from PowerShell by using Invoke-sqlcmd:
</p><p>
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#list of servers to be check</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:orangered">$servers</span>
			<span style="color:darkgray">=</span>
			<span style="color:blue">Invoke-Sqlcmd</span>
			<span style="color:navy">-ServerInstance</span>
			<span style="color:blueviolet">sql2016a</span>
			<span style="color:navy">-Database</span>
			<span style="color:blueviolet">PerformanceMonitor</span>
			<span style="color:navy">-Query</span>
			<span style="color:darkred">"SELECT DISTINCT [ServerName] FROM Server WHERE HasIsCatalog = 1" 
</span></span></p><p>
 </p><p>Next, we are going to wrap the actual sql statement we want to run inside of a function:
</p><p>
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#function to retrieve database users and roles</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkblue">Function</span>
			<span style="color:blueviolet">Get-DatabaseUsers</span> (<span style="color:darkgray">[<span style="color:teal">string<span style="color:darkgray">]<span style="color:orangered">$Servername</span>)
</span></span></span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">{
</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$query</span>
			<span style="color:darkgray">=</span>
			<span style="color:blue">Invoke-Sqlcmd</span>
			<span style="color:navy">-ServerInstance</span>
			<span style="color:orangered">$Servername</span>
			<span style="color:navy">-Database</span>
			<span style="color:blueviolet">SSISDB</span>
			<span style="color:navy">-Query</span>
			<span style="color:darkred">"SELECT @@SERVERNAME [ServerName]
</span></span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">    ,dr.name [DatabaseRoleName]
</span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">    ,ISNULL(pr.Name, 'No Members Found!') [DatabaseUserName]
</span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">FROM sys.database_role_members drm
</span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">RIGHT JOIN sys.database_principals dr
</span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">    ON drm.role_principal_id=dr.principal_id
</span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">LEFT JOIN sys.database_principals pr
</span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">    ON drm.member_principal_id=pr.principal_id
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkred">WHERE dr.name = 'ssis_admin'"</span>
		</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkgreen">#the below outputs the result of the above when the function is called</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$query</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">} 
</span></p><p>
 </p><p>The function itself is relatively straight-forward. It takes the query we wrote earlier in this blog, calls it from invoke-sqlcmd, and uses a parameter called $Servername as an input to know which server to run against. The bottom $query statement outputs the result of the invoke-sqlcmd from calling the function.
</p><p>
 </p><p>Next on our list is to write the result into our centralized admin server. One of the easiest ways to do this in PowerShell is to use a datatable  and then bulk copy the data into the table. We need to set the stage by creating a function:
</p><p>
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkblue">Function</span>
			<span style="color:blueviolet">out-DataTable</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">{
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$dt</span>
			<span style="color:darkgray">=</span>
			<span style="color:blue">new-object</span>
			<span style="color:blueviolet">Data.datatable</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$First</span>
			<span style="color:darkgray">=</span>
			<span style="color:orangered">$true</span>
		</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkblue">foreach</span> (<span style="color:orangered">$item</span>
			<span style="color:darkblue">in</span>
			<span style="color:orangered">$input</span>){  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$DR</span>
			<span style="color:darkgray">=</span>
			<span style="color:orangered">$DT<span style="color:darkgray">.</span>NewRow()  
</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$Item<span style="color:darkgray">.</span>PsObject<span style="color:darkgray">.</span>get_properties() <span style="color:darkgray">|</span>
				<span style="color:blue">foreach</span> {  
</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkblue">if</span> (<span style="color:orangered">$first</span>) {  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$Col</span>
			<span style="color:darkgray">=</span>
			<span style="color:blue">new-object</span>
			<span style="color:blueviolet">Data.DataColumn</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$Col<span style="color:darkgray">.</span>ColumnName <span style="color:darkgray">=</span> $_<span style="color:darkgray">.</span>Name<span style="color:darkgray">.</span>ToString()  
</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$DT<span style="color:darkgray">.</span>Columns<span style="color:darkgray">.</span>Add($Col</span>)       }  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkblue">if</span> (<span style="color:orangered">$_<span style="color:darkgray">.</span>value <span style="color:darkgray">-eq</span> $null</span>) {  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$DR<span style="color:darkgray">.</span>Item($_<span style="color:darkgray">.</span>Name) <span style="color:darkgray">=</span>
				<span style="color:darkred">"[empty]"</span>
			</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">      }  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkblue">elseif</span> (<span style="color:orangered">$_<span style="color:darkgray">.</span>IsArray) {  
</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$DR<span style="color:darkgray">.</span>Item($_<span style="color:darkgray">.</span>Name) <span style="color:darkgray">=[<span style="color:teal">string<span style="color:darkgray">]::</span>Join(<span style="color:orangered">$_<span style="color:darkgray">.</span>value <span style="color:darkgray">,<span style="color:darkred">";"</span>)  
</span></span></span></span></span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">      }  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkblue">else</span> {  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$DR<span style="color:darkgray">.</span>Item($_<span style="color:darkgray">.</span>Name) <span style="color:darkgray">=</span> $_<span style="color:darkgray">.</span>value  
</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">      }  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">    }  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$DT<span style="color:darkgray">.</span>Rows<span style="color:darkgray">.</span>Add($DR</span>)  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$First</span>
			<span style="color:darkgray">=</span>
			<span style="color:orangered">$false</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">  } 
</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkblue">return</span> @(<span style="color:darkgray">,</span>(<span style="color:orangered">$dt</span>))
</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">} 
</span></p><p>
 </p><p>And then we can loop over the list of servers in our environment that we want to manage and write the result to our data table. 
</p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#execute the functions</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkblue">foreach</span> (<span style="color:orangered">$ServerName</span>
			<span style="color:darkblue">in</span>
			<span style="color:orangered">$servers</span>)
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">{
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:orangered">$dataTable</span>
			<span style="color:darkgray">=</span>
			<span style="color:blue">Get-DatabaseUsers</span>
			<span style="color:orangered">$ServerName<span style="color:darkgray">.</span>ServerName <span style="color:darkgray">|</span>
				<span style="color:blue">out-DataTable</span>
			</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#$dataTable #you can use this to check the output</span>
		</span></p><p style="background: white">
 </p><p style="background: white">
 </p><p style="background: white"> 
 </p><p>Ensuring that we're getting the results we expect, now we can write the result to a sql table. We'll do this by using the Data.sqlclient.sqlbulkcopy object and mapping it to a predefined destination table. The below code segment handles this part of the process:
</p><p>
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#initialize a sqlbulk copy object to write the data to the centralized table</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:orangered">$connectionString</span>
			<span style="color:darkgray">=</span>
			<span style="color:darkred">"Data Source=sql2016a; Integrated Security=True;Initial Catalog=PerformanceMonitor;"</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#open the connection</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:orangered">$bulkCopy</span>
			<span style="color:darkgray">=</span>
			<span style="color:blue">new-object</span> (<span style="color:darkred">"Data.SqlClient.SqlBulkCopy"</span>) <span style="color:orangered">$connectionString</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#set the destination table</span>
		</span></p><p style="background: white"><span style="color:orangered;font-family:Lucida Console;font-size:9pt">$bulkCopy<span style="color:darkgray">.</span>DestinationTableName <span style="color:darkgray">=</span>
			<span style="color:darkred">"DatabaseRolesList"</span>
		</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#perform the column mappings</span>
		</span></p><p style="background: white"><span style="color:orangered;font-family:Lucida Console;font-size:9pt">$bulkCopy<span style="color:darkgray">.</span>ColumnMappings<span style="color:darkgray">.</span>Add(<span style="color:darkred">"ServerName"<span style="color:darkgray">,<span style="color:darkred">"ServerName"</span>)
</span></span></span></p><p style="background: white"><span style="color:orangered;font-family:Lucida Console;font-size:9pt">$bulkcopy<span style="color:darkgray">.</span>ColumnMappings<span style="color:darkgray">.</span>Add(<span style="color:darkred">"DatabaseRoleName"<span style="color:darkgray">,<span style="color:darkred">"DatabaseRoleName"</span>)
</span></span></span></p><p style="background: white"><span style="color:orangered;font-family:Lucida Console;font-size:9pt">$bulkcopy<span style="color:darkgray">.</span>ColumnMappings<span style="color:darkgray">.</span>Add(<span style="color:darkred">"DatabaseUserName"<span style="color:darkgray">,<span style="color:darkred">"DatabaseUserName"</span>)
</span></span></span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#write the data to the table</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:orangered">$bulkCopy<span style="color:darkgray">.</span>WriteToServer($dataTable</span>) 
</span></p><p>
 </p><p>The nice part about this script is that by simply changing the query in the invoke-sqlcmd function and doing the bulk copy mapping in the foreach loop, this script could be extended to run almost any sql query and write the results to a sql table.
</p><p>An end to end sample of the code is below.
</p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#list of servers to be check</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:orangered">$servers</span>
			<span style="color:darkgray">=</span>
			<span style="color:blue">Invoke-Sqlcmd</span>
			<span style="color:navy">-ServerInstance</span>
			<span style="color:blueviolet">sql2016a</span>
			<span style="color:navy">-Database</span>
			<span style="color:blueviolet">PerformanceMonitor</span>
			<span style="color:navy">-Query</span>
			<span style="color:darkred">"SELECT DISTINCT [ServerName] FROM Server WHERE HasIsCatalog = 1"</span>
		</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#data table to hold results</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkblue">Function</span>
			<span style="color:blueviolet">out-DataTable</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">{
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$dt</span>
			<span style="color:darkgray">=</span>
			<span style="color:blue">new-object</span>
			<span style="color:blueviolet">Data.datatable</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$First</span>
			<span style="color:darkgray">=</span>
			<span style="color:orangered">$true</span>
		</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkblue">foreach</span> (<span style="color:orangered">$item</span>
			<span style="color:darkblue">in</span>
			<span style="color:orangered">$input</span>){  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$DR</span>
			<span style="color:darkgray">=</span>
			<span style="color:orangered">$DT<span style="color:darkgray">.</span>NewRow()  
</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$Item<span style="color:darkgray">.</span>PsObject<span style="color:darkgray">.</span>get_properties() <span style="color:darkgray">|</span>
				<span style="color:blue">foreach</span> {  
</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkblue">if</span> (<span style="color:orangered">$first</span>) {  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$Col</span>
			<span style="color:darkgray">=</span>
			<span style="color:blue">new-object</span>
			<span style="color:blueviolet">Data.DataColumn</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$Col<span style="color:darkgray">.</span>ColumnName <span style="color:darkgray">=</span> $_<span style="color:darkgray">.</span>Name<span style="color:darkgray">.</span>ToString()  
</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$DT<span style="color:darkgray">.</span>Columns<span style="color:darkgray">.</span>Add($Col</span>)       }  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkblue">if</span> (<span style="color:orangered">$_<span style="color:darkgray">.</span>value <span style="color:darkgray">-eq</span> $null</span>) {  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$DR<span style="color:darkgray">.</span>Item($_<span style="color:darkgray">.</span>Name) <span style="color:darkgray">=</span>
				<span style="color:darkred">"[empty]"</span>
			</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">      }  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkblue">elseif</span> (<span style="color:orangered">$_<span style="color:darkgray">.</span>IsArray) {  
</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$DR<span style="color:darkgray">.</span>Item($_<span style="color:darkgray">.</span>Name) <span style="color:darkgray">=[<span style="color:teal">string<span style="color:darkgray">]::</span>Join(<span style="color:orangered">$_<span style="color:darkgray">.</span>value <span style="color:darkgray">,<span style="color:darkred">";"</span>)  
</span></span></span></span></span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">      }  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkblue">else</span> {  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$DR<span style="color:darkgray">.</span>Item($_<span style="color:darkgray">.</span>Name) <span style="color:darkgray">=</span> $_<span style="color:darkgray">.</span>value  
</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">      }  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">    }  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$DT<span style="color:darkgray">.</span>Rows<span style="color:darkgray">.</span>Add($DR</span>)  
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$First</span>
			<span style="color:darkgray">=</span>
			<span style="color:orangered">$false</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">  } 
</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkblue">return</span> @(<span style="color:darkgray">,</span>(<span style="color:orangered">$dt</span>))
</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">}
</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#function to retrieve database users and roles</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkblue">Function</span>
			<span style="color:blueviolet">Get-DatabaseUsers</span> (<span style="color:darkgray">[<span style="color:teal">string<span style="color:darkgray">]<span style="color:orangered">$Servername</span>)
</span></span></span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">{
</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$query</span>
			<span style="color:darkgray">=</span>
			<span style="color:blue">Invoke-Sqlcmd</span>
			<span style="color:navy">-ServerInstance</span>
			<span style="color:orangered">$Servername</span>
			<span style="color:navy">-Database</span>
			<span style="color:blueviolet">SSISDB</span>
			<span style="color:navy">-Query</span>
			<span style="color:darkred">"SELECT @@SERVERNAME [ServerName]
</span></span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">    ,dr.name [DatabaseRoleName]
</span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">    ,ISNULL(pr.Name, 'No Members Found!') [DatabaseUserName]
</span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">FROM sys.database_role_members drm
</span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">RIGHT JOIN sys.database_principals dr
</span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">    ON drm.role_principal_id=dr.principal_id
</span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">LEFT JOIN sys.database_principals pr
</span></p><p style="background: white"><span style="color:darkred;font-family:Lucida Console;font-size:9pt">    ON drm.member_principal_id=pr.principal_id
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkred">WHERE dr.name = 'ssis_admin'"</span>
		</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:darkgreen">#the below outputs the result of the above when the function is called</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">
			<span style="color:orangered">$query</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">}
</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#execute the functions</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkblue">foreach</span> (<span style="color:orangered">$ServerName</span>
			<span style="color:darkblue">in</span>
			<span style="color:orangered">$servers</span>)
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">{
</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:orangered">$dataTable</span>
			<span style="color:darkgray">=</span>
			<span style="color:blue">Get-DatabaseUsers</span>
			<span style="color:orangered">$ServerName<span style="color:darkgray">.</span>ServerName <span style="color:darkgray">|</span>
				<span style="color:blue">out-DataTable</span>
			</span></span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#$dataTable #you can use this to check the output</span>
		</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#initialize a sqlbulk copy object to write the data to the centralized table</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:orangered">$connectionString</span>
			<span style="color:darkgray">=</span>
			<span style="color:darkred">"Data Source=sql2016a; Integrated Security=True;Initial Catalog=PerformanceMonitor;"</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#open the connection</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:orangered">$bulkCopy</span>
			<span style="color:darkgray">=</span>
			<span style="color:blue">new-object</span> (<span style="color:darkred">"Data.SqlClient.SqlBulkCopy"</span>) <span style="color:orangered">$connectionString</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#set the destination table</span>
		</span></p><p style="background: white"><span style="color:orangered;font-family:Lucida Console;font-size:9pt">$bulkCopy<span style="color:darkgray">.</span>DestinationTableName <span style="color:darkgray">=</span>
			<span style="color:darkred">"DatabaseRolesList"</span>
		</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#perform the column mappings</span>
		</span></p><p style="background: white"><span style="color:orangered;font-family:Lucida Console;font-size:9pt">$bulkCopy<span style="color:darkgray">.</span>ColumnMappings<span style="color:darkgray">.</span>Add(<span style="color:darkred">"ServerName"<span style="color:darkgray">,<span style="color:darkred">"ServerName"</span>)
</span></span></span></p><p style="background: white"><span style="color:orangered;font-family:Lucida Console;font-size:9pt">$bulkcopy<span style="color:darkgray">.</span>ColumnMappings<span style="color:darkgray">.</span>Add(<span style="color:darkred">"DatabaseRoleName"<span style="color:darkgray">,<span style="color:darkred">"DatabaseRoleName"</span>)
</span></span></span></p><p style="background: white"><span style="color:orangered;font-family:Lucida Console;font-size:9pt">$bulkcopy<span style="color:darkgray">.</span>ColumnMappings<span style="color:darkgray">.</span>Add(<span style="color:darkred">"DatabaseUserName"<span style="color:darkgray">,<span style="color:darkred">"DatabaseUserName"</span>)
</span></span></span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:darkgreen">#write the data to the table</span>
		</span></p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt"><span style="color:orangered">$bulkCopy<span style="color:darkgray">.</span>WriteToServer($dataTable</span>)
</span></p><p style="background: white">
 </p><p style="background: white"><span style="font-family:Lucida Console;font-size:9pt">}
</span></p><p style="background: white">
 </p><p style="background: white"> 
 </p><p>
 </p><p>
 </p><p>
 </p><p>
 </p>]]></content:encoded>
    </item>
    <item>
      <title>Load Testing SSAS with PowerShell</title>
      <link>https://docs.microsoft.com/archive/blogs/chriss/load-testing-ssas-with-powershell</link>
      <pubDate>Wed, 01 Jun 2016 11:54:40 GMT</pubDate>
      <dc:creator><![CDATA[Christopher M Schmidt]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chriss/?p=25</guid>
      <description><![CDATA[Over the years, there has been much confusion as to the best way to load test Analysis Services. I...]]></description>
      <content:encoded><![CDATA[Over the years, there has been much confusion as to the best way to load test Analysis Services. I have seen solutions ranging from as simple as using <em>ascmd</em> to completely custom console apps in Visual Studio. One of the challenging aspects of Business Intelligence solutions has been unit testing in the past, and I believe that one of the major barriers to adoption has been the complexity required to set things up. Projects always have very tight deadlines, and who has the time, I hear a lot. Fortunately, with Powershell and the Invoke-ASCmd cmdlet this becomes a very direct exercise and removes any barriers. This solution can be used either against Multidimensional or Tabular databases, with either MDX, DAX, or DMX queries.

The Invoke-ASCMD cmdlet is a part of the sqlps module for Powershell. If you do not already have this imported into your environment, the first step would be to bring this in so you can properly run script against Analysis Services.

&nbsp;

## Import the SQL Server Module.

&nbsp;

Import-Module “sqlps” -DisableNameChecking

&nbsp;

&nbsp;

Once this is done, we can then start running queries by using the Invoke-ASCmd cmdlet within PowerShell. This cmdlet allows us execute MDX, XMLA, DAX, DMX, or (with tabular 2016 only) TMSL scripts against an Analysis Server remotely. A very straightforward run of the cmdlet would look something like the below:

#Issue a query command against SSAS and output result to disk

Invoke-ASCmd -Server localhost\sql2012tabular -Database "AdventureWorks Tabular Model SQL 2012" -Query "SELECT { [Measures].[Number of Orders], [Measures].[Sum of SalesAmount] } ON COLUMNS ,

&nbsp;

NON EMPTY { [Date].[Calendar].[Year] } ON ROWS

&nbsp;

FROM [Model]"

&nbsp;

Where the -Server parameter denotes the server you want to run against, -Database is the database you want to hit, and -Query is the query you want to run. This is very handy but can be extended by changing the -Query parameter to an Input File parameter. This allows us to write and manage our queries separately. Additionally, instead of 1 query having them separated into a new InputFile gives the ability to run multiple queries via the use of the GO operator between queries. Looking at the same query above but with the InputFile parameter we get the below syntax:

Invoke-ASCmd -Server localhost\sql2012tabular -Database "AdventureWorks Tabular Model SQL 2012" -InputFile "C:\ASPowershellFolder\InputQueries\Query1.mdx"

&nbsp;

And the queries that live in the Query1.mdx file are as follows:

SELECT NON EMPTY { [Measures].[Sum of SalesAmount], [Measures].[Number of Orders] } ON COLUMNS

, NON EMPTY { ([Customer].[Occupation].[Occupation].ALLMEMBERS ) } ON ROWS

FROM [Model]

GO

SELECT NON EMPTY { [Measures].[Sum of SalesAmount] } ON COLUMNS

, NON EMPTY { ([Date].[Calendar].[Month].ALLMEMBERS ) } ON ROWS

FROM [Model]

GO

&nbsp;

Ok, we now have a simple elegant way to run either a single or multiple query(ies) against SSAS through PowerShell. We can now extend our solution via the use of PowerShell workflows. Workflows are a way in which PowerShell can do the same thing multiple times and retry upon failure, as well as creating a queue that stacks up. Without the use of the workflow, if we executed the above script with 1000 concurrent queries, all 1000 would fire off, some would be successful and the rest would fail after we hit our limit. Workflows take the 1000 queries and send them in via managed requests up to the max point the server can handle. I found the below code from Jamie Thomson over on <a href="https://sqlblog.com/blogs/jamie_thomson/archive/2014/12/09/parallel-foreach-loops-one-reason-to-use-powershell-workflow-instead-of-ssis.aspx">sqlblog</a>, which is very close to what we are looking for. By changing the function that he created to call a URI to our earlier Invoke-ASCmd, we can kick off a specified number of requests in parallel against our database! The code to create the workflow is below:

#used the workflow code from Jamie Thomson's parallel workflows in Powershell tip at https://sqlblog.com/blogs/jamie_thomson/archive/2014/12/09/parallel-foreach-loops-one-reason-to-use-powershell-workflow-instead-of-ssis.aspx

#given an specified input file path and the database that it should be run under, runs a simulated load test against an SSAS server with the specified number of

#used the workflow code from Jamie Thomson's parallel workflows in Powershell tip at https://sqlblog.com/blogs/jamie_thomson/archive/2014/12/09/parallel-foreach-loops-one-reason-to-use-powershell-workflow-instead-of-ssis.aspx

#given an specified input file path and the database that it should be run under, runs a simulated load test against an SSAS server with the specified number of

workflow asloadtest{

Param($NumberofConnections)

&nbsp;

$array = 1..$NumberofConnections

&nbsp;

&nbsp;

function ASLoadTest($i){

Invoke-ASCmd -Server localhost\sql2012tabular -Database "AdventureWorks Tabular Model SQL 2012" -InputFile "C:\ASPowershellFolder\InputQueries\Query1.mdx"

;

}

&nbsp;

&nbsp;

foreach -parallel ($i in $array) {ASLoadTest $i}

&nbsp;

}

cls

&nbsp;

asloadtest 5

&nbsp;

Now the only thing left for us to do is to call the workflow to execute, and pass in the number of connections that we want to execute in parallel. This is a very straightforward command:

&nbsp;

asloadtest 5

&nbsp;

Where asloadtest is the name of the workflow and the 5 is the number of connections parameter. That’s it! With 20 lines of PowerShell code we have a scalable SSAS load testing harness. What’s really cool is that we can easily change the Invoke-ASCmd to Invoke-SQLCmd and reuse this exact same approach for load testing the database engine as well. How cool is that!? Now that we have the hard part done the next step is to configure analysis services to capture the performance monitor metrics that we want to see. Over on his <a href="https://byobi.com/blog/2016/03/performance-monitoring-for-ssas-perfmon-counter-cheat-sheet/">blog</a>, Bill Anton has done an excellent job detailing what perfmon metrics you should be capturing for SSAS and why they are all important (as well as a super helpful summary list at the bottom).

&nbsp;

The complete PowerShell scripts are available <a href="https://gallery.technet.microsoft.com/SQL-Server-Analysis-Load-48d7adea">here</a> on the TechNet gallery for download.

&nbsp;

&nbsp;

&nbsp;

&nbsp;]]></content:encoded>
    </item>
  </channel>
</rss>