SQLvariations: SQL Server, a little PowerShell, maybe some Hyper-V Rotating Header Image

PowerShell

PowerShell Presentation at SQLskills open-mic night

Kimberly Tripp ( blog | twitter ) and Paul Randal ( blog | twitter ) SQLsklls are here in Atlanta this week.  Last night they held an ‘open mic’ night and allowed anyone who wanted to present a topic 15 minutes to show something to the rest of the class.  Surprise, surprise I decided to talk about PowerShell.

I received multiple requests to post the scripts I used before I even had a chance to sit down so here they are.

If you were in the class and would like to use these and don’t even know where to start with PowerShell have a look at my “Resources for my SQL Server PowerShell Extensions webcast” post.

If you ever get a chance to attend one of their classes and present in front of Paul and Kim TAKE IT! :-)   Even if it’s just about your SSMS tips or how to work around a problem you encountered.  The feedback you get is *more* than worth it!

Quick Blog: Grabbing basic machine info with PowerShell

The other day I needed to track down how much RAM a couple of our servers had installed.  A few days later I needed to verify that a couple of them were in fact 64-bit and not 32-bit.  I decided I wanted to be able to get at this basic info any time that I wanted without having to remember all the syntax so I built it into a PowerShell function.

Building a PowerShell function is almost as easy easier than building a stored procedure around a select statement in SQL.  The reason PowerShell is easier than SQL is that when you have a parameter that you are passing in, you can give it a data type, but you don’t have to.

For the function below I gave it a default value of the local machine but you can pass in a machine name that you are trying to get to.

Just copy the code below into an ISE window and hit F5.

function Get-MachineInfo($ServerName="localhost")             
{            
get-wmiobject win32_computersystem -ComputerName $ServerName |            
select DNSHostName, Manufacturer, Model, SystemType ,             
        @{Name="TotalPhysicalMemoryInMB";Expression={"{0:n2}" -f($_.TotalPhysicalMemory/1mb)}},             
        NumberOfLogicalProcessors, NumberOfProcessors, CurrentTimeZone, DaylightInEffect            
}# End Get-MachineInfo

After you’ve done that, to call the stored proc function simply type in the name ( Get-MachineInfo ) to the prompt at the bottom and hit enter

image

Scripts for presentation today at the 2011 PASS Summit

I’m presenting at the PASS Summit today and just wanted to post the scripts I plan on using.  If you’re following along and you’re new to PowerShell I recommend that you have a look at this article I wrote earlier this year: Day Zero with PowerShell

  1. Table Size
    1. Store Results
  2. Compress Tables
    1. Compress Indexes
    2. Store Results
  3. Process Cube
  4. Backup Database –PassThru
  5. Download Denali CTP
  6. Grab Configuration Info
  7. New Get-DisksSpace try to pass from Reg servers w/ Group
  8. Email Space Report
  9. CSV with Bulk Insert
  10. Import CSV with Out-DataTable
  11. Allen Kinsel – Logs
  12. SQL Saturday – Navigate Event Schedule XML

Whats in my PowerShell Profile

Here are two zip files.  The first file is my profile and the second zip file is the scripts that my profiles references.  These are just some of the tools I find useful for enhancing PowerShell.

Resources for my SQL Server PowerShell Extensions webcast

imageI did another webcast for the Secrets of SQL Server webcast series today.  In the today’s webcast we built on some things I had demoed in a prior webcast and showed how PowerShell in conjunction with SQLPSX can really help you solve some common problems DBAs face.

I showed how you could pull size and free space information from all of your data files, then used the same technique to pull size information from all of your tables across every database on an instance.  Later we created a database and some tables, and then showed how to do some basic login comparisons, all with SQLPSX.

In addition, we stored the results of the frees pace and table size information in a database using the Out-DataTable and Write-DataTable functions.  Finally we wrapped up with a quick demo on how the new SQL Server cmdlets inside of the SQLPS Module in Denali combined with some new functionality in PowerShell v3 CTP1 can really make backing up a database with PowerShell a lot easier.

Here’s what you’ll need to recreate today’s demos;

I hope I see you next week at the PASS Summit or next month during another webcast, this time on customizing your own functions to work with the SMO.

New PowerShell Cmdlets in SQL Denali CTP3

CTP3 of SQL Denali is finally publicly available!

I woke up at 5 am this morning to kick off my download.  I’ve finished the install and I’m happy that I can finally report that we have new cmdlets for SQL Server. 

First off, after running Get-Module -ListAvailable I saw:

Manifest   SQLASCMDLETS
Manifest   SQLPS

This means that SQLPS inside of SQL Agent should finally allow you to import a module during your job step. 

There is now a Function called SQLServer that, from what I can tell, is the SQLServer Provider.  When under PS SQLSERVER:\> if you do a dir | Select pschildname you will find the following list:

PSChildName
———–
SQL
SQLPolicy
SQLRegistration
DataCollection
XEvent
Utility
DAC
IntegrationServices
SQLAS

From my notes it looks like XEvent, IntegrationServices, and SQLAS are the directories that have been added here.  Can’t wait to try out the IntegrationServices portion!  [Update]: Apparently I may need a defaul instance install for this to work.

