I have a master table in a database.
Example Menu table
+-----------+-----------+-------------+---------+------------------------+
| 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 |
+-----------+-----------+------+------+---------+------------------------+
I used to generate master data script like below for each record.
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
-- Repeating same manual record creation work for all 70 records & other master data( 10k rows
)
However there is some existing table ApplicationMenu
in another database is having same column, datatypes. We would like to generate the below script automatically for us by using some stored procedure.
Is it possible to create a procedure like below
CREATE PROCEDURE spGenerateInsertScripts
(
@SourceTableName VARCHAR(100),
@ExistsWhereClauseTemplate NVARCHAR(1000),
@TargetTableName VARCHAR(100)
)
BEGIN
-- In some loop create those above insert statements
END
We would like to execute like below
exec spGenerateInsertScripts 'ApplicationMenu'
, 'WHERE Id={Id} AND Key={Key}'
, 'Menu'
Here the {Id} & {Key} will be read from every row from existing table and replaced.
This will actually reduce lot of manual work for us.
Note:
We could not use SQL server insert script generation tool, since we want to check the data existence as well as need to keep the records added by user using our application.
Need to generate a insert scripts so that we can just run in future, even when ApplicationTable is not available
Is it possible to write such a procedure to generate insert script from other table based on existence? Like how sql server Generate Scripts work for table creation by looking into INFORMATION_SCHEMA
table, same way I am expecting for this.
Final output of the procedure would be like PRINT @insert_Sql_Statements
Your Data
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')
Query to Create Script
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
Generated Script
╔════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
║ (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 ║
╚════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
Note
I have got results back in Grid
but you can export the results to a file or to text and copy paste it into your query window when you want to execute it.
Assuming I understand your problem correctly, what you're proposing (where clause as a parameter) doesn't sound too good and can cause a WHOLE lot of other issues (eg SQL injection, verifying SQL string is in correct format, etc).
How about this approach, which uses linked servers
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: Since you want to return the insert script, how about dynamic SQL then:
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
You can use an SQL statement to generate the required insert statements. You can then just copy and paste the output into wherever you want to execute the query.
Its not a generic solution to creating a script that generates insert statements into one table from another table, but it will dramatically reduce the manual work required for your specific case. You can configure the name of the target table, but the column names and values and the name of the table the data is being retrieved from are hardcoded.
It assumes that the target table entered has the same schema as the table the data is being retrieved from.
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]
Honestly, the script is a bit painful to look at, but it gets the job done.
If you truly want a generic solution to the problem, you'll probably have more luck implementing it in some sort of programming language (like C#). The upside of implementing it in C# is that you can then import the library into SQL server and call it like a stored procedure (I think, I've never done that sort of thing before).
Additionally there are tools available that will do generate this sort of script for you. If I remember correctly, RedGate SQL Data Compare will do this sort of thing fairly easily. There are probably others.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.