2014-01-14 2 views
4

У меня есть основная таблица в базе данных.Сгенерировать скрипты вставки с IF NOT EXISTS

таблицы Пример меню

+-----------+-----------+-------------+---------+------------------------+ 
| Id  | Key  | Display Text| ParentId| CreatedOn 
+-----------+-----------+-------------+---------+------------------------+ 
| 1   | Home  | Home  | NULL |2014-01-14 21:17:37.387 | 
| 2   | About  | About Us | NULL |2014-01-14 21:17:37.387 | 
| 3   | Contact | Contact Us | NULL |2014-01-14 21:17:37.387 | 
+-----------+-----------+------+------+---------+------------------------+ 

Я использовал для генерации сценария основных данных, как показано ниже для каждой записи.

IF NOT EXISTS(SELECT 1 FROM [Menu] WHERE Id=1 AND Key='Home') 
BEGIN 
SET IDENTITY_INSERT [dbo].[Menu] ON 

INSERT INTO [dbo].[Menu] 
      (Id 
      ,[Key] 
      ,[DisplayText] 
      ,[ParentId] 
      ,[CreatedOn]) 
    VALUES 
      (1 
      ,'Home' 
      ,'Home' 
      ,NULL 
      ,GETDATE() 
      ) 
SET IDENTITY_INSERT [dbo].[Menu] OFF 

END 
GO 

- Повторяя же ручную работу создания записи для всех 70 записей & других основных данные (10k rows)

Однако есть некоторые существующие таблицы ApplicationMenu в другой базе данных, имеющие тот же столбец, типы данные. Мы хотели бы создать сценарий ниже для нас, используя некоторую хранимую процедуру.

Можно ли создать процедуру, как показано ниже

CREATE PROCEDURE spGenerateInsertScripts 
(
    @SourceTableName VARCHAR(100), 
    @ExistsWhereClauseTemplate NVARCHAR(1000), 
    @TargetTableName VARCHAR(100) 
) 
BEGIN 

-- In some loop create those above insert statements 
END 

Мы хотели бы выполнить, как ниже

exec spGenerateInsertScripts 'ApplicationMenu' 
           , 'WHERE Id={Id} AND Key={Key}' 
           , 'Menu' 

Здесь {Id} & {Key} будет читать каждый строка из существующей таблицы и заменена.

Это фактически уменьшит количество ручной работы для нас.

Примечание:

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

нужно создать вставки скриптов, так что мы можем просто работать в будущем, даже если ApplicationTable не доступен

Можно ли написать такую ​​процедуру для создания вставки сценария из другой таблицы на основе существования? Как и sql server Generate Scripts work for table creation by looking into INFORMATION_SCHEMA таблица, я так и ожидаю.

Окончательный результат процедуры будет как PRINT @insert_Sql_Statements

+0

Итак, вы хотите использовать таблицу ApplicationMenu (в другой базе данных) для создания строк в базе данных меню (если эти строки еще не существуют). Использование столбцов Id и Key из ApplicationMenu? – Umair

+1

Почему вы просто не создаете хранимую процедуру, которая принимает параметр таблицы и передает значения хранимой процедуре и возвращает значения, которые были добавлены в целевую таблицу. ???? –

+0

@Umair, Да. Обе таблицы имеют одинаковое имя столбца, типы данных. Я хотел бы импортировать все ApplicationMenu в мою таблицу меню только в том случае, если они не существуют – Billa

ответ

2

Предполагая, что я понимаю вашу проблему правильно, то, что вы предлагаете (где положение в качестве параметра) не звучит слишком хорошо, и может вызвать ЦЕЛЫЙ много другого проблемы (например, SQL-инъекция, проверка строки SQL в правильном формате и т. д.).

Как насчет этого подхода, который использует связанные серверы

SET IDENTITY_INSERT [dbo].[Menu] ON 
GO 

INSERT INTO [dbo].[Menu] ([Id],[Key],[DisplayText],[ParentId],[CreatedOn]) 
SELECT a.Id, a.Key, a.Key, NULL, GETDATE() 
FROM [ApplicationMenu_Instance].[ApplicationMenu_Database].[dbo].[ApplicationMenu] AS a 
WHERE NOT EXISTS (
    SELECT 1 
    FROM [dbo].[Menu] AS m 
    WHERE m.Id = a.Id 
     AND m.Key = a.Key 
) 