I also noticed that Tab-Completion appears to be fixed!!  :-)   Also, SQL Registrations > ‘Database Engine Server Group’ are split up into instances like CMS was.  Not sure what that’s all about just yet.  In fact when I try to use it, it doesn’t seem to work.  Maybe I should read the help files.  But I think they may have just gotten CMS & RS reversed.  CMS isn’t working for me either yet.

When you drill down under XEvents and go to your Denali instaince you will see: Packages, & Sessions.  I guess this means that I finally need to read Jonathat’s blog series on X-Events.

When I imported the SQLPS module I received a warning about unapproved verbs.  Oh well, hopefully they’ll work that out soon.  Next I ran Get-Command -Module “SQLPS” and found the following list of cmdlets.

Name Module
Add-SqlAvailabilityDatabase SQLPS
Add-SqlAvailabilityGroupListenerStaticIp SQLPS
Backup-SqlDatabase SQLPS
Convert-UrnToPath SQLPS
Decode-SqlName SQLPS
Disable-SqlHADRService SQLPS
Enable-SqlHADRService SQLPS
Encode-SqlName SQLPS
Invoke-PolicyEvaluation SQLPS
Invoke-Sqlcmd SQLPS
Join-SqlAvailabilityGroup SQLPS
New-SqlAvailabilityGroup SQLPS
New-SqlAvailabilityGroupListener SQLPS
New-SqlAvailabilityReplica SQLPS
New-SqlHADREndpoint SQLPS
Remove-SqlAvailabilityDatabase SQLPS
Remove-SqlAvailabilityGroup SQLPS
Remove-SqlAvailabilityReplica SQLPS
Restore-SqlDatabase SQLPS
Resume-SqlAvailabilityDatabase SQLPS
Set-SqlAvailabilityGroup SQLPS
Set-SqlAvailabilityGroupListener SQLPS
Set-SqlAvailabilityReplica SQLPS
Set-SqlHADREndpoint SQLPS
SQLSERVER SQLPS
Suspend-SqlAvailabilityDatabase SQLPS
Switch-SqlAvailabilityGroup SQLPS
Test-SqlAvailabilityGroup SQLPS
Test-SqlAvailabilityReplica SQLPS
Test-SqlDatabaseReplicaState SQLPS

Analysis Services got some love too in the form of 11 cmdlets!  After inporting the SQLASCMDLETS module I ran this Get-Command -Module “SQLASCMDLETS” and found the following.

Name Module
Add-RoleMember SQLASCMDLETS
Backup-ASDatabase SQLASCMDLETS
Invoke-ASCmd SQLASCMDLETS
Invoke-ProcessCube SQLASCMDLETS
Invoke-ProcessDimension SQLASCMDLETS
Invoke-ProcessPartition SQLASCMDLETS
Merge-Partition SQLASCMDLETS
New-RestoreFolder SQLASCMDLETS
New-RestoreLocation SQLASCMDLETS
Remove-RoleMember SQLASCMDLETS
Restore-ASDatabase SQLASCMDLETS

More news to follow soon!

Emailing tempdb Query Results to Paul Randal with PowerShell

imageI was referred to someone on twitter today who wants to email query results without setting up database mail.  I explained this in Post 6 of PowerShell Week at SQL University but that example was somewhat complicated. Instead, I thought I’d whip up a new example using Paul’s latest survey.  Paul want’s to know know how many cores your instances have and how many data files that tempdb has.

Paul’s query is pretty simple:

SELECT os.Cores, df.Files
FROM
(SELECT COUNT(*) AS Cores FROM sys.dm_os_schedulers WHERE status = 'VISIBLE ONLINE') AS os,
(
SELECT COUNT(*) AS Files FROM tempdb.sys.database_files WHERE type_desc = 'ROWS') AS df;
GO

I simply took that query and wrapped it with almost the same code that I used at SQL University.  The difference allows me to show off two new tricks.  Smile

  • First, I separated out the part that grabs the list of servers from your Registered Servers to happen before the foreach loop.  I had received feedback from a reader that A) Having it there made it hard to read on my website, and B) it simplified the logic flow.  It also has the added benefits of performing faster when you’re running against hundreds of instances like me, and making it a little more clear how to swap it out when you want to use something besides Registered Servers to list your instances.  For more information on the different data sources that you can use for reading in a list of servers have a look here at Post 5.
  • Second I added this $S++; it is a little piece of code to enumerate the instances for you.  Last time I had written the results to a table and then read them out using DENSE_RANK but since we don’t have multiple results this time [and because I love showing off cool PowerShell code] I used this instead.
$ServerList = dir -recurse SQLSERVER:\SQLRegistration\'Database Engine Server Group'\ | where {$_.Mode -ne "d"}            

foreach ($RegisteredSQLs in $ServerList )
{
$S++;
$dt+=invoke-sqlcmd2 -ServerInstance $RegisteredSQLs.ServerName -database master -Query "
    (SELECT COUNT(*) AS Cores FROM sys.dm_os_schedulers WHERE status = 'VISIBLE ONLINE') AS os,
    (SELECT COUNT(*) AS Files FROM tempdb.sys.database_files WHERE type_desc = 'ROWS') AS df" -As 'DataTable'
}            

