Sql 生成插入脚本(如果不存在)
我在数据库中有一个主表 示例菜单表Sql 生成插入脚本(如果不存在),sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我在数据库中有一个主表 示例菜单表 +-----------+-----------+-------------+---------+------------------------+ | Id | Key | Display Text| ParentId| CreatedOn +-----------+-----------+-------------+---------+------------------------+ | 1 | Home
+-----------+-----------+-------------+---------+------------------------+
| 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行
)
但是,另一个数据库中的某些现有表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'
我们希望执行如下操作
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 server插入脚本生成工具,因为我们希望检查数据是否存在,并且需要保留用户使用我们的应用程序添加的记录
需要生成一个插入脚本,以便我们可以在将来运行,即使ApplicationTable不可用
是否可以编写这样一个过程,根据存在性从其他表生成插入脚本?就像sql server生成脚本如何通过查看信息\u SCHEMA
表来创建表一样,这与我期望的方式相同
该过程的最终输出类似于
PRINT@insert\u Sql\u Statements
假设我正确理解了您的问题,您的建议(where子句作为参数)听起来不太好,可能会导致大量其他问题(例如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
更新:
既然要返回插入脚本,那么动态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
您的数据
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 ║
╚════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
生成的脚本
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 ║
╚════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
注意
我在
网格中得到了结果,但您可以将结果导出到文件或文本中,并在需要执行时将其复制粘贴到查询窗口中 您可以使用SQL语句生成所需的insert语句。然后,您可以将输出复制并粘贴到您想要执行查询的任何位置
它不是一个通用的解决方案,可以创建一个脚本,从另一个表向一个表中生成insert语句,但它将大大减少特定情况下所需的手动工作。您可以配置目标表的名称,但列名和值以及从中检索数据的表的名称是硬编码的
它假定输入的目标表与从中检索数据的表具有相同的模式
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 server并像调用存储过程一样调用它(我想,我以前从未做过这种事情)
此外,还有一些工具可以为您生成此类脚本。如果我没记错的话,RedGate SQL数据比较将非常容易地完成这类工作。可能还有其他行。因此您希望使用ApplicationMenu表(在其他数据库中)在菜单数据库中创建行(如果这些行还不存在)。使用ApplicationMenu中的Id和Key列?为什么不创建一个存储过程,它接受表值参数并将值传递给存储过程,然后返回添加到目标表中的值呢@乌米尔,是的。这两个表具有相同的列名和数据类型。我想将所有ApplicationMenu导入到我的菜单表中,但前提是它们不是exists@M.Ali,我需要一个插入脚本,以便以后可以随时运行,即使ApplicationMenu表不可用。但我需要它作为文本脚本
,以便即使ApplicationMenu不可用,我也可以随时运行该脚本。我想在ApplicationMenu可用时生成脚本文本,之后我想随时重新运行。对不起,我不太明白。为什么不能用上面的代码创建一个sp,然后在需要时执行它?是否需要它,以便可以决定源应用程序菜单表的位置(通过传递参数)?我看起来类似于使用sql server生成脚本工具生成存储过程脚本。在数据库中不存在表时,可以选择创建表。因此,通过检查INFORMATION\u SCHEMA
table,它将自动为我们生成一个表脚本。同样,我希望使用value语句,而不是从ApplicationMenu
中选择a.Id、a.Key、a.Key、NULL、GETDATE()。请检查我的问题。到现在为止,我正在逐一插入。我想要一些助手程序通过读取另一个表来生成这些记录。Awwww,对于基本相同的答案,要慢24分钟+谢谢你,先生,先到那儿。