SET IDENTITY_INSERT [dbo].[Menu] OFF 
GO 

UPDATE: Так как вы хотите, чтобы вернуть сценарий вставки, как о динамическом SQL, то:

CREATE PROCEDURE spGenerateInsertScripts 
(
    @SourceTable VARCHAR(100), 
    @TargetTable VARCHAR(100) 
) 
BEGIN 
    DECLARE @SQL NVARCHAR(MAX) = ' 
    SET IDENTITY_INSERT [dbo].[Menu] ON 
    GO 

    INSERT INTO [dbo].[' + @TargetTable + '] ([Id],[Key],[DisplayText],[ParentId],[CreatedOn]) 
    SELECT a.Id, a.Key, a.Key, NULL, GETDATE() 
    FROM ' + @SourceTable + ' AS a 
    WHERE NOT EXISTS (
     SELECT 1 
     FROM [dbo].[' + @TargetTable + '] AS m 
     WHERE m.Id = a.Id 
      AND m.Key = a.Key 
    ) 

    SET IDENTITY_INSERT [dbo].[Menu] OFF 
    GO 
    '; 

    SELECT @SQL; 
END 
+0

Но мне это нужно как 'TEXT SCRIPT', так что я могу запустить это в любое время, даже если приложение не доступно. Я хочу сгенерировать текст сценария, когда ApplicationMenu доступен, после чего я хочу повторно запустить любое время. – Billa

+0

Извините, я не совсем понимаю. Почему вы не можете просто создать sp с кодом выше, а затем выполнить его, когда захотите? – Umair

+0

Вы хотите, чтобы вы могли определить местоположение таблицы меню исходного приложения (путем передачи в параметр)? – Umair

2

Ваши данные

DECLARE @Table TABLE(Id INT, [Key] VARCHAR(30),[Display Text] VARCHAR(30), ParentId INT, CreatedOn DATETIME) 
INSERT INTO @Table VALUES 
(1,'Home' ,'Home'  ,NULL, '2014-01-14 21:17:37.387'), 
(2,'About' ,'About Us' ,NULL, '2014-01-14 21:17:37.387'), 
(3,'Contact','Contact Us',NULL, '2014-01-14 21:17:37.387') 

запросов для создания сценария