$MultipleResults = $dt | ConvertTo-Html -Property Instance, Cores, Files | Out-String;            

Send-MailMessage -To paul@SQLskills.com `
 -Subject "tempdb Survey Results" `
 –From YourEmailAddress@GoesHere.com `
 -SmtpServer YourSMTPServerGoesHere `
 -Body $MultipleResults -BodyAsHtml

Hopefully this will help you email query results to your heart’s content :-)   Big thanks to TJay Belt ( blog | @TJayBelt ) for pointing out this request on the #SQLHelp hotline to me.  I’ve done this tons of times myself and I LOVE that anyone can walk up with a question and when people don’t have the answer they still do what they can to help them out right away.  I less than three community!!

Please Note:

DO NOT SPAM Paul Randal! You should probably try emailing this to yourself a time or two before you decide to send it to him.

I’m using Chad Miller’s (Blog|Twitter) invoke-sqlcmd2 to output the results as a data table (you’ll need that).

Finally a friendly reminder that unlike SQL Server, PowerShell persists variables so if you run this multiple times you’ll want to clear out the $dt variable like this: $dt=$null.

Finding SQL Servers with PowerShell

image Have you ever clicked a drop-down to connect to one of your databases and noticed an instance that you don’t remember setting up? Or maybe a server that was recently setup for some new application in your organization, that no one mentioned it needing SQL, but you come back from your day off and notice that server is now one of your available SQL Servers? If your office is like mine those things happen all too often.

There are several different methods to finding out just how many SQL Servers are running on your “network” right now. Each method has pros and cons. But the biggest problem that I run into is: ‘what is defined as the network?’ Is it just the network of computers at your office? Does it include servers at your collocation facility? What if you have a completely separate domain for Development?

The first method I’m going to point out to you is really easy to use but it’s results vary depending on your network rights and where you run it from, but, it still can find machines that you didn’t even know about so lets have a look. Wait, why would I start out with an example that’s so imperfect? Because this method uses the same .Net components that are used to generate the list of servers you see when you click on the “<Browse for more>” option in the drop down of the SSMS connection window*. This means that you’ll see a list that you recognize (probably). Fire up the ISE and kick off this command:

[System.Data.Sql.SqlDataSourceEnumerator]::Instance.GetDataSources()

Now if you’re just on you laptop or sitting at home or something you’ll probably get a nice short list like this: image But if you’re at work, you’ll get back a much longer list; maybe even longer than you expected :-)

Heck how many servers just came back anyways! The answer to that question is really easy, just pipe the output of the command to Measure-Object and find out like this:

[System.Data.Sql.SqlDataSourceEnumerator]::Instance.GetDataSources() | Measure-Object

and you’ll get some output like this:

image Now like I said earlier, these results are going to vary depending on where you run the command so here’s what I recommend. Run this command from your desk. Then try it from a machine that is on a different network segment that you’re usually on – like a Dev domain. Then go home, VPN in and run the command, see how many you get back now.

OK that’s great but with all of these variances can I do anything useful with this example? Sure you can. Take your results and put them in a table. First build a simple table to use:

CREATE TABLE FoundSQLServers (
ServerName VARCHAR(128),
InstanceName VARCHAR(128),
IsClustered VARCHAR(3),
VersionNumber VARCHAR(64)
)

Then build some insert statements off of the results like this:

$SQL = [System.Data.Sql.SqlDataSourceEnumerator]::Instance.GetDataSources() | ` foreach {
"INSERT INTO dbo.FoundSQLServers VALUES ('$($_.ServerName)', '$($_.InstanceName)', '$($_.IsClustered)', '$($_.Version)')" ` >> C:\Temp\INSERTFoundSQLServers.sql
        }

To open up the file that was just created in Management Studio just run this

Ssms.exe C:\Temp\INSERTFoundSQLServers.sql

…and you should get some nice insert statements for that table like this:

INSERT INTO dbo.FoundSQLServers VALUES ('WIN7ULT', 'KILIMANJARO', 'No', '10.50.1600.1')

Go ahead and insert those rows into your table, maybe even give the table a little bit different name like: FoundSQLsFromVPN or FoundSQLsFromDev. Run some queries to compare the results you get from different network segments; see which servers we found both at home (through VPN) and at work from your desk; and more importantly which ones are only found from one of those locations. We’ll take a look at a couple of different methods I’ve learned about in future posts but I wanted to get you started with finding out how well this method finds your servers and knowing how your network location can affect it. Just in case you’ve recently started a new job or something ;-)

Special Thanks: I just wanted to take a moment to thank Grant Fritchey ( blog | twitter ) for doing a tech-check on this post and helping convey my points a little more concisely.

* Small Disclaimer: I was told that it’s the same .Net component used by applications like SSMS but since I don’t work at Microsoft and I’m not a developer I wouldn’t even know where to start to verify this but the list produced has always been very similar or down-right identical.