Cómo Cambiar el Propietario de Una Base de Datos

PROBLEMA: Tengo base de datos donde el propietario no es “sa”, cómo puedo cambiar el propietario de varias bases de datos a “sa” de una forma dinámica.

SOLUCION: Yo utilizo el cmdlet Get-SqlDatabase del módulo SqlServer para capturar las bases de datos de una instancia de SQL Server. Entonces hago una búsqueda en el objeto generado por el cmdlet Get-SqlDatabase para encontrar las bases de datos donde la propiedad “.owner” no es “sa”. De ahi, ejecuto el método “.SetOwner” y el “.Alter” por cada una de las bases de datos encontradas para asignar el nuevo propietario “sa”.

Get-SqlDatabase -ServerInstance 'TUIRA' `
| Where {$_.Owner -ne "sa"} `
| foreach {$_.SetOwner("sa"); $_.Alter()}

En Inglés

Change Database Ownership

PROBLEM: Database ownership is set to the user who created or restored the database and I want to change it to “SA”.

SOLUTION: I use the Get-SqlDatabase cmdlet from SqlServer module to capture the list of databases from the SQL instance. I then pipe and search for databases where the “.owner” property is not “sa”. Then pipe the database object to change the “.owner” property to “sa” by invoking the methods “.SetOwner” and “.Alter”.

Get-SqlDatabase -ServerInstance "TUIRA" `
| WHERE {$_.owner -ne 'sa'} `
| foreach {$_.SetOwner('sa'); $_.Alter()}

In Spanish

How to Copy All Tables Definition with PowerShell

PROBLEM: You need to copy the table definition for all tables in a database between two SQL servers.

SOLUTION: One of the requirements is to use PowerShell and I will use it in combination with SQLPSX. Yes, I will use SQLPSX again and you probably have noticed I use it in all my PowerShell scripts that access MS SQL Server –I’m a fan, what else can I say.

There are a few highlighted lines of code I want to mention because I had a bit of trouble while scripting tables with dependencies on user defined data types and partitioned tables. Line 5 and 6 are string variables assigments for the target server and database. On line 13, I added the scripting option “NoFileGroup” because the source database was set up using multiple filegroups and the script failed when these file groups were not available on the target server; the target server in this example will have a single file group. On line 15, I added the “WithDependencies” which helped with the creation of partitioned table functions and schemas. And on line 16, I used the “IncludeIfNotExists” in order to avoid errors if the database objects already exists.

CLEAR 

$sSRCServer = "TUIRADEVELOPMENT" 
$sSRCDatabase = "AdventureWorks" 
$sTRGServer = "TUIRA" 
$sTRGDatabase = "AdventureWorks" 

$oSO = New-SqlScriptingOptions 
$oSO.Permissions = $false 
$oSO.ClusteredIndexes = $true 
$oSO.Indexes = $true 
$oSO.Triggers = $true 
$oSO.NoFileGroup = $true
$oSO.NonClusteredIndexes = $true 
$oSO.WithDependencies = $true
$oSO.IncludeIfNotExists = $true

$oTables = Get-SqlDatabase $sSRCServer $sSRCDatabase|Get-SqlTable 