SELECT N'IF NOT EXISTS(SELECT 1 FROM [Menu] WHERE Id='+ CAST(Id AS NVARCHAR(10)) 
     + ' AND Key='''+ CAST([Key] AS NVARCHAR(1000)) +''')' + CHAR(10) 
     + N'BEGIN ' + CHAR(10) + ' 
     SET IDENTITY_INSERT [dbo].[Menu] ON ' + CHAR(10) + ' 

     INSERT INTO [dbo].[Menu]  ' + CHAR(10) + ' 
        (Id ' + CHAR(10) + ' 
        ,[Key] ' + CHAR(10) + ' 
        ,[DisplayText]' + CHAR(10) + ' 
        ,[ParentId]' + CHAR(10) + ' 
        ,[CreatedOn])' + CHAR(10) + ' 
      VALUES' + CHAR(10) + ' 
        (' + ISNULL(CAST(Id AS NVARCHAR(10)), 'NULL') + ' ' + CHAR(10) + ' 
        ,''' + ISNULL(CAST([Key] AS NVARCHAR(1000)), 'NULL') +''' ' + CHAR(10) + ' 
        ,''' + ISNULL(CAST([Display Text] AS NVARCHAR(1000)), 'NULL') + ''' ' + CHAR(10) + ' 
        ,' + ISNULL(CAST(ParentId AS NVARCHAR(10)), 'NULL') + ' ' + CHAR(10) + ' 
        ,GETDATE() ' + CHAR(10) + ' 
        ) ' + CHAR(10) + ' 
     SET IDENTITY_INSERT [dbo].[Menu] OFF ' + CHAR(10) + ' 
     END ' + CHAR(10) + ' 
     GO ' + CHAR(10) + ' '+ CHAR(10) 
FROM @Table 

Сформирован сценарий

╔════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗ 
║                                                       (No column name)                                                       ║ 
╠════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣ 
║ IF NOT EXISTS(SELECT 1 FROM [Menu] WHERE Id=1 AND Key='Home') BEGIN  SET IDENTITY_INSERT [dbo].[Menu] ON   INSERT INTO [dbo].[Menu]     (Id    ,[Key]   ,[DisplayText]   ,[ParentId]   ,[CreatedOn])  VALUES   (1   ,'Home'   ,'Home'   ,NULL   ,GETDATE()   )  SET IDENTITY_INSERT [dbo].[Menu] OFF  END  GO     ║ 
║ IF NOT EXISTS(SELECT 1 FROM [Menu] WHERE Id=2 AND Key='About') BEGIN  SET IDENTITY_INSERT [dbo].[Menu] ON   INSERT INTO [dbo].[Menu]     (Id    ,[Key]   ,[DisplayText]   ,[ParentId]   ,[CreatedOn])  VALUES   (2   ,'About'   ,'About Us'   ,NULL   ,GETDATE()   )  SET IDENTITY_INSERT [dbo].[Menu] OFF  END  GO   ║ 
║ IF NOT EXISTS(SELECT 1 FROM [Menu] WHERE Id=3 AND Key='Contact') BEGIN  SET IDENTITY_INSERT [dbo].[Menu] ON   INSERT INTO [dbo].[Menu]     (Id    ,[Key]   ,[DisplayText]   ,[ParentId]   ,[CreatedOn])  VALUES   (3   ,'Contact'   ,'Contact Us'   ,NULL   ,GETDATE()   )  SET IDENTITY_INSERT [dbo].[Menu] OFF  END  GO  ║ 
╚════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝ 

Примечание

Я получил результаты назад в Grid, но вы можете экспортировать результаты в файл или текст и скопировать его в окно запроса, когда вы хотите для его выполнения.

+0

Awwww, на 24 минуты медленнее, в основном, тот же ответ. +1 к вам, сэр, для того, чтобы попасть туда первым. –

2

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

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

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

DECLARE @TARGET_TABLE AS VARCHAR(100) = '[dbo].[Menu]' 

SELECT Script 
FROM 
(
    SELECT Id, [Key], 0 AS [Order], 
     'IF NOT EXISTS(SELECT 1 FROM ' + @TARGET_TABLE + 
     ' WHERE Id=' + CONVERT(varchar(100), Id) + 
     ' AND Key=''' + [Key] + ''')' AS Script 
    FROM ApplicationMenu 
    UNION 
    SELECT Id, [Key], 1 AS [Order], 'BEGIN' AS Script 
    FROM ApplicationMenu 
    UNION 
    SELECT Id, [Key], 2, 'SET IDENTITY_INSERT ' + @TARGET_TABLE + ' ON' 
    FROM ApplicationMenu 
    UNION 
    SELECT Id, [Key], 3, 
     'INSERT INTO ' + @TARGET_TABLE + 
     ' VALUES(' + 
     CONVERT(varchar(11), Id) + ', ''' + 
     [Key] + ''', ''' + 
     [DisplayText] + ''', ' + 
     ISNULL(CONVERT(varchar(11), ParentId), 'NULL') + 
     ', GETDATE())' 
    FROM ApplicationMenu 
    UNION 
    SELECT Id, [Key], 4, 'SET IDENTITY_INSERT ' + @TARGET_TABLE + ' OFF' 
    FROM ApplicationMenu 
    UNION 
    SELECT Id, [Key], 5, 'END' 
    FROM ApplicationMenu 
) AS ScriptInfo 
ORDER BY Id, [Key], [Order] 

Честно говоря, сценарий немного больно смотреть, но он выполняет свою работу.

Если вы действительно хотите получить общее решение проблемы, вам, вероятно, повезло бы реализовать ее на каком-то языке программирования (например, C#). Потенциал его реализации в C# заключается в том, что вы можете импортировать библиотеку на SQL-сервер и называть ее как хранимую процедуру (я думаю, я никогда раньше этого не делал).

Кроме того, есть инструменты, которые будут генерировать этот скрипт для вас. Если я правильно помню, RedGate SQL Data Compare будет делать это довольно легко. Возможно, есть и другие.

+0

+1 за то, что в итоге попал туда :) –