Utilidades de Sql Server con ADO.NET - Separar y adjuntar una base de datos

Hola ¿Qué tal?...

Continuando con las utilidades de SQL Server con ADO.NET  toca el turno a una nueva funcionalidad que puede ser de gran ayuda al momento de cambiar de nombre a una base de datos de SQL Server.

Esta funcionalidad podrá ser utilizada con bases de datos de SQL Server 2000 y 2005, aunque en ocasiones tendré que especificar si es posible en versiones anteriores a SQL Server 2005 ya que estaré publicando estas utilidades principalmente para funcionar en SQL Server 2005.

Separar y Adjuntar los Archivos de una Base de Datos de SQL Server con T-SQL

Separar una base de datos del servidor es útil en contadas ocasiones, casi siempre es mejor realizar respaldos de las bases de datos, sin embargo hay escenarios en los que la recuperación de bases de datos no es tarea fácil, y esto es porque en un respaldo se guarda la ruta original del archivo ya que está pensada la restauración para ser ejecutada en el mismo servidor donde se realizó el respaldo. En ocasiones cuando se necesita mover una base de datos de un servidor a otro la mejor manera es separando la base de datos, de esta manera los archivos quedan libres y se pueden adjuntar en un nuevo servidor sin mucho problema, el único detalle es que los trabajos programados no se van con la base de datos, ni aún con los respaldos, dado que los trabajos son registrados en las bases de datos de sistema.

Para la tarea de cambiar el nombre de la base de datos nos será útil la capacidad de SQL Server de separar los archivos del servidor, de esta manera, podremos cambiar el nombre del archivo para volverlo a adjuntar, una vez adjuntados será útil realizar el procedimiento que he descrito con anterioridad en este artículo.

Veamos la manera de realizar la separación de la base de datos del servidor utilizando T-SQL:

--Ejecutado de manera directa
EXEC sp_detach_db AdventureWorks--Ejecutad con asiganción explícita
--del parámetro @dbname
EXEC sp_detach_db @dbname=AdventureWorks

Se utiliza el procedimiento almacenado de sistema sp_detach_db, cuyos parámetros son tres, sin embargo es suficiente con el parámetro de base de datos ya que el segundo parámetro es para indicar si se omite la instrucción UPDATE STATISTICS sobre todas las tablas de la base de datos. UPDATE STATISTICS se ejecuta de manera predeterminada sobre todas las tablas de la base de datos antes de separarla si se omite este valor, lo cual es bueno pues deja a la base de datos lista para adjuntarse en otro servidor.

Cuando se separan los archivos de una base de datos estos quedan en el directorio de datos del servidor, este directorio de archivos de bases de datos comúnmente está en:

 %programfiles%\Microsoft SQL Server\MSSQL.1\MSSQL\Data

Esto es para instancias de SQL Server 2005, aunque puede variar según la instancia del servidor donde se esté trabajando, la instancia se identifica por la carpeta MSSQL y el sufijo .n donde n es el número de la instancia.

Continuando con el tema de renombrar la base de datos, separamos la base de datos en cuestión y procederemos a cambiar el nombre de los archivos en congruencia con el nuevo nombre de la base de datos, esto es, que si el archivo se llama AdventureWorks_Data.mdf y el nuevo nombre de la base de datos será NewAdventureWorks, pues la congruencia sería renombrar el archivo a NewAdventureWorks_Data.mdf, de manera similar será con el archivo Log (ldf); así entonces, una vez cambiado el nombre de los archivos procedemos a adjuntaros. En versiones anteriores a SQL Server 2005 se utilizaba el procedimiento almacenado de sistema sp_attach_db, sin embargo, en SQL Server 2005 se utiliza la instrucción CREATE DATABASE para adjuntar una base de datos. En el siguiente ejemplo se muestra cómo adjuntar la base de datos que hemos modificado:

Create Database NewAdventureWorks
on
(FILENAME='C:\Archivos de programa\
                    Microsoft SQL Server\
                    MSSQL.1\MSSQL\Data\NewAdventureWorks_Data.mdf'
),
(
FILENAME='C:\Archivos de programa\
                    Microsoft SQL Server\
                    MSSQL.1\MSSQL\Data\NewAdventureWorks_Log.ldf'
)
For ATTACH

NOTA: la ruta del archivo debe quedar en una sola línea, sin espacios ni saltos de línea, aunque en el ejemplo se muestra con saltos de línea a causa de las limitaciones del ancho de esta publicación, ya que de otra manera causaría un error.

