Sql-server – Auto Script DB Objects for SVN

scriptingsql-server-2008sql-server-2008-r2

My Boss requires that we keep up to date scripts of all database objects in svn. This results in constantly trying to find the object in the current script and copy and pasting the changes.

Is there an easy way to set sql server to script database objects and write them to a file on the drive?

If not then I've built the following sql script as a test run for creating a tables file but I'm not sure how to capture the output string that sp_executesql is creating.

DECLARE @SQL2 NVARCHAR(MAX) = ''

CREATE TABLE #Dbs(name varchar(200) NOT NULL)

INSERT INTO #Dbs(name)
SELECT name
  FROM sys.databases
 WHERE name NOT IN ('master','msdb','tempdb', 'model')
 ORDER BY name

WHILE (SELECT COUNT(1) FROM #Dbs) > 0 
BEGIN

SET @SQL2 = N'USE [' + (SELECT TOP 1 #Dbs.name FROM #Dbs ORDER BY name) + N']' + '

DECLARE @SQL NVARCHAR(MAX) = ''''
DECLARE @CurrentTable VARCHAR(200) = '' ''
DECLARE @OldTable VARCHAR(200) = '' ''

SET @SQL = ''''

    SET @SQL = @SQL + N''USE ['' + (SELECT TOP 1 #Dbs.name FROM #Dbs ORDER BY name) + N'']''

    CREATE TABLE #columns (ColumnName VARCHAR(200) NULL,
                           ColumnID INT, 
                           TableName VARCHAR(200) NULL,
                           DataType VARCHAR(50) NULL,
                           Nullable VARCHAR(15) NULL, 
                           MiscInfo VARCHAR(50) NULL,
                           UseAnsiNulls VARCHAR(50) NULL
                           )

    INSERT INTO #columns(columnname, ColumnID, TableName, datatype, Nullable, MiscInfo, UseAnsiNulls)
    SELECT s.name as ColumnName,
           s.column_id,
           ''[''+sh.name+''].[''+b.name+'']'' AS ObjectName ,
           CASE 
               WHEN t.name IN (''char'',''varchar'') THEN t.name+''(''+CASE WHEN s.max_length<0 then ''MAX'' ELSE CONVERT(varchar(10),s.max_length) END+'')'' 
               WHEN t.name IN (''nvarchar'',''nchar'') THEN t.name+''(''+CASE WHEN s.max_length<0 then ''MAX'' ELSE CONVERT(varchar(10),s.max_length/2) END+'')'' 
               WHEN t.name IN (''numeric'') THEN t.name+''(''+CONVERT(varchar(10),s.precision)+'',''+CONVERT(varchar(10),s.scale)+'')'' 
               ELSE t.name 
           END AS DataType, 
           CASE 
               WHEN s.is_nullable=1 THEN ''NULL'' 
               ELSE ''NOT NULL'' 
           END AS Nullable, 

           CASE 
               WHEN ic.column_id IS NULL THEN '''' 
               ELSE '' identity(''+ISNULL(CONVERT(varchar(10),ic.seed_value),'''')+'',''+ISNULL(CONVERT(varchar(10),ic.increment_value),'''')+'')''
           END + CASE 
                     WHEN sc.column_id IS NULL THEN '''' 
                     ELSE '' computed(''+ISNULL(sc.definition,'''')+'')'' 
                 END + CASE 
                           WHEN cc.object_id IS NULL THEN '''' 
                           ELSE '' check(''+ISNULL(cc.definition,'''')+'')'' 
                       END AS MiscInfo,
           CASE 
               WHEN uses_ansi_nulls = 1 THEN
                    N''SET ANSI_NULLS ON''
               ELSE N''SET ANSI_NULLS OFF''
           END UseAnsiNulls
      FROM sys.columns s 
           JOIN sys.types t ON s.system_type_id=t.system_type_id and t.is_user_defined=0 
           JOIN sys.tables b ON s.object_id=b.object_id 
           JOIN sys.schemas sh on b.schema_id=sh.schema_id 
           LEFT OUTER JOIN sys.identity_columns  ic ON s.object_id=ic.object_id AND s.column_id=ic.column_id 
           LEFT OUTER JOIN sys.computed_columns  sc ON s.object_id=sc.object_id AND s.column_id=sc.column_id 
           LEFT OUTER JOIN sys.check_constraints cc ON s.object_id=cc.parent_object_id AND s.column_id=cc.parent_column_id 
     ORDER BY sh.name+''.''+b.name,s.column_id 

    WHILE (SELECT COUNT(1) FROM #columns) > 0 
    BEGIN

        SET @CurrentTable = (SELECT TOP 1 Tablename 
                               FROM #columns
                              ORDER BY TableName, columnid)

        IF @OldTable != @CurrentTable
        BEGIN

            IF @SQL IS NOT NULL AND @SQL != '''' AND @SQL !=  N''USE ['' + (SELECT TOP 1 #Dbs.name FROM #Dbs ORDER BY name) + N'']''
            BEGIN
              SET @SQL = (SELECT SUBSTRING(@SQL,1,LEN(@SQL)-2)) + '')''
            END

                SET @SQL = @SQL + '' '' + (SELECT TOP 1 UseAnsiNulls 
                                           FROM #columns
                                          ORDER BY TableName, columnid) +N'' CREATE TABLE '' + (SELECT TOP 1 TableName
                                                                                                                FROM #columns
                                                                                                               ORDER BY TableName, columnid) + ''(''
        SET @OldTable = @CurrentTable
        END

        SET @SQL = @SQL + (SELECT TOP 1 Columnname + '' '' + datatype + '' '' + Nullable + '' '' + MiscInfo + '',''  FROM #columns ORDER BY TableName, columnid)

        DELETE FROM #columns
          FROM #columns c
         WHERE c.ColumnName = (SELECT TOP 1 Columnname FROM #columns ORDER BY TableName, columnid)
           AND c.TableName = (SELECT TOP 1 tablename FROM #columns ORDER BY TableName, columnid)
    END--Loop Columns End

SELECT SUBSTRING(@SQL,1,LEN(@SQL)-2) + '')''

DROP TABLE #Columns'

exec sp_executesql @SQL2

DELETE FROM #Dbs
 WHERE #dbs.name = (SELECT TOP 1 name FROM #Dbs WHERE name NOT IN ('master','msdb','tempdb', 'model') ORDER BY name)
END--LOOP DBS END

DROP TABLE #DBs

Best Answer

For a repeatable process you can use Powershell to script objects. The following link has more detail but essentially you load the SMO objects, loop through the objects in the database, and call the Script function.

http://philergia.wordpress.com/2011/02/28/using-powershell-and-smo-to-script-sql-server-database-objects-3/