foreach ($oTable in $oTables){  
    $oT = $oTable.Name  
    $oS = $oTable.Schema  
    $DDL = Get-SqlScripter $oTable -scriptingOptions $oSO 
    invoke-sqlcmd -ServerInstance "$sTRGServer" -Database "$sTRGDatabase" `
          -Query "$DDL" 
}

This solution can easily be converted to a function with optional parameters that map to scripting options. The target variables for server and/or database could hold arrays for copying the tables definition to multiple servers. A form could also be developed using WPF to make it user friendly. What do you think?

Related Links

En Español

Cómo Copiar el Esquema de Tablas Utilizando PowerShell

PROBLEMA: Necesitas copiar el esquema de tablas de un servidor Microsoft SQL a otro servidor SQL.

SOLUCION: Para resolver este problema utilizo PowerShell y el SQLPSX. Si sigues este blog, podrás notar que utilizo la extensión SQLPSX de SQL para PowerShell en todos mis PowerShell scripts de base de datos.

Hay algunas líneas en el código adjunto las cuales hago resaltar porque al escribir el script tuve ciertas dificultades ya que existen dependencias entre las tablas y tipos definidos por el usuario además de la existencia de tablas con particiones. La línea 5 y 6 son para asignar el nombre del servidor y base de datos de destino a variables. En la línea 13 agrego la opción de scripting “NoFileGroup” ya que la base de datos de origen está configurada con múltiples grupos de archivos (filegroups) y mi script termino en error cuando estos filegroups no se encontraron en la base de datos de destino. En este ejemplo, la base de datos de destino cuenta con un solo filegroup. En la línea 15 añado la opción de scripting “WithDependencies” para ayudar con la creación de funciones y esquemas de particiones de tablas. Finalmente en la línea 16, incluyo la opción de scripting “IncludeIfNotExists” para verificar que los objetos de base de datos a crear no existan en la base de datos de destino y así evitar los errores de creación.

CLEAR

$sSRCServer = "TUIRADEVELOPMENT"
$sSRCDatabase = "AdventureWorks"
$sTRGServer = "TUIRA"
$sTRGDatabase = "AdventureWorks"

$oSO = New-SqlScriptingOptions
$oSO.Permissions = $false
$oSO.ClusteredIndexes = $true
$oSO.Indexes = $true
$oSO.Triggers = $true
$oSO.NoFileGroup = $true
$oSO.NonClusteredIndexes = $true
$oSO.WithDependencies = $true
$oSO.IncludeIfNotExists = $true

$oTables = Get-SqlDatabase $sSRCServer $sSRCDatabase|Get-SqlTable

foreach ($oTable in $oTables){
    $oT = $oTable.Name
    $oS = $oTable.Schema
    $DDL = Get-SqlScripter $oTable -scriptingOptions $oSO
    invoke-sqlcmd -ServerInstance "$sTRGServer" -Database "$sTRGDatabase" `
         -Query "$DDL"
}

Esta solución puede ser convertida a una función de PowerShell y utilizar parámetros para vincular las opciones de scripting. Las variables de servidor y base de datos de destino pueden contener una matriz (array) con nombres de servidores y base de datos para así copiar el esquema de tablas a múltiples servidores. Un formulario web puede ser creado utilizando WPF para facilitar el uso de esta solución. ¿Qué te parece esta solución?

Artículos Relacionados

In English

How to Script All Stored Procedures From a Database with PowerShell

PROBLEM: You need to script all stored procedures from a database.  Each stored procedure needs to be on its own file so you can add them to a source control repository.

SOLUTION: The solution here is a variation of what we did for “How to Script All Tables From a Database with PowerShell”.  The only difference in this solution is the use of the Get-SQLStoredProcedure function from the SQL Server PowerShell Extensions (SQLPSX).

CLEAR
$sServer = "TUIRA"
$sDatabase = "AdventureWorks"

$oSO = New-SqlScriptingOptions
$oSO.Permissions = $true
$oProcs = Get-SqlDatabase $sServer $sDatabase|Get-SqlStoredProcedure

