Comparing two SQL Server database schemas in C #

I am releasing a newer version of my application for Windows. In the new version of database schema changes. Also I do not want to lose data.

So the approach I took is to replace the dll while saving the database. To update the database, I plan to compare the database schema of the old database and make the necessary changes.

So, how can I compare the database structure (schema) of the old with the new and how can I detect the changes and fix it. So far, I have tried to try and get the database schema using the GetSchema method.

But since the new scheme is predefined, how can I insert a new scheme into the program and compare it with the existing one on the site where the older one was installed.

+5
source share
4 answers

Here you can freely compare databases.

The following is a SQL Server script that displays the contents of stored procedures, views, and database tables in the Exit window.

Run it by calling:

 exec [dbo].[ScriptStoredProcedures] 

In many of my projects, I ran this script, copied the text to a file in a Visual Studio project so that I could register a copy of how our database was viewed at a specific time.

(Yes, you can also have database projects in Visual Studio, but this is an alternative method.)

If you run this script in both of your databases, you can compare the two outputs to find the differences.

 CREATE PROCEDURE [dbo].[ScriptStoredProcedures] AS BEGIN -- -- Attempt to create a long SQL script, to Drop, then "CREATE PROCEDURE" on all SPs and "CREATE FUNCTION" on all Functions in this database. -- -- You can then run this script on a "target" database, and it'll have the latest Stored Procedures & functions -- created/updated on it. -- -- exec [dbo].[ScriptStoredProcedures] -- SET NOCOUNT ON PRINT '--' PRINT '-- SQL Script, generated by the [ScriptStoredProcedures] Stored Procedure.' PRINT '-- Created on ' + convert(nvarchar, GetDate(), 106) + ' ' + convert(nvarchar, GetDate(), 108) PRINT '--' PRINT '-- This will create/update the Stored Procedures on this database, to bring them up-to-date with the SPs ' PRINT '-- from the database ''' + DB_NAME() + ''' on the server ''' + @@SERVERNAME + '''' PRINT '--' PRINT '--' -- Create a temporary table, where each record contains one line of Stored Procedure/Function script -- (ie If you have a Stored Procedure with 30 lines of script in it, we'll create 30 temporary records -- to store it) CREATE TABLE #tmp ( [inx] INT IDENTITY(1, 1), [text] nvarchar(4000) ) DECLARE @StoredProcedureName NVARCHAR(200) DECLARE @StoredProcedureType NVARCHAR(10) DECLARE @ExecCommand NVARCHAR(200) DECLARE @OneLineOfScript NVARCHAR(4000) -- First, get a list of all Stored Procedures & Functions in this database DECLARE cursorEachStoredProcedure CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY FOR SELECT [name], -- Name of the Stored Procedure or Function [type] -- This will contain "FN" if it a Function, or "P" if it a Stored Procedure FROM sysobjects WHERE (OBJECTPROPERTY(id, N'IsProcedure') = 1 OR OBJECTPROPERTY(id, N'IsTableFunction') = 1 OR OBJECTPROPERTY(id, N'IsScalarFunction') = 1 OR OBJECTPROPERTY(id, N'IsView') = 1) AND [name] NOT LIKE 'sp_%' AND [name] NOT LIKE 'fn_%' ORDER BY [type] DESC, -- Sort by Stored Procedures first, then functions [name] -- then show the list of SPs/Functions in name order OPEN cursorEachStoredProcedure FETCH NEXT FROM cursorEachStoredProcedure INTO @StoredProcedureName, @StoredProcedureType -- For each Stored Procedure we've found in our database, create some script to delete the Stored Procedure -- from the target database if it exists, then re-create it. WHILE (@@FETCH_STATUS = 0) BEGIN PRINT '' IF (@StoredProcedureType = 'P') BEGIN PRINT 'PRINT ''Creating stored procedure: ''''' + @StoredProcedureName + '''''''' PRINT '' PRINT 'IF EXISTS(select Name from sysobjects where OBJECTPROPERTY(id, N''IsProcedure'') = 1 AND Name = ''' + @StoredProcedureName + ''')' PRINT 'BEGIN' PRINT ' DROP PROCEDURE [' + @StoredProcedureName + '] ' PRINT 'END' END ELSE IF (@StoredProcedureType = 'V') BEGIN PRINT 'PRINT ''Creating view: ''''' + @StoredProcedureName + '''''''' PRINT '' PRINT 'IF EXISTS(select Name from sysobjects where OBJECTPROPERTY(id, N''IsView'') = 1 AND Name = ''' + @StoredProcedureName + ''')' PRINT 'BEGIN' PRINT ' DROP VIEW [' + @StoredProcedureName + '] ' PRINT 'END' END ELSE BEGIN PRINT 'PRINT ''Creating function: ''''' + @StoredProcedureName + '''''''' PRINT '' PRINT 'IF EXISTS(select Name from sysobjects where (OBJECTPROPERTY(id, N''IsTableFunction'') = 1 OR OBJECTPROPERTY(id, N''IsScalarFunction'') = 1) AND Name = ''' + @StoredProcedureName + ''')' PRINT 'BEGIN' PRINT ' DROP FUNCTION [' + @StoredProcedureName + '] ' PRINT 'END' END PRINT 'GO ' -- Run the "sp_helptext" command, to get the text of this Stored Procedure (one row per *line* of script) -- and store this set of results in a temporary table, so we can step through, line-by-line, and send -- the output to the Messages window. SET @ExecCommand = 'sp_helptext @objname = ''' + @StoredProcedureName + '''' DELETE FROM #tmp INSERT INTO #tmp EXEC(@ExecCommand) -- Step through each line of this Stored Procedure DECLARE cursorEachLineOfScript CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY FOR SELECT [text] FROM #tmp ORDER BY [inx] OPEN cursorEachLineOfScript FETCH NEXT FROM cursorEachLineOfScript INTO @OneLineOfScript WHILE (@@FETCH_STATUS = 0) BEGIN -- For each line of Stored Procedure script, send the text to the Messages window PRINT @OneLineOfScript FETCH NEXT FROM cursorEachLineOfScript INTO @OneLineOfScript END CLOSE cursorEachLineOfScript DEALLOCATE cursorEachLineOfScript PRINT 'GO ' FETCH NEXT FROM cursorEachStoredProcedure INTO @StoredProcedureName, @StoredProcedureType END CLOSE cursorEachStoredProcedure DEALLOCATE cursorEachStoredProcedure DROP TABLE #tmp PRINT 'EXEC [dbo].[spGrantExectoAllStoredProcs]' PRINT 'GO' PRINT '--' PRINT '--' PRINT '-- List of tables (and their fields) in this database' PRINT '--' PRINT '--' PRINT '--' -- First, let iterate through our list of tables, and find out which fields they contain. DECLARE @tableName nvarchar(200), @fieldName nvarchar(500), @fieldType nvarchar(500), @fieldNullable nvarchar(200) DECLARE cursorTables CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY FOR SELECT st.NAME as 'Table_name' FROM sys.tables st ORDER BY 1 OPEN cursorTables FETCH NEXT FROM cursorTables INTO @tableName WHILE (@@FETCH_STATUS = 0) BEGIN PRINT '-- Table: ' + @tableName DECLARE cursorFields CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY FOR SELECT sc.NAME as 'Field_name', case when t.Name in ('char', 'varchar', 'nvarchar') then t.Name + '(' + cast(sc.max_length/2 as nvarchar) + ')' else case when t.Name in ('numeric') then t.Name + '(' + cast(sc.precision as nvarchar) + ',' + cast(sc.scale as nvarchar) + ')' else t.Name end end as 'Data_type', case when sc.is_nullable=1 then 'null' else 'not null' end as 'Nullable' FROM sys.tables st INNER JOIN sys.columns sc ON st.object_id = sc.object_id INNER JOIN sys.types t ON sc.system_type_id = t.system_type_id WHERE t.Name != 'sysname' AND st.name = @tableName ORDER BY 1, 2 OPEN cursorFields FETCH NEXT FROM cursorFields INTO @fieldName, @fieldType, @fieldNullable WHILE (@@FETCH_STATUS = 0) BEGIN PRINT '-- ' + @fieldName + ' (' + @fieldType + ', ' + @fieldNullable + ')' FETCH NEXT FROM cursorFields INTO @fieldName, @fieldType, @fieldNullable END CLOSE cursorFields DEALLOCATE cursorFields PRINT '--' FETCH NEXT FROM cursorTables INTO @tableName END CLOSE cursorTables DEALLOCATE cursorTables END 
+4
source

We use RedGate's SQL Compare, but it's not particularly cheap.

SQL Compare

This allows us to compare the structure of two databases and create an SQL script to update one of the databases in accordance with the other.

+3
source

Create Database Migration scripts and run them with a tool like Db Up to track schema changes. SQL Scripts migrate your database from version 1 to 2, from 2 to 3, etc. Schema Compare is another option mentioned in the previous question .

  • Change Customer Tables.sql
  • Update .sql settings
+2
source

Two sentences.

  • use the Redgate SQL Comparison SDK (for whom I work). This allows you programmatic access to SQL Compare technology.
  • There should be a characteristic of a specific version of the circuit that you can check to determine what it is? If so, you can run the appropriate script for this version to continue to the next. For your installer, you just need to enable a chain of migration scripts that run sequentially in order to move to the next incremental version. Ideally, you will have version information embedded in the schema, either through an extended property or into a version table, which is updated after the script migration is successfully applied.
0
source

All Articles