Tag: sql server

  • Quick Tips–SSMS Select a vertical block

    I saw this years ago in a presentation from Aaron Bertrand. At the time I thought it was super cool and I’d use it all the time, but I haven’t found many uses. However since I needed to do this recently, this helped.

    Imagine that you have this:

    blockselect_a

    A normal select statement. Perhaps you’ve qualified columns with SQL Prompt, or you’ve used some tool to enter this (or you’re a typing masochist). Now you add an alias for the column because you don’t want to type the full name everywhere. That causes SSMS to complain.

    blockselect_b

    You can’t run this because once you use an alias, you need to use it elsewhere. The full table name isn’t valid anymore.

    Now you could do a search and replace (CTRL+H), but that presents other problems, not the least of which is replacing the table in the FROM name. Unless you want to go through and approve or deny every replacement. You could also edit Person to “p” on each line manually.

    Hey, this is programming, we don’t do things over and over when we can avoid them.

    Enter Block Select

    If you place your cursor here, shown with the arrow as my capture tool missed it.

    blockselect_c

    Now I can click ALT+Shift and hold them down while I move my cursor to the lower right of the block I want to select. In this case, it’s between the “n” and period on the last line of the column list, above the FROM clause. Look at the image below.

    blockselect_d

    I’ve now selected a block, and I can hit delete. This gives me:

    blockselect_e

    Notice that my selection is a thin cursor still visible. I can actually type here. Imagine I typed “sn” now. This is what I’d get.

    blockselect_f

    I fixed the alias before I shot this, and once I moved the cursor, I lost my selection, but a simple ALT+Shift, lets me highlight, select, and type in a vertical block.

    Handy when trying to correct a number of items on separate lines.

  • Patching Problems

    I applied the Windows 8.1 update a few weeks ago and had some issues with my machine. Windows was fine, but I lost my SQL Server service. A few other users, including some of the SQLServerCentral community also had issues and sent me ideas, but their fixes didn’t work for me. That was OK because the problems gave me a chance to use PoSh to solve a real problem. I’ll be blogging about that in the next week.

    However the 8.1 update has caused lots of issues, and Microsoft is acknowledging these problems. That’s good, but the process gives me pause, and to a large extent, I think this makes more and more people suspect about all of Microsoft’s patching processes. I bet there are companies that feel even more justified in waiting for SP1 for SQL Server 2014 before upgrading, even though there is a chance that the patch itself will cause problems.

    This is one reason I’ve been hesitant to remain current with Cumulative Updates (CUs). Microsoft doesn’t stand behind them, with the text on each CU page that users should only apply the patch if they are experiencing specific problems. Otherwise users are told to wait for the next Service Pack, which seem to be coming less and less often.

    Any patch can cause issues, and I certainly don’t like the idea of automatic updates always being applied because if there are issues, they can become much more widespread than controlled updates. There is also the issue of vendor responsiveness. Microsoft has pushed out patches that caused issues, and while they’ve try to fix issues quickly, I don’t want to have all of my desktops, or all of my SQL Servers, down because of a bad patch.

    I don’t know how we patch in a more effective manner, but I do know that I want to have some control over updates as an end user, and I also want ways to remove patches. Moving to the app model of always applying patches over patches, and never rolling back seems to be a step in the wrong direction.

    PS – If you want better servicing for SQL Server, vote for final service packs for products still under support.

    Steve Jones

    The Voice of the DBA Podcast

    Listen to the MP3 Audio ( 2.8MB) podcast or subscribe to the feed at iTunes and LibSyn. feed

    The Voice of the DBA podcast features music by Everyday Jones. No relation, but I stumbled on to them and really like the music. Support this great duo at www.everydayjones.com.

  • Attaching All Databases with PowerShell–Checking All Databases

    I wrote a PowerShell script recently to actually accomplish a task I that I needed. What’s more, this was the first time I thought that Powershell might prove more useful than other methods. This series looks at my script, and this part examines the first part that I wrote.

    I wrote an overview of this process, and then a script to loop through files. The next step is to connect to a SQL Server and loop through databases. I’ll also compare these against the MDF file names.

    The first step is to connect to a database. First, I need to add a variable (eventually a parameter) that will hold the name of my instance.

    $instance = ‘Tiny’

    With this, I need to now open a SQL Server connection. I start with some assemblies I need. I saw a post that noted I need these assemblies. I’m not sure if I need them all, but this is where I started.

    [System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SqlServer.SMO”) | Out-Null
    [System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SqlServer.SmoExtended”) | Out-Null
    [System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SqlServer.ConnectionInfo”) | Out-Null
    [System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SqlServer.SmoEnum”) | Out-Null

    The next step is to create a server object and connect. Note that as I add this code, I’ll run F5 to be sure things still work.

    $server = New-Object (“Microsoft.SqlServer.Management.Smo.Server”) $instance

    That works fine, and now I need to see if I can get information from the server.

    if ($debug -eq 2
    {
    “Database List”
    “————-”
    foreach($sqlDatabase in $Server.databases)
    { write-host “DB:” $sqlDatabase.name
    }
    #end debug
    }

    I add this right after the connection so that I get a list of databases. I use a new debug value so that I don’t see all files. What I expect is a list of databases, and then a list of mdf files (from the previous article).

    This works by setting a variable to each of the items in the databases collection of the SQL Server instance. I then write out the name. When I do this, I see:

    attach_k

    Success!

    Now I want to alter this a bit more. I want to move this loop inside of the file loop. My plan is to take each file and use that to loop through each of the databases for a matching name.

    However I’m not sure that a name match here is enough. What I want to note is if any of these MDF files are being used by SQL Server. Meaning that the MDF file is being used by one of the databases. To do that, I need to find the file and path of each database mdf file.

    I do this by looping through each filegroup with this code. Note that I only worry about default filegroups. I’m torn on that, but it works for me.

    $sqlfg = $sqlDatabase.FileGroups
    foreach ($fg in $sqlfg| Where-Object {$_.ISDefault -eq $true})

    Once I have this, I sub-loop inside this to check each of the files.

    foreach ($dbfile in $fg.files | Where-Object {$_.ISPrimaryFile -eq $true} )

    In here, I go through the files, pipe those to the Where-Object command and look for a property of ISPrimaryFile set to true. The result of this is run through the foreach loop. This gives me this code:

    # loop through each  of the databases
    foreach($sqlDatabase in $Server.databases)
    {

        $sqlfg = $sqlDatabase.FileGroups
    foreach ($fg in $sqlfg | Where-Object {$_.ISDefault -eq $true})
    {
    foreach ($dbfile in $fg.files | Where-Object {$_.ISPrimaryFile -eq $true} )
    {

           if ($debug -eq 4)
    {
    write-host “DB MDF File: ”  $file.name
    #end debug
    }

          #end foreach db file
    }
    #end foreach filegroup
    }

       # end foreach
    }

    and this result

    attach_l

    That seems funny until you think about it. In this case, I’m taking the file and checking against each database, which means that I’m getting a loop inside a loop. Not the most efficient, but when this runs, it will be attaching these databases ones, so this should be OK.

    What I want to do now is test if I get a match of the file. To do that, I need to get the full path. I’ll check to the FullName property to get the path and file. I then compare that to my mdf file with. Now I add an IF statement below my database loop.

    if ($file.FullName -eq $dbfile.FileName)
    {
    if ($debug -eq 5)
    {
    write-host “Match ” $file.FullName ” = ” $dbfile.FileName
    #end if
    }
    #end if
    }

    That gives me (with the proper debug value:

    attach_m

    I can see my files (the first value) matching the file for my database (second value).

    That concludes this post. At this point, I can tell what matches, The next step is to track those files that don’t match, and those will be the ones I attach. We’ll tackle that in the next post.

  • Attaching All Databases with PowerShell–Finding My MDF Files

    I wrote a PowerShell script recently to actually accomplish a task I that I needed. What’s more, this was the first time I thought that Powershell might prove more useful than other methods. This series looks at my script, and this part examines the first part that I wrote.

    The overview contains information about my strategy and breakdown, and this post looks at the first item.

    When I decided I was going to use Powershell for this task, the first thing I decided to do was find all the MDF files in my folder. When I examined my folder, I saw lots of files.

    attach_c

    Actually, my instance had no files, but I copied over all my mdf/ldf files (apart from system databases) from my original install to the \Data folder for my new instance. I had created these databases for various tests and experiments, and as such, they tended to use the default naming from SQL Server. This meant:

    • The database name was used as the mdf file, i.e. the Baseball database has Baseball.mdf as the file.
    • The log file is the database name with _log.ldf. As in Baseball_log.ldf.

    To start the script, I began by noting I’d need some parameters for the script, as in the folder where the data was stored. I decided to start with a variable, which I can then turn into a parameter.

    $folder = ‘D:\mssqlserver\MSSQL11.MSSQLSERVER\MSSQL\DATA’
    $debug = 0

    I include a “debug” variable that I can use to print out information if needed.

    I started with the  Get-ChildItem command using the folder. I can use this in a foreach loop to run through all the child items.

    # loop through each  of the file
    foreach ($file in Get-ChildItem $folder)
    {

    # end for loop of files
    }

    Note that when I build these loops, I close the brackets first, and include a comment that helps me figure out where this item ends. Before I go further, I decided to start outputting information. I added a debug statement.

    # loop through each  of the file
    foreach ($file in Get-ChildItem $folder)
    {
    #Debug
    if ($debug -eq 1)
    {
    write-host $file.name
    #end debug
    }

    # end for loop of files
    }

    This will output all the files in the folder. I can change the debug value to 1 and then I’ll get this output:

    attach_g

    I see all my .mdf and .ldf files, along with my Filestream storage folders. Now I need to limit things to a specific type of file.

    There’s an Extension property for the items in a folder that I can use. I’ll add that.

    if ($file.Extension -eq ‘.mdf’)
    {
    if ($debug -eq 1)
    {
    write-host $file.name
    #end debug
    }

    # end if
    }

    When I run this, I get this output, and immediately see a problem.

    attach_h

    My output runs together. I need to differentiate which log output is being printed. I do that with a message before each file name.

    write-host “MDF Files: ” + $file.name

    With this added (and customized) for each debug message, I get this:

    attach_i

    That gets me the list of MDF files. If I turn off debugging, and add just a print, I see just my MDF files.

    attach_j

    That’s a good loop. I’m sure there are easier and shorter ways to do this, but this works well, and it gives me flexibility if I’d like to change to another extension.

    This is also the basis of moving forward, where I’ll need to connect to SQL Server and check this list of files against the databases on the server.