{"id":53643,"date":"2009-05-29T15:28:00","date_gmt":"2009-05-29T15:28:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/05\/29\/hey-scripting-guy-how-can-i-use-windows-powershell-to-run-daily-checks-on-my-sql-server-2008-servers\/"},"modified":"2009-05-29T15:28:00","modified_gmt":"2009-05-29T15:28:00","slug":"hey-scripting-guy-how-can-i-use-windows-powershell-to-run-daily-checks-on-my-sql-server-2008-servers","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-use-windows-powershell-to-run-daily-checks-on-my-sql-server-2008-servers\/","title":{"rendered":"Hey, Scripting Guy! How Can I Use Windows PowerShell to Run Daily Checks on My SQL Server 2008 Servers?"},"content":{"rendered":"<p><H2><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"> <\/H2>\n<P>Hey, Scripting Guy! I have several items I have to check daily on my SQL 2008 servers. I currently have some VBScripts that do many of my tasks, but there are some new things I want to do. I figure that Windows PowerShell would be easier. Do you have any pointers?<BR><BR>&#8211; SC<\/P><IMG border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\"> \n<P>Hi SC,<\/P>\n<P>It is becoming late as Ed continues plowing through almost 200 e-mail messages that piled up during the two weeks leading up to Tech\u00b7Ed 2009 and during the week of Tech\u00b7Ed 2009. He is about ready to go swimming, expecting that the cool water will cool his overheated brain if nothing else.<\/P>\n<TABLE id=\"EXC\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\">This week we are examining using Windows PowerShell to work with SQL Server 2008. The <A href=\"http:\/\/www.microsoft.com\/sqlserver\/2008\/en\/us\/default.aspx\" target=\"_blank\">SQL Server 2008 product page<\/A> is an excellent starting point. From here, you can download trial versions of the real product and free versions of SQL Server 2008 Express Edition. The <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/db.mspx\" target=\"_blank\">Script Center Database Hub<\/A> is a great place to start examining scripting and working with databases.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Because Ed does not consider himself to be a SQL Server 2008 guru, we decided to pass this question off to Buck Woody, SQL Server Technical Specialist for the Microsoft Corporation. He is a former Program Manager on the SQL Server team and the author of seven books about SQL Server. (Compared to Buck, Ed cannot even spell SQL. Oh, wait, he just did.)<\/P>\n<P>&nbsp;<\/P>\n<P>In the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/all.mspx\" target=\"_blank\">last three installments<\/A>, we explained what Windows PowerShell is and how a database administrator (DBA) can use it. <\/P>\n<P>Last time we showed you the new Windows PowerShell Provider for SQL Server 2008. It\u2019s the \u201cmini-shell\u201d that makes using Windows PowerShell with SQL Server instances even easier. We tooled around a bit inside the structure that this provider has, learned about the objects that it exposes and how you can get and set properties, and even ran several commands that the provider includes. But now it is time to really put this thing to work. We will see how you can use Windows PowerShell to perform some useful tasks, working through some practical applications.<\/P>\n<P>Let us take everything that you have learned to this point and put it together in a single command. We will create a variable, use a standard command, send the results to more commands by using a pipeline operator, and do it all inside the SQL Server 2008 Windows PowerShell provider.<\/P>\n<P>The first thing we have to do is obtain the directory of all the databases on an instance. Substituting the server name in the <B>serverName<\/B> part of this string and instance name (use <B>default<\/B> if it is the default instance) in the <B>instanceName<\/B> part of this string, type this command in the Windows PowerShell for SQL Server provider:<\/P><PRE class=\"codeSample\">DIR &#8220;SQLSERVER:\\SQL\\serverName\\instanceName\\Databases&#8221; \n<\/PRE>\n<P>Now let us add in a <B>where-Object<\/B> Windows PowerShell cmdlet to locate only those databases for which the backup is greater than a day:<\/P><PRE class=\"codeSample\">DIR &#8220;SQLSERVER:\\SQL\\serverName\\instanceName\\Databases&#8221; |\nwhere-Object {((get-Date)-($_.LastBackupDate)).days -gt 1} \n<\/PRE>\n<P>You can see that the <B>Where-Object<\/B><I><\/I>cmdlet is followed by a set of braces. This encloses what we want to do with the collection of items to the results of the <B>dir <\/B>command. We are just asking for the <B>LastBackupDate<\/B> property on each item (remember that we can see those properties by using the <B>Get-Member <\/B>cmdlet). The <B>$_<\/B><I><\/I>part stands in for each database, one at a time. The interesting part is that we are enclosing that whole string with another cmdlet that can read dates\u2014<B>G<\/B><B>et-Date<\/B><B>.<\/B> We ask for a property of that cmdlet (the <B>days<\/B> part), and the whole thing is enclosed by that <B>Where-Object<\/B> cmdlet. So in plain old English, here is what we are really saying:<\/P>\n<P><I>\u201cSee all those databases? Show me the ones that have a property of <\/I><B>LastBackupDate<\/B> greater than one day.\u201d<\/P>\n<P>Even though this shows us the databases, it does not show the information that we want. No worries. We will just pipe that out to another command that selects the objects and shows certain properties. The name of this mysterious cmdlet is <B>Select-Object<\/B>:<\/P><PRE class=\"codeSample\">DIR &#8220;SQLSERVER:\\SQL\\serverName\\instanceName\\Databases&#8221; | \nwhere-Object {((get-Date)-($_.LastBackupDate)).days -gt 1}  | \nsort-Object -Property LastBackupDate | \nselect-Object Name, RecoveryModel, LastBackupDate\n<\/PRE>\n<P>Not bad. What else can we do? Do you remember a couple of articles back when we used the Server Management Objects (SMO) Library to script out certain objects? With the Windows PowerShell provider for SQL Server, it is even easier. It does not even need much explanation, although it could do with a warning.<\/P>\n<P>Because you are in the SQL Server PowerShell provider, each SMO library object class is now a directory, exactly like the databases we just used. Now we can type <B>dir<\/B> to gain access to those objects. One <B>dir<\/B> command and we can loop through all the objects it contains. But as the Scripting Guys\u2019 grandmother used to say, &#8220;Just because you <I>can<\/I> do something, does not mean that you <I>should<\/I><I><\/I>do something.&#8221; Scripting is one of those times. If you script out all the tables in a database, you could really take some time and processor cycles on your system. You can do it, of course, but we are just saying that perhaps you might want to take a microsecond and reconsider. <\/P>\n<P>With all those warnings and repeating ourselves that you should be on a test system, here is a simple script to script out all the databases. Not all the objects in them, mind you, but the databases themselves: <\/P><PRE class=\"codeSample\">DIR &#8220;SQLSERVER:\\SQL\\serverName\\instanceName\\Databases&#8221; | \nforEach-object {$_.Script()}\n<\/PRE>\n<P>The same command works for other containers such as tables and views. You could even restrict the tables with that useful <B>Select-Object<\/B> cmdlet to limit the scripting to a certain schema, name, or other property. Oh\u2014you want that to go out to a file? No problem. Just add the <B>Out-File<\/B> cmdlet with another pipeline operator:<\/P><PRE class=\"codeSample\">DIR &#8220;SQLSERVER:\\SQL\\serverName\\instanceName\\Databases&#8221; | \nforEach-object {$_.Script()} | \nout-File \u2013FilePath C:\\temp\\Scripts.sql\n<\/PRE>\n<P>Another way to the SQL provider is to send the script to a .sql file, and then use the script file to make a change to the database object. Run the script again, but change the output file to another name. Then just use the <B>Compare-Object<\/B> cmdlet to see the differences: <B>Get-Help <\/B><B>C<\/B><B>ompare-Object<\/B>.<\/P>\n<P>No problem, we have several ways to do this. The first way is just to use <B>Invoke-Sqlcmd <\/B>cmdlet that the SQL Server provider has built in. Here is a sample. As always, replace the <B>serverName<\/B> and <B>instanceName<\/B> for your system:<\/P><PRE class=\"codeSample\">invoke-Sqlcmd -query &#8220;select @@VERSION&#8221; \u2013ServerInstance serverName\\instanceName\n<\/PRE>\n<P>You must be able to connect to that instance with different credentials? No worries:<\/P><PRE class=\"codeSample\">invoke-Sqlcmd -query &#8220;select @@VERSION&#8221; \u2013ServerInstance serverName\\instanceName `\n\u2013UserName yourUserName \u2013Password yourPassword\n<\/PRE>\n<P>Replace the <B>yourUserName<\/B><I><\/I>part with, you know, you user name and the same for the password. By the way, this works for SQL Server 2005 and even SQL Server 2000 systems, too.<\/P>\n<P>\u201cHey, wait a minute,\u201d we hear you say. \u201cThat is cheating. I want a real drive letter on that other system, exactly as I have it here. I want to browse the objects, do the <B>dir<\/B> thing and all that. Can I do that?\u201d No problemo. We will just make a completely new drive, by using the Windows PowerShell cmdlet called <B>New-PSDrive<\/B>. It makes a new Windows PowerShell drive from any installed provider. It requires a string representing the new drive and the kind of provider you want to use. From there, you add the server name that you want to connect to and there you have it:<\/P><PRE class=\"codeSample\">new-PSDrive &#8220;OtherServer&#8221; -PSProvider SqlServer -Root &#8220;SQLSERVER:\\SQL\\ serverName\\instanceName&#8221;\n<\/PRE>\n<P>Now just type <B>OtherServer<\/B><I>:<\/I> (or whatever you called it) and press ENTER. Voila! You are in the <B>Instance<\/B> folder.Now that you have learned enough to be dangerous, you can really get in there and dig around to think of all kinds of useful scripts for working with your databases. And here is the real beauty of working with Windows PowerShell and SQL Server: Windows PowerShell lets you work with all kinds of objects in addition to the database, such as files, Web pages, and more. In fact, you can manage Windows servers, Microsoft Exchange servers, System Center, and most other Microsoft products with Windows PowerShell. And because Windows PowerShell is based on the .NET Framework, you have access to all those items, too. Who says DBAs can\u2019t learn new tricks?<\/P>\n<P>&nbsp;<\/P>\n<P>Well, SC, thanks for an excellent question to end this week. Buck Woody, you have our sincere appreciation for an entertaining and educational series of SQL Server articles. We are skipping Quick-Hits Friday this week because Monday was a holiday for us, and sometimes even we need to take a holiday. Next week, we take a look back at some of the best content from Scripting Games history. Just to get you all juiced up for this year\u2019s Summer Scripting Games, June 15\u201326. Until then, peace.<\/P>\n<P>&nbsp;<\/P>\n<P><B>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/B><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I have several items I have to check daily on my SQL 2008 servers. I currently have some VBScripts that do many of my tasks, but there are some new things I want to do. I figure that Windows PowerShell would be easier. Do you have any pointers?&#8211; SC Hi SC, It [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[729,146,56,3,176,730,45],"class_list":["post-53643","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-buck-woody","tag-databases","tag-guest-blogger","tag-scripting-guy","tag-sql-server","tag-sql-server-2008","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I have several items I have to check daily on my SQL 2008 servers. I currently have some VBScripts that do many of my tasks, but there are some new things I want to do. I figure that Windows PowerShell would be easier. Do you have any pointers?&#8211; SC Hi SC, It [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/53643","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=53643"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/53643\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=53643"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=53643"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=53643"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}