Сравнение схем MSSQL с помощью T SQL

У меня есть 21 БД на одном сервере, которые «должны» иметь одну и ту же схему (на данный момент ограничивая схему только схемой таблицы), но это не так. В той среде, в которой я нахожусь, я не могу установить какие-либо инструменты/приложения в соответствии с правилами соответствия. Единственный способ, который я могу придумать, - это вывести схему всех 21 БД в Excel и сравнить, но это утомительно.

Может ли кто-нибудь помочь мне в разработке T-SQL, который может сравнить схему для всех 21 БД и выделить различия?

Вот столбцы, которые мне нужны: Table_Name, имя столбца, тип данных, максимальная длина, is_nullable, is_replicated, первичный ключ.

Следующий T-sql выводит эту информацию для меня. Мне нужно некоторое представление о том, как я могу сравнить эту информацию для 21 БД

SELECT    a.name Table_Name, c.name 'Column Name',
     t.Name 'Data type',
     c.max_length 'Max Length',
     c.is_nullable,a.is_replicated ,
     ISNULL(i.is_primary_key, 0) 'Primary Key'
FROM    Sys.tables a inner join      sys.columns c
On A.object_id=C.object_id
INNER JOIN 
     sys.types t ON c.user_type_id = t.user_type_id
LEFT OUTER JOIN 
     sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
LEFT OUTER JOIN 
     sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
     Order by 1,2

мне нужна отправная точка


person Alok Singh    schedule 29.07.2016    source источник
comment
и выделить отличия? какие отличия?   -  person TheGameiswar    schedule 29.07.2016
comment
Если какое-либо из 7 полей отличается для данной таблицы для 21 БД - это считается разницей. Я буду счастлив, если смогу поместить результат для 21 БД во временную таблицу, а затем запросить временную таблицу на наличие различий. Что-то в этих строках...   -  person Alok Singh    schedule 29.07.2016
comment
В Visual Studio есть Инструменты › Sql Server › Новое сравнение схем, которое будет различать два источника. Может быть стоит посмотреть.   -  person Phritzy    schedule 29.07.2016
comment
@Phritzy - я мог бы попробовать это, но по какой-то причине моя клиентская компания также не разрешает мне использовать Visual Studio. Так что все, что я могу сделать, это через T sql. В худшем случае: я вытащу все данные в Excel, а затем сравню   -  person Alok Singh    schedule 29.07.2016
comment
Это не сработает. То, что у вас есть, едва царапает поверхность фактического сравнения схем. Все, на что вы смотрите, это таблицы. Как насчет представлений, функций, процедур и т. д.?   -  person Sean Lange    schedule 29.07.2016
comment
@SeanLange На данный момент меня беспокоят только столы. Извините - я не упомянул об этом в своем первоначальном вопросе.   -  person Alok Singh    schedule 29.07.2016
comment
Как насчет ограничений, триггеров или ключей?   -  person Bridge    schedule 29.07.2016
comment
И не забывайте об индексах!!   -  person Sean Lange    schedule 29.07.2016
comment
@Bridge Ты прав! Мне они тоже понадобятся :) и индексы тоже. Возможно ли это сделать с помощью T SQL? или я слишком много прошу.   -  person Alok Singh    schedule 29.07.2016
comment
То, с чем вы сталкиваетесь сейчас, является причиной того, что существует несколько программ, которые специализируются на этом. Это НЕ просто и очень быстро становится невероятно сложным, пытаясь создать свой собственный для такого рода вещей. Почему бы просто не установить бесплатную версию VS и избавить себя от мучений на несколько недель. Есть несколько других готовых приложений, которые делают подобные вещи намного лучше, чем доморощенные версии.   -  person Sean Lange    schedule 29.07.2016
comment
Что сказал @Sean. Большинство сторонних инструментов устанавливаются на ваш компьютер (ноутбук), подключаются к нужным (удаленным) экземплярам SQL и работают с ними. Я часто использую Redgate SQL Compare, и даже если вы сравниваете только две базы данных одновременно, версия (большой номер), обновленная для SQL 2014, чертовски исчерпывающая.   -  person Philip Kelley    schedule 29.07.2016
comment
Redgate SQL Compare действительно надежный, но НЕ дешевый. Это обсуждение превратило это в вопрос о том, какое стороннее программное обеспечение следует использовать, что не относится к теме SO.   -  person Sean Lange    schedule 29.07.2016
comment
Это возможно, мне приходится делать все слишком часто. Хотя это требует немного работы.   -  person RBarryYoung    schedule 29.07.2016
comment
Я просто не могу ничего установить даже на свою локальную машину, у меня нет прав администратора. Здесь даже загрузка отключена :D   -  person Alok Singh    schedule 29.07.2016


Ответы (1)


Мне постоянно приходится делать подобные вещи с одинаковыми ограничениями, в том числе без использования профессиональных инструментов, предназначенных для этого. Вот один из способов:

Сначала создайте временную таблицу для хранения информации таблицы:

CREATE TABLE #DbSchemas(
    DbName nvarchar(128) NULL,
    Table_Name sysname NOT NULL,
    [Column Name] sysname NULL,
    [Data type] sysname NOT NULL,
    [Max Length] smallint NOT NULL,
    is_nullable bit NULL,
    is_replicated bit NULL,
    [Primary Key] bit NOT NULL
)
GO

Затем оберните уже имеющийся запрос в недокументированную системную процедуру sp_MSforeachdb, чтобы выполнить его в каждой базе данных, добавив результаты в таблицу #DbSchemas:

EXECUTE master.sys.sp_MSforeachdb 'USE [?];
    INSERT INTO #DbSchemas
    SELECT DB_NAME() DbName,   a.name Table_Name, c.name [Column Name],
         t.Name [Data type],
         c.max_length [Max Length],
         c.is_nullable,a.is_replicated ,
         ISNULL(i.is_primary_key, 0) [Primary Key]
    FROM    Sys.tables a inner join      sys.columns c
    On A.object_id=C.object_id
    INNER JOIN 
         sys.types t ON c.user_type_id = t.user_type_id
    LEFT OUTER JOIN 
         sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
    LEFT OUTER JOIN 
         sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
         Order by 1,2
    ;
';
go

Теперь вы должны иметь возможность запрашивать данные из любой базы данных в таблице #DbSchemas:

select * from #DbSchemas where Dbname = 'master'

Наконец, чтобы сравнить их, вы можете использовать что-то вроде этого:

SELECT  * FROM #DbSchemas s1
WHERE   DbName = 'msdb'
  AND NOT EXISTS(
    SELECT  * FROM #DbSchemas s2 
    WHERE   s2.DbName           = 'master'
      AND   s2.Table_Name       = s1.Table_Name
      AND   s2.[Column Name]    = s1.[Column Name]
      AND   s2.[Data type]      = s1.[Data type]
      AND   s2.[Max length]     = s1.[Max length]
      AND   s2.is_nullable      = s1.is_nullable
      AND   s2.is_replicated    = s1.is_replicated
      AND   s2.[Primary Key]    = s1.[Primary Key]
      )
person RBarryYoung    schedule 29.07.2016
comment
Это именно то, что мне нужно. Ты обалденный - person Alok Singh; 29.07.2016