foreach ($oProc in $oProcs){
    $oP = $oProc.Name
    $oS = $oProc.Schema
    $DDL = Get-SqlScripter $oProc -scriptingOptions $oSO
    Out-File -FilePath "E:AdventureWorks$oS`_$oP.sql" -InputObject $DDL
}
Related Links
  • How to Script All Tables From a Database with PowerShell.
  • How to Script All Tables From a Database with PowerShell

    PROBLEM: You need to script all the tables from a database.  Each table needs to be on its own file so they can be added to a source control repository.

    SOLUTION: The use of SQL Server PowerShell Extensions (SQLPSX) facilitates the solution I’m about to show. The first example is a straight to the point, just DDL for the table without indexes, permissions, or any other scripting options. I used the Get-SQLDatabase, Get-SQLTable and Get-SQLScripter functions from SQLPSX to script out each table from the database into their own file.

    CLEAR
    $sServer = "TUIRA" 
    $sDatabase = "AdventureWorks"
    $oTables = Get-SqlDatabase $sServer $sDatabase|Get-SqlTable
    
    foreach ($oTable in $oTables){
        $oT = $oTable.Name
        $oS = $oTable.Schema
        $DDL = Get-SqlScripter $oTable
        Out-File -FilePath "E:AdventureWorks$oS`_$oT.sql" `
            -InputObject $DDL
    }

    Next, I extended the initial script by adding a reference to the SMO scripting class SQLScriptionOptions.  Now, I can script all primary key, indexes, foreign keys, default values and more.  Look for “ScriptingOptions Members” in Books Online or the Internet and you will find under public properties all the possible things you can include or exclude from your DDL scripts.

    Here, I chose to NOT include permissions and to include the clustered index, regular indexes, triggers, and schemas.

    CLEAR
    $sServer = "TUIRA"
    $sDatabase = "AdventureWorks"
    
    $oSO = New-SqlScriptingOptions
    $oSO.Permissions = $false
    $oSO.ClusteredIndexes = $true
    $oSO.Indexes = $true
    $oSO.Triggers = $true
    $oSO.NonClusteredIndexes = $true
    
    $oTables = Get-SqlDatabase $sServer $sDatabase|Get-SqlTable
    
    foreach ($oTable in $oTables){
        $oT = $oTable.Name
        $oS = $oTable.Schema
        $DDL = Get-SqlScripter $oTable -scriptingOptions $oSO
        Out-File -FilePath "E:AdventureWorks$oS`_$oT.sql" `
            -InputObject $DDL
    }


    Monitoring MS SQL Jobs with PowerShell

    PROBLEM: You manage many MS SQL servers and need an easy way to review jobs that have failed.

    SOLUTION: I will show you one way to accomplish this task with results displaying on the screen or to a file. To make your life easier, I recommend you download & install PowerGUI from Quest Software. This application comes with a script editor that will enhance your PowerShell development experience.

    Go ahead and open a new session of PowerShell. You can type or copy and paste the code from our initial three lines of code. We will start by loading the SMO assembly & creating an instance of the server object. On the third and final line of code, we get a collection of all jobs by accessing the SQL Server agent on the server. We then pipe the resulting object and look for all jobs which are enabled that have failed.

    [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")|out-null
    $srv=New-Object "Microsoft.SqlServer.Management.Smo.Server" "TUIRA"
    $srv.jobserver.jobs|where-object {$_.IsEnabled -eq $TRUE -and `
        $_.LastRunOutcome -eq "Failed"
    }

    You will notice the result not being in a desirable format, especially when you have many jobs. We will use the information from one of the jobs to pick the specific properties we want in our report and display them in a table format. Lets pick the Parent, Category, Description, LastRunDate, LastRunOutcome, & Name properties for our next result.
    On your PS session screen, hit the up key and you should get the last line of commands we executed. Hit the left arrow key to modify the command as follow

    $srv.jobserver.jobs|where-object {$_.isenabled -eq $TRUE}|Format-Table `
        Parent, Category, Name, LastRunDate, LastRunOutcome, Description `
        -Autosize

    Now we have a result we can save to a file or print. But before doing that, we’ll expand this script to retrieve the jobs from multiples servers. Lets go ahead and open a Notepad session and enter the name of a few MS SQL servers you manage, one name per line, and save it with the file name serverlist.txt. I saved mine in C: for simplicity. Now, we just need to enclose our previously executed commands in a loop.

    [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")|out-null
    foreach($svr in get-content C:serverlist_prd.txt) {
        $srv=New-Object "Microsoft.SqlServer.Management.Smo.Server" "$svr"
        $srv.jobserver.jobs|where-object {$_.isenabled -eq $TRUE}| `
            Format-Table Parent, Category, Name, LastRunDate, `
            LastRunOutcome, Description -Autosize
    }

    I find this looping syntax very helpful whenever I need to execute code against multiple servers. The result from this modified version of the original code will leave a blank space between each server or iteration of the code. We’ll solve that with a variable in the next and final version of the script which includes the code to save the report to a file.

    CLEAR
    Set-Content -Path "C:TempMonitorJobs_LowerEnvironments.txt" -Value " "
    [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")|out-null
    
    foreach($svr in get-content C:tempserverlist.txt) {
        $srv=New-Object "Microsoft.SqlServer.Management.Smo.Server" "$svr"
        $a += $srv.jobserver.jobs
    }
    
    $a|where-object {$_.isenabled -eq $TRUE -and $_.LastRunOutcome `
        -eq "Failed"}|Sort-Object -Descending LastRunDate| `
        Format-Table Parent, Category, Name, LastRunDate, `
        LastRunOutcome, Description -Autosize|Out-File `
        -FilePath C:TempMonitorJobs.txt -Append -Encoding ASCII


    How to Script Database Tables with PowerShell

    PROBLEM: I need an easy way to script out all the tables from a database in MS SQL 2000 and above.

    SOLUTION: Like anything in programming, there are a thousand ways to skin a cat. Here, I’ll show you the simplest way I found to meet this request.

    Go ahead and open a new session of PowerShell. You can type or copy and paste in your PS session window all the code in this solution. We will start by loading the SMO assembly.

    [system.reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO")|out-null

    Next, we’ll create an instance of SMO server object, database object, and scripter object

    $srv = new-object "Microsoft.SqlServer.Management.SMO.Server" "."
    $db = new-object("Microsoft.SqlServer.Management.SMO.Database")
    $scr = new-object("Microsoft.SqlServer.Management.SMO.Scripter")

    We then assign the instance of MS SQL Server we want the scripter to use. We wrap it up by calling the Script() method with an SQL SMO collection of objects to be script out –in this case, all tables.

    $scr.Server = $srv
    $scr.Script($srv.Databases["AdventureWorks"].tables)

    That’s it! The simplest way to script out all tables from a database with PowerShell. In a future article, I’ll expand from this solution by writing a script that will take parameters, use SMO Scripter Options, filter tables to be script out, and then some.

    Generate T-SQL Script for a List of Views

    USE:

    CLEAR 
    
    $sSRCServer = "TUIRA"
    $sSRCDatabase = "AdventureWorks"
    
    $oSO = New-SqlScriptingOptions
    $oSO.Permissions = $true
    $oSO.IncludeIfNotExists = $true
    
    $a = Get-Content "C:tempviewlist.txt"
    
    foreach ($o in $a) {
    	Get-SqlDatabase $sSRCServer $sSRCDatabase|Get-SqlView -Name $o| `
                         Get-SqlScripter -scriptingOptions $oSO
    	WRITE("GO `n`n`n")
    }

     

    Script Out All Indexes and Primary Keys from a Database

    USE: To generate T-SQL code for all indexes and PK constraints from a database.

    CLEAR 
    
    $sSRCServer = "TPW520"
    $sSRCDatabase = "iSQLPS" 
    
    $oSO = New-SqlScriptingOptions
    $oSO.ClusteredIndexes = $true
    $oSO.Indexes = $true
    $oSO.NonClusteredIndexes = $true
    $oSO.IncludeIfNotExists = $true
    
    $oTables = Get-SqlDatabase $sSRCServer $sSRCDatabase|Get-SqlTable
    
    foreach ($oTable in $oTables){
        $oT = $oTable.Indexes
        
    	foreach ($oIndex in $oT) {
    		$DDL = Get-SqlScripter $oIndex -scriptingOptions $oSO
    	    
    		"$DDL `nGO `n`n"
    	}
    }