В SQL Server 2008, как я должен копировать данные из базы данных в другую базу данных? - PullRequest
2 голосов
/ 04 августа 2010

Я пытаюсь написать хранимую процедуру для копирования подмножества данных из одного набора таблиц в идентичный набор таблиц в другой базе данных.Исходная база данных должна быть параметром для хранимой процедуры.

Я боролся с этим уже два дня, и я подумал, что у меня есть хорошее решение:

  1. Убедитесь, что схемы совпадают.
  2. Создайте временные синонимы "rmt" для исходных таблиц, используя динамический SQL.
  3. Скопируйте данные, используя INSERT INTO A SELECT * FRMT WHERE
  4. Удалите синонимы.

Это работает довольно хорошо для большинства таблиц, но для таблиц, содержащих столбец идентификаторов, я вынужден не только включать и выключать SET IDENTITY_INSERT, но дажехуже, я не могу использовать SELECT *;Я должен указать все столбцы явно.Это будет кошмаром, если я добавлю или удалю столбцы позже.

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

Помощь?

1 Ответ

1 голос
/ 04 августа 2010

Похоже, вы используете динамический SQL в своей хранимой процедуре, поэтому вы готовы динамически создавать свой список столбцов в предложении SELECT.

Вы можете выбрать из sys.columns, чтобы получить список столбцов и узнать, есть ли в таблице столбец идентификаторов. Вот запрос, который показывает информацию, необходимую для создания списка столбцов.

SELECT c.name, is_identity
FORM sys.columns c
WHERE object_id = object_id('MyTable')

Короче говоря, если is_identity равно 1 хотя бы для одного столбца, вам нужно будет включить SET IDENTITY_INSERT. И вы исключили бы любые столбцы из предложения SELECT, где is_identity = 1.

И этот подход адаптируется к новым столбцам, добавляемым в таблицы.

Вот пример

DECLARE @TableName varchar(128) = 'MyTableName'
DECLARE @ColumnName varchar(128)
DECLARE @IsIdentity bit
DECLARE @TableHasIdentity bit = 0
DECLARE @sql varchar(2000) = 'SELECT '

-- create cursor to step through list of columns
DECLARE MyCurs CURSOR FOR
SELECT c.name, is_identity
FROM sys.columns c
WHERE object_id = object_id(@TableName)
ORDER BY column_id

-- open cursor and get first row
OPEN MyCurs
FETCH NEXT FROM MyCurs INTO @ColumnName, @IsIdentity

-- process each column in the table
WHILE @@FETCH_STATUS = 0
  BEGIN
    IF @IsIdentity = 0
-- add column to the SELECT clause
        SET @sql = @sql + @ColumnName + ', '
    ELSE
-- indicate that table has identity column  
        SET @TableHasIdentity = 1

-- get next column
    FETCH NEXT FROM MyCurs INTO @ColumnName, @IsIdentity
  END

-- cursor cleanup
CLOSE MyCurs
DEALLOCATE MyCurs

-- add FROM clause
SET @sql = LEFT(@sql, LEN(@sql)-1) + CHAR(13) + CHAR(10) + 'FROM ' + @TableName

-- add SET IDENTITY if necessary
IF @TableHasIdentity = 1
    SET @sql = 'SET IDENTITY_INSERT ' + @TableName + ' ON' + CHAR(13) + CHAR (10)
                + @sql + CHAR(13) + CHAR (10)
                + 'SET IDENTITY_INSERT ' + @TableName + ' OFF'

PRINT @sql
...