Click here to Skip to main content
15,891,136 members
Articles / Database Development / SQL Server

SQL Server database versioning with Subversion (SVN)

Rate me:
Please Sign up or sign in to vote.
4.61/5 (19 votes)
13 Oct 20067 min read 286.5K   4.4K   144  
This tool (ScriptDB4Svn) enables you to add your SQL Server databases to Subversion (SVN) source control.
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.IO;
using System.Data;
using System.Data.Common;

namespace ScriptDB4SVN
{
    public static class DataScripter
    {
        //private string _connectionString;
        //public string ConnectionString
        //{
        //    get { return _connectionString; }
        //    set { _connectionString = value; }
        //}

        //private string _tables;
        //public string Tables
        //{
        //    get { return _tables; }
        //    set { _tables = value; }
        //}

        public static bool ScriptData(string connectionString, string[] tables, string outputPath)
        {
            SqlConnection conn = new SqlConnection(connectionString);
            conn.Open();
            DataTable pkSchema = conn.GetSchema("IndexColumns");

            foreach (string table in tables)
            {
                // Get the contents of the table
                Console.WriteLine("Scripting data for table [" + table + "]..");

                SqlCommand command = conn.CreateCommand();
                // Find out what columns belong to the table

                List<string> sortColumns = new List<string>();
                string selection = string.Format("table_name='{0}' AND index_name like 'PK_%'", table);
                DataRow[] pkColumns = pkSchema.Select(selection, "ordinal_position");
                if (pkColumns.Length > 0)
                {
                    foreach (DataRow pkColumn in pkColumns)
                        sortColumns.Add("[" + pkColumn["column_name"].ToString() + "]");
                }
                else
                {
                    sortColumns.Add("1");
                }
                string orderBy = string.Join(",", sortColumns.ToArray());

                command.CommandText = string.Format("SELECT * FROM {0} ORDER BY {1}", table, orderBy);
                SqlDataReader dr = command.ExecuteReader();
                string fields = "";
                string sqlStatements = "";

                // Only continue if there is at least 1 row in the returned data
                if (dr.HasRows)
                {
                    // Get table columns
                    for (int fieldnr = 0; fieldnr < dr.FieldCount; fieldnr++)
                    {
                        fields += dr.GetName(fieldnr) + ",";
                    }
                    fields = fields.TrimEnd(',');
                    sqlStatements = string.Format("-- Data scripted for table {0} with columns: {1}\n", table, fields);

                    //dr.Close();
                    //// Now fetch all table contents, order by all columns to always get the same order
                    //command.CommandText = string.Format("SELECT * FROM {0} ORDER BY {1}", table, fields);
                    //dr = command.ExecuteReader();

                    // Set XACT_ABORT on so that the transaction will be rolled back when an error occurs
                    sqlStatements += "SET XACT_ABORT ON\n";
                    // Begin transaction
                    sqlStatements += "BEGIN TRANSACTION\n\n";
                    // Delete existing data
                    sqlStatements += string.Format("DELETE FROM {0}\n\n", table);
                    // Enable optional identity values to be inserted
                    sqlStatements += string.Format("IF exists(SELECT OBJECT_NAME(id) FROM syscolumns WHERE OBJECT_NAME(id)='{0}' AND (status & 128) = 128) BEGIN\n\tSET IDENTITY_INSERT {0} ON\nEND\n\n", table);

                    //// INSERT INTO statement
                    //sqlStatements += string.Format("INSERT INTO {0} ({1})\n", table, fields);

                    // Loop through all rows
                    while (dr.Read())
                    {
                        string values = "";
                        string formattedValue = "";

                        // Loop through all columns
                        for (int fieldnr = 0; fieldnr < dr.FieldCount; fieldnr++)
                        {
                            object someValue = dr.GetValue(fieldnr);
                            switch (someValue.GetType().Name)
                            {
                                case "String": formattedValue = "N'" + ((string)someValue).Replace("'", "''") + "'"; break;
                                case "DateTime": formattedValue = "'" + ((DateTime)someValue).ToString("yyyy/MM/dd HH:mm:ss") + "'"; break;
                                case "DBNull": formattedValue = "NULL"; break;
                                case "Boolean": formattedValue = (bool)someValue ? "1" : "0"; break;
                                case "Guid": formattedValue = "'" + ((Guid)someValue).ToString() + "'"; break;
                                case "Decimal":
                                case "Float":
                                case "Double":
                                case "Single":
                                    formattedValue = someValue.ToString().Replace(',', '.');
                                    break;

                                default: formattedValue = someValue.ToString(); break;
                            }
                            values += formattedValue + ",";
                        }
                        values = values.TrimEnd(',');

                        // Create INSERT statement
                        string insertStatementFormat = "INSERT INTO {0} ({1})\n\tVALUES ({2})\n";
                        sqlStatements += string.Format(insertStatementFormat, table, fields, values);
                        //string insertStatementFormat = "SELECT {0} UNION\n";
                        //sqlStatements += string.Format(insertStatementFormat, values);
                    }

                    //// Cut off the last UNION statement
                    //if (sqlStatements.EndsWith("UNION\n"))
                    //{
                    //    sqlStatements = sqlStatements.Substring(0, sqlStatements.Length - "UNION\n".Length) + "\n";
                    //}

                    // Disable identity inserts again
                    sqlStatements += string.Format("\nIF exists(SELECT OBJECT_NAME(id) FROM syscolumns WHERE OBJECT_NAME(id)='{0}' AND (status & 128) = 128) BEGIN\n\tSET IDENTITY_INSERT {0} OFF\nEND\n\n", table);

                    // Commit the transaction
                    sqlStatements += "COMMIT TRANSACTION\n";
                    // Turn XACT_ABORT off again
                    sqlStatements += "SET XACT_ABORT OFF\n";
                }
                dr.Close();

                // Save insert statements to file
                Directory.CreateDirectory(outputPath);
                string filename = outputPath + "\\" + table + ".sql";
                StreamWriter sw = File.CreateText(filename);
                sw.Write(sqlStatements);
                sw.Close();
            }

            conn.Close();
            return true;
        }

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Netherlands Netherlands
27 years old. Alive and kicking!

Comments and Discussions