Tag: SQL

  • SSMS Trusted

    SSMS Trusted

    It is possible to run SQL Server Management Studio under the guise of another user account from the command line:

    runas /netonly /user:domain\user c:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\ssms.exe

    The command line will request a password which (quite rightly!) cannot be entered into the command. Successful authentication will launch an instance of SSMS 2008. Lovely.

  • SQL Server Compact 4.0

    Loving the medium trust capabilities for small online apps – take that! all you sucky rip off hosters!!Here Comes SQL Server Compact 4.0 | Rob Tiffany

  • Restore Database 2005 User Logins

    When a database is restored from one server to another user logins are dropped. This script will help rectify that:

    SET NOCOUNT ON

    --SELECT 'EXEC sp_change_users_login ''Auto_Fix'', '''+ user_id + ''', NULL, '''+ user_id + ''''
    SELECT 'EXEC sp_change_users_login ''Auto_Fix'', '''+ user_id + ''', NULL, ''password'''
    FROM staff s
    JOIN sys.sysusers su
    ON su.name = s.user_id
    WHERE s.is_Deleted = 'N'

    This will generate some further SQL statements that need to be executed. The passwords are reset to the values in the final parameter (i.e. password):

    EXEC sp_change_users_login 'Auto_Fix', 'wm', NULL, 'password'
    EXEC sp_change_users_login 'Auto_Fix', 'TTestA', NULL, 'password'
    EXEC sp_change_users_login 'Auto_Fix', 'TTestB', NULL, 'password'
    EXEC sp_change_users_login 'Auto_Fix', 'TTestC', NULL, 'password'

    To transfer logins between servers: http://support.microsoft.com/kb/246133

  • Using ASPNET_RegSQL.exe with SQL Express databases in APP_DATA

    As discussed at Lance’s Whiteboard, a really easy way to hook up an ASPNET membership provider database to an application … perfect for rapid prototyping…

    “Creating a new DB in VisualStudio.NET 2005 is as simple as “Select APP_DATA node -> Add New Item -> Sql Database” and wah-lah you have a new aspnet.mdf file located in your APP_DATA folder.”

    and to register the ASPNET membership provider content within this database:

    aspnet_regsql -A all -C "Data Source=.\SQLEXPRESS;Integrated Security=True;User Instance=True" -d "C:\MyProject\APP_DATA\aspnetdb.mdf

  • Compare contents of two tables.

    SET QUOTED_IDENTIFIER ON 
    GO
    SET ANSI_NULLS ON
    GO

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sp_CompareTables]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
    drop procedure [dbo].[sp_CompareTables]
    GO

    CREATE PROCEDURE sp_CompareTables
    @table1 sysname,
    @table2 sysname,
    @ColumnList varchar(8000) = '*',
    @Summary bit = 0,
    @Detail bit = 1,
    @TableNameHeader varchar(30) = '[Table Name]',
    @CounterHeader varchar(30) = '[Counter]',
    @rc int = null out
    AS
    ------------------------------------------------------------------------------
    --Compare the contents of two tables
    --@table1 and @table2 are the table names
    --@ColumnList is the list of column names, by default all columns will be compared
    --@Summary - set this to 1 it you want summary information
    --@Detail - set this to 1 (the default) if you want the details of the differences
    --@TableNameHeader - this is used as the column heading the a column that contains the table name
    --@CounterHeader - this is used as the column heading the a column that contains a row count
    --(this is used when there may be multiple identical rows
    --@rc - the number of rows that are different
    --Note: this SP can "live" in the master DB
    ------------------------------------------------------------------------------
    DECLARE @err integer,
    @SQL1 varchar(8000),
    @SQL2 varchar(8000),
    @SQL3 varchar(8000),
    @SQL4 varchar(8000),
    @SQLTop varchar(8000),
    @SQLBot varchar(8000),
    @SQLTop2 varchar(8000),
    @SQLBot2 varchar(8000),
    @ColumnGrouping varchar(8000),
    @indexlist varchar(8000)

    SET NOCOUNT ON

    -- a bit of validation first
    IF object_id(@table1) IS NULL
    BEGIN
    RAISERROR ('Table ''%s'' does not exist', 11, 1, @table1) WITH NOWAIT
    RETURN
    END

    IF object_id(@table2) IS NULL
    BEGIN
    RAISERROR ('Table ''%s'' does not exist', 11, 1, @table2) WITH NOWAIT
    RETURN
    END

    IF @table1 NOT LIKE '%.%'
    BEGIN
    SET @table1 = DB_NAME() + '..' + @table1
    END

    IF @table2 NOT LIKE '%.%'
    BEGIN
    SET @table2 = DB_NAME() + '..' + @table2
    END

    -- let's get a list of columns that have different collations ...
    CREATE TABLE #CollationColumns (name sysname)

    DECLARE @SQL varchar(8000)

    set @SQL = 'INSERT #CollationColumns SELECT a.name
    FROM %db1..syscolumns a
    INNER JOIN %db2..syscolumns b
    ON a.name = b.name COLLATE database_default
    WHERE a.id = object_id(''%t1'')
    AND b.id = object_id(''%t2'')
    AND a.collationid b.collationid'
    SET @SQL = replace(@SQL, '%db1', PARSENAME(@table1, 3))
    SET @SQL = replace(@SQL, '%db2', PARSENAME(@table2, 3))
    SET @SQL = replace(@SQL, '%t1', @table1)
    SET @SQL = replace(@SQL, '%t2', @table2)

    EXEC (@SQL)

    -- If the first table is in the current database
    -- we can look to see if there is a unique index
    IF PARSENAME(@table1, 3) = DB_NAME()
    BEGIN
    SET @indexlist = NULL

    SELECT @indexlist = COALESCE(@indexlist + ', ', '') + '[' + c.name + ']'
    FROM syscolumns c
    INNER JOIN sysindexkeys k ON c.colid = k.colid
    AND k.id = OBJECT_ID(@table1)
    AND c.id = k.id
    INNER JOIN sysindexes i ON i.id = k.id
    AND i.indid = k.indid
    WHERE i.indid = ( SELECT TOP 1 i.indid -- get the first unique index (favouring the clustered one)
    FROM sysindexes
    WHERE id = OBJECT_ID(@table1)
    AND INDEXPROPERTY(i.id,i.name, 'IsUnique') = 1
    AND INDEXPROPERTY(i.id,i.name, 'IsStatistics') = 0
    ORDER BY INDEXPROPERTY(i.id,i.name, 'IsClustered') DESC)
    ORDER BY k.keyno
    END

    IF @indexlist IS NULL AND @Summary = 1
    BEGIN
    RAISERROR ('Summary is not availabe as table ''%s'' has no unique index', 10, 1, @table1) WITH NOWAIT
    SET @Summary = 0
    END

    -- Let's generate a list of columns ...
    IF @ColumnList = '*' or @ColumnList = ''
    BEGIN
    -- we can only do this in the current database (this could be enhanced though)
    IF PARSENAME(@table1, 3) DB_NAME()
    BEGIN
    RAISERROR ('Table ''%s'' is not in the current database', 11, 1, @table1) WITH NOWAIT
    RETURN
    END
    SET @ColumnList = NULL
    SET @ColumnGrouping = NULL
    -- get a comma delimited list
    -- convert text and netxt to varchar(8000)
    -- convert image to binary
    SELECT @ColumnList = COALESCE(@ColumnList + ', ', '') + CASE
    WHEN systypes.name IN ( 'text' ,'ntext')
    THEN 'CONVERT(VARCHAR(8000),' + '[' + syscolumns.name + ']' + ') AS '
    WHEN systypes.name ='image'
    THEN 'CONVERT(BINARY,' + '[' + syscolumns.name + ']' + ') AS '
    ELSE ''
    END
    + '[' + syscolumns.name + ']'
    -- if the column has different collation the just use a database default
    + CASE WHEN syscolumns.name IN (SELECT name COLLATE database_default FROM #CollationColumns)
    THEN ' collate database_default AS [' + syscolumns.name + ']'
    ELSE ''
    END
    FROM syscolumns INNER JOIN systypes ON syscolumns.xusertype = systypes.xusertype
    WHERE ID = object_id(@table1)
    ORDER BY colid

    -- we need a similar list of columns for the GROUP BY clause
    SELECT @ColumnGrouping = COALESCE(@ColumnGrouping + ', ', '') + CASE
    WHEN systypes.name in ( 'text' ,'ntext')
    THEN 'convert(varchar(8000),' + '[' + syscolumns.name + ']' + ')'
    WHEN systypes.name = 'image'
    THEN 'convert(binary,' + '[' + syscolumns.name + ']' + ')'
    ELSE '[' + syscolumns.name + ']'
    END
    FROM syscolumns
    INNER JOIN systypes on syscolumns.xusertype = systypes.xusertype
    WHERE id = object_id(@table1)
    ORDER BY colid
    END
    ELSE
    BEGIN
    SET @ColumnGrouping = @ColumnList
    END

    DECLARE @Counter1 varchar(8000)
    DECLARE @Counter2 varchar(8000)

    -- if we have a unique index then we don't need a row count.
    IF @indexlist IS NULL
    BEGIN
    SET @Counter1 = 'COUNT (*) AS ' + @CounterHeader + ', '
    SET @Counter2 = @CounterHeader + ', '
    END
    ELSE
    BEGIN
    SET @Counter1 = ''
    SET @Counter2 = ''
    END

    -- here's the wizzy SQL (I will explain it sometime)
    SET @SQL1 = 'SELECT ' + @Counter1 + '''' + @table1 + ''' AS ' + @TableNameHeader + ', ' + @ColumnList + ' FROM ' + @Table1 + char(13)
    SET @SQL2 = ' GROUP BY ' + @ColumnGrouping + char(13)
    SET @SQL3 = ' UNION ALL SELECT ' + @Counter1 + '''' + @table2 + ''' AS ' + @TableNameHeader + ', ' + @ColumnList + ' FROM ' + @Table2 + char(13)
    SET @SQL4 = ' GROUP BY ' + @ColumnGrouping + char(13)
    SET @SQLTop = 'SELECT ' + @Counter2 + ' Max(' + @TableNameHeader + ') AS ' + @TableNameHeader + ', ' + @ColumnList + ' FROM (' + char(13)
    SET @SQLBot = ') A ' + CHAR(13) + ' GROUP BY ' + @Counter2 + @ColumnGrouping + CHAR(13) + ' HAVING COUNT(*) 2'
    SET @SQLTop2 = 'SELECT ' + @indexlist +
    ' , CASE COUNT(*) when 2 ' +
    ' THEN ''Different'' ' +
    ' ELSE ''Only in '' + max(' + @TableNameHeader + ') ' +
    ' END AS [Details] ' +
    ' FROM ( '
    SET @SQLBot2 = ') B GROUP BY ' + @indexlist

    -- now output the details
    IF @Detail = 1
    BEGIN
    EXEC (@SQLTop + @SQL1 + @SQL2 + @SQL3 + @SQL4 + @SQLBot)
    SET @rc = @@ROWCOUNT
    END

    IF @Summary = 1
    BEGIN
    EXEC (@SQLTop2 + @SQLTop + @SQL1 + @SQL2 + @SQL3 + @SQL4 + @SQLBot + @SQLBot2)
    SET @rc = @@ROWCOUNT
    END

    IF @rc = 0
    BEGIN
    RAISERROR ('Tables ''%s'' and ''%s'' are the same', 10, 1, @table1, @table2) WITH NOWAIT
    END
    ELSE
    BEGIN
    RAISERROR ('Tables ''%s'' and ''%s'' contain %d ''different'' rows', 10, 1, @table1, @table2, @rc) WITH NOWAIT
    END


    SET NOCOUNT OFF
    GO
    SET QUOTED_IDENTIFIER OFF
    GO
    SET ANSI_NULLS ON
    GO

  • Compare 2 database tables

    SET QUOTED_IDENTIFIER ON
    GO
    SET ANSI_NULLS ON
    GO
    IF EXISTS (select * from dbo.sysobjects where id = object_id(N'[dbo].[sp_CompareDBTables]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
    drop procedure [dbo].[sp_CompareDBTables]
    GO

    CREATE PROC sp_CompareDBTables
    @targetDB sysname,
    @Summary bit = 0,
    @Detail bit = 1
    --****************************************
    --@targetDB: we'll compare the current database with this one
    --@Summary: do we want summary output?
    --@Detail: do we want detail output?

    --calls sp_CompareTables for each table in the current table

    --Note: this SP can "live" in the master DB
    --*****************************************/
    AS
    IF DB_ID(@targetDB) IS NULL
    BEGIN
    RAISERROR('The target database cannot be found.', 10, 1) WITH NOWAIT
    END

    DECLARE @SQL varchar(4000)

    SET @SQL = 'exec sp_CompareTables ''?'', ''' + @targetDB + '.?'', @Summary = ' + convert(varchar(1) ,@Summary) + ', @Detail = ' + convert(varchar(1) ,@Detail)

    EXEC sp_msforeachtable @SQL

    GO
    SET QUOTED_IDENTIFIER OFF
    GO
    SET ANSI_NULLS ON
    GO