Al cambiar el nombre directamente de los archives nos da la oportunidad de definir el nuevo nombre de la base de datos al adjuntarlos nuevamente, lo único que quedará pendiente será cambiar los nombre de los archivos lógicos, con lo que estará completamente cambiado el nombre de la base de datos. Y digo cambiar completamente el nombre ya que el cambiar el nombre de la base de datos desde el SQL Server Management Studio no aplica los cambios en los archivos lógicos y físicos.

Separar y Adjuntar los Archivos de una Base de Datos de SQL Server con ADO.NET

Ahora nos enfocaremos a escribir los métodos necesarios para separar y adjuntar una base de datos de Sql Server, pero utilizando ADO.NET, para lo cual utilizaremos lo que vimos con T-SQL.

Primeramente crearemos el método que separa la base de datos. El siguiente ejemplo muestra cómo queda este método:

VB.NET

Public Sub DetachDataBase(ByVal DBName As String)
    'Declaramos el SqlCommand que se usará
    'para ejecutar el procedimiento almacenado
    Dim cmd As SqlCommand = _
        New SqlCommand("sp_detach_db")
    'Se establece el tipo de Command que se
    'usará, para este caso StoredProcedure
    cmd.CommandType = CommandType.StoredProcedure
    'Se agrega el parámetro @dbname que se
    'utiliza para identificar la base de datos
    'a separar
    cmd.Parameters.Add("@dbname", _
        SqlDbType.NVarChar, 128).Value = DBName
    'Se asigna la conexión al command
    cmd.Connection = cnn
    Try
        'se abre la conexión
        cnn.Open()
        'se ejecuta el command
        cmd.ExecuteNonQuery()
    Catch ex As SqlException
        'se capturan los mensajes de error
        mMessages = ex.Message
    Finally
        'se cierra la conexión al terminar
        cnn.Close()
    End Try
End
Sub


C#

public void DetachDataBase(string DBName)
{
    //Declaramos el SqlCommand que se usará
    //para ejecutar el procedimiento almacenado
    SqlCommand cmd =
        new SqlCommand("sp_detach_db");
    //Se establece el tipo de Command que se
    //usará, para este caso StoredProcedure
    cmd.CommandType = CommandType.StoredProcedure;
    //Se agrega el parámetro @dbname que se
    //utiliza para identificar la base de datos
    //a separar
    cmd.Parameters.Add("@dbname",
        SqlDbType.NVarChar, 128).Value = DBName;
    //Se asigna la conexión al command
    cmd.Connection = cnn;
    try
    {
        //se abre la conexión
        cnn.Open();
        //se ejecuta el command
        cmd.ExecuteNonQuery();
    }
    catch (SqlException ex)
    {
        //se capturan los mensajes de error
        messages = ex.Message;
    }
    finally
    {
        //se cierra la conexión al terminar
        cnn.Close();
    }
}


Aquí tenemos ya nuestro método para separa la base de datos, habrá que hacer algunas observaciones adicionales, como por ejemplo, el parámetro @dbname que utilizamos en T-SQL para pasar el nombre de la base de datos en el procedimiento almacenado sp_detach_db es del tipo sysname en T-SQL, este tipo es un tipo definido por el usuario en Sql Server, por lo que no podremos utilizarlo directamente, sin embargo tiene una equivalencia con NVarchar(128), por lo que utilizaremos este tipo y longitud en nuestro parámetro, lo cual es equivalente funcionalmente.

Ahora veremos cómo podremos adjuntar los archivos nuevamente. Este método será crucial para el objetivo principal que es cambiar el nombre a la base de datos y es que será el que realmente cambie el nombre de la base de datos ya que al adjuntar los archivos, debemos especificar un nombre en la base de datos, con lo que estaremos definiendo el nombre que nos interesa.

El siguiente ejemplo muestra el método que realizará la tarea de adjuntar la base de datos al servidor:

VB.NET

Public Sub AttachDataBase(ByVal DBName As String, _
        ByVal Files As List(Of String))
    'Se declara el SqlCommand que ejecutará la
    'instrucción
    Dim cmd As SqlCommand = New SqlCommand()
    'Se declara un string donde se construirá
    'la cadena de la instrucción
    Dim strSql As String
    'Se contruye la primera parte de la instrucción
    strSql = String.Format("Create Database {0} on ", DBName)
    'Se agreagan las rutas de archivos que usará
    'la instrucción CREATE DATABASE
    For Each str As String In Files
        strSql &= String.Format("(FILENAME='{0}'),", str)
    Next
    'Se remueve la útlima coma de la cadena
    strSql = strSql.Remove(strSql.Length - 1)
    'Se completa la instrucción
    strSql &= " FOR ATTACH"
    'Se asigna la instrucción al SqlCommand
    cmd.CommandText = strSql
    'Se asigna la conexión al SqlCommand
    cmd.Connection = cnn
    'Se intenta ejecutar el SqlCommand
    Try
        'Se abre la conexión
        cnn.Open()
        'Se ejecuta la instrucción
        cmd.ExecuteNonQuery()
    Catch ex As SqlException
        'Se capturan los mensajes de error
        mMessages = ex.Message
    Finally
        'Se cierra la conexión
        cnn.Close()
    End Try
End
Sub


C#

public void AttachDataBase(String DBName,
    List<string> Files)
{
    //Se declara el SqlCommand que ejecutará la
    //instrucción
    SqlCommand cmd = new SqlCommand();
    //Se declara un string donde se construirá
    //la cadena de la instrucción
    String strSql;
    //Se contruye la primera parte de la instrucción
    strSql = String.Format("Create Database {0} on ", DBName);
    //Se agreagan las rutas de archivos que usará
    //la instrucción CREATE DATABASE
    foreach (String str in Files)
    {
        strSql += String.Format("(FILENAME='{0}'),", str);
    }
    //Se remueve la útlima coma de la cadena
    strSql = strSql.Remove(strSql.Length - 1);
    //Se completa la instrucción
    strSql += " FOR ATTACH";
    //Se asigna la instrucción al SqlCommand
    cmd.CommandText = strSql;
    //Se asigna la conexión al SqlCommand
    cmd.Connection = cnn;
    //Se intenta ejecutar el SqlCommand
    try
    {
        //Se abre la conexión
        cnn.Open();
        //Se ejecuta la instrucción
        cmd.ExecuteNonQuery();
    }
    catch (SqlException ex)
    {
        //Se capturan los mensajes de error
        messages = ex.Message;
    }
    finally
    {
        //Se cierra la conexión
        cnn.Close();
    }
}


Con esto tendremos listo el método para adjuntar la base de datos. Nótese que he usado un parámetro de lista genérica para pasar la ruta de los archivos que se usaran para adjuntar la base de datos. Si no se agrega el archivo Log, SQL Server intentará crear uno nuevo.

Conclusiones

Como hemos visto hasta ahora, realizar la transformación de T-SQL a ADO.NET ha sido completamente sencillo ya que solo hemos tenido que asignar las instrucciones T-SQL al CommandText de nuestra variable de SqlCommand, seguido solo asignamos la conexión, abrimos la conexión y ejecutamos el SqlCommand. Las demás utilidades que estaré publicando, se hacen de la misma manera.

Recuerden que este método está pensado en el diseño original de la clase SqlUtilities que creamos en la primera publicación de la serie el cual está aquí:

http://msmvps.com/blogs/otelis/archive/2007/06/19/utilidades-de-sql-server-con-ado-net-regenerar-campos-identity.aspx

He decidido publicar segmentos más cortos para  mejor asimilación, este es el primer segmento de la serie que terminará en el método que automatiza el cambio de nombre de una base de datos por completo, así que estén pendientes.

Espero que haya sido de utilidad, nos vemos en el próximo post.

Saludos…

Octavio Telis

Published Saturday, June 30, 2007 6:52 AM by Octavio Telis Aynés
Filed under: , , , , ,

Comments

# re: Utilidades de Sql Server con ADO.NET - Separar y adjuntar una base de datos

Wednesday, August 29, 2007 11:55 AM by Fabian

Muy bueno tu blog para aprender .net y sql a la vez :) felicitaciones y gracias por enseñar algo de tecnología a .net newbies como yo =)

# re: Utilidades de Sql Server con ADO.NET - Separar y adjuntar una base de datos

Thursday, December 06, 2007 8:45 AM by Janior Alexander

pero podrias hacer lo mismo para visual basic 6.0 incluyendo la conexion a sql y ejecucion del procedure

Leave a Comment

(required) 
(required) 
(optional)
(required) 
Powered by Community Server (Commercial Edition), by Telligent Systems