Generate Insert Scripts with IF NOT EXISTS - sql

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 (e.g. 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.

Related

Triggers-Implementation Issue

I am making 2 tables for implementing triggers –
create table emp(id int primary key identity(1,1),
name char(40),
salary varchar(50),
gender char(40),
departmentid int);
insert into emp(name,salary,gender,departmentid) values ('jimmi',4800,'Male',4);
create table emp_audit
(
id int primary key identity(1,1),
audit varchar(60)
);
alter trigger trigger_em_update on emp for update
as begin
Declare #Id int
Declare #oldname char(40),#newname char(40)
Declare #oldsal int,#newsal int
Declare #oldgen char(40),#newgen char(40)
Declare #olddeptid int,#newdeptid int
Declare #auditstring nvarchar(max)
--select * from deleted;
select * into #temptable from inserted;
while(Exists(select id from #temptable)) --boolean condition if there are rows are not
Begin
set #auditstring =''
--if there are many rows we still select the first one
select Top 1 #Id =id,#newname=name,#newgen=gender,#newsal=salary,#newdeptid=departmentid
from #temptable;
select Top 1 #Id =id,#oldname=name,#oldgen=gender,#oldsal=salary,#olddeptid=departmentid
from deleted where #Id=id;
set #auditstring=' Employee with id= '+CAST(#Id as varchar(20))+ ' changed '
if(#oldname<>#newname)
set #auditstring=#auditstring + 'name from '+ #oldname +' to' +#newname
if(#oldsal<>#newsal)
set #auditstring=#auditstring + ' salary from '+ #oldsal +' to ' +#newsal
if(#oldgen<>#newgen)
set #auditstring=#auditstring + ' gender from ' + #oldgen + ' to ' + #newgen
-- if(#olddeptid<>#newdeptid)
--set #auditstring=#auditstring + ' departmentid from ' + cast(#olddeptid as nvarchar(5))+' to '
insert into emp_audit values(#auditstring)
delete from #temptable where id=#Id
end
end
when i use update query
update emp set name='vishi',gender='male',salary='4000',departmentid=3 where id=3;
It gives an error
"Conversion failed when converting the nvarchar value ' Employee with id= 3 changed name from james tovishi salary from ' to data type int.
"
i don't know how to solve this..can you solve this..
The problem is in line:
if(#oldsal<>#newsal)
set #auditstring=#auditstring + ' salary from '+ #oldsal +' to ' +#newsal
Should be:
if(#oldsal<>#newsal)
set #auditstring=#auditstring+ ' salary from '+CAST(#oldsal AS NVARCHAR(100))
+' to ' +CAST(#newsal AS NVARCHAR(100))
A couple of thoughts:
It is a good practice to end each statement with semicolon
#oldsal<>#newsal won't detect changing from NULL to value or value to NULL
Row-by-row processing is not best practice from performance perspective(especially inside trigger's body)
set #auditstring=#auditstring +.... could be replaced with set #auditstring += ...
If any value that you are using to concatenate auditstring is NULL variable will be set to NULL.
I do not recommend to store name/variable as CHAR(size), it is better to use VARCHAR(size)
Tracking what has changed as single string will require parsing in the future(unless you only want to display it).
The problem is that one of the columns used with + is a number, probably salary. But your trigger is way too complicated.
SQL is a set-based language. So use the sets when you can:
alter trigger trigger_em_update on emp for update
as
begin
insert into emp_audit (auditstring) -- guessing the name
select ('Employee with id k= ' + CAST(#Id as varchar(20))+ ' changed ' +
(case when #oldname <> #newname
then 'name from '+ #oldname +' to ' + #newname + ' '
else ''
end) +
(case when #oldsal <> #oldsal
then 'salary from '+ convert(varchar(255), #oldsal) +' to ' + concvert(varchar(255), #newsal) + ' '
else ''
end) +
(case when #oldgen <> #newgen
then 'gender from '+ convert(varchar(255), #oldgen) +' to ' + concvert(varchar(255), #newgen) + ' '
else ''
end) +
(case when #olddeptid <> #newdeptid
then 'departmentid from '+ convert(varchar(255), #olddeptid) +' to ' + concvert(varchar(255), #newdeptid) + ' '
else ''
end)
) as auditstring
from inserted i join
deleted d
on i.id = d.id;
end;

SQL Server - Include table name programatically

I am in the process of writing a pretty large query that selects from multiple tables and unions them. Because of some really poor database design, a table is created for every user.
What I am doing is something like this:
SELECT *
FROM tbl1
UNION ALL
SELECT *
FROM tbl2
What I am looking for is something generic to add to each line that will enable me to select the table name along with what's inside the table.
I won't accept the below as an answer, because that is not what I've asked for.
SELECT *, 'tbl1'
FROM tbl1
UNION ALL
SELECT *, 'tbl2'
FROM tbl2
To do something like that you either have to make some rather complex and large query into the system views (sys.tables and sys.columns)
But you're properly better off building the query dynamically in what ever code lanuage you use and execute it as a string:
A very rough example could be something like
DECLARE #tableName varchar(255) = 'tbl1';
DECLARE #tableName2 varchar(255) = 'tbl2';
DECLARE #columnList varchar(255) = 'Col1, Col2, Col3';
EXEC(
'SELECT '+ #columnList +' FROM ' +#tableName + '
UNION ALL
SELECT '+ #columnList +' FROM ' +#tableName2
);
Before each select from the table add a SELECT NULL, NULL, 'tableName'; (add as many NULL as table columns so that union all doesn't 'fail'. Or Instead of NULL use '-' or whatever.
I guess the tables looping and obtaining the column names shouldn't be an issue..
Below demo:
create table #t1(C1 int, C2 int)
create table #t2(C1 int, C2 int)
insert #t1 (C1, C2) values (1,2)
insert #t2 (C1, C2) values (3,4)
insert #t2 (C1, C2) values (5,6)
declare #t1 varchar(10) = '#t1';
declare #t2 varchar(10) = '#t2';
declare #cols varchar(100) = 'C1, C2';
declare #sql nvarchar(4000) = ''
set #sql =
' SELECT NULL, NULL, ''' + #t1 + ''' ' + char(10) + char(13) +
' UNION ALL ' + char(10) + char(13) +
' SELECT '+ #cols +', NULL FROM ' + #t1 + char(10) + char(13) +
' UNION ALL ' + char(10) + char(13) +
' SELECT NULL, NULL, ''' + #t2 + ''' ' + char(10) + char(13) +
' UNION ALL ' + char(10) + char(13) +
' SELECT '+ #cols +', NULL FROM ' + #t2
-- select #sql
exec (#sql);
In production code you already need to construct a query that has FROM table_name so you should just add that table name in as a projected column at the same time.
Technically there is a way of doing this in versions that support dm_db_page_info though but this would be very inefficient and require elevated permissions.
CREATE TABLE dbo.T(X INT);
INSERT INTO T VALUES (1),(2),(3);
SELECT OBJECT_NAME(pg_info.object_id) AS table_name, T.*
FROM dbo.T
CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%) pl
CROSS APPLY sys.dm_db_page_info(db_id(), pl.file_id, pl.page_id, 'LIMITED') pg_info
Returns
+------------+---+
| table_name | X |
+------------+---+
| T | 1 |
| T | 2 |
| T | 3 |
+------------+---+

How to find the query for creating a table in SQL Server 2008

Is there a way to display the query for creating a table? For example, there is a table called CLIENT, and I want to see the query for creating this table. How can I do this?
Right Click on the table
Script Table as
CREATE to
New Query Editor Window
EDIT: Damn you have to be quick here for the easy rep! haha.
Right click the table in SSMS and select Script Table > As Create
If you want to do it from some script then here it is
declare #table varchar(100)
set #table = 'client_table' -- set table name here
declare #sql table(s varchar(1000), id int identity)
-- create statement
insert into #sql(s) values ('create table [' + #table + '] (')
-- column list
insert into #sql(s)
select
' ['+column_name+'] ' +
data_type + coalesce('('+cast(character_maximum_length as varchar)+')','') + ' ' +
case when exists (
select id from syscolumns
where object_name(id)=#table
and name=column_name
and columnproperty(id,name,'IsIdentity') = 1
) then
'IDENTITY(' +
cast(ident_seed(#table) as varchar) + ',' +
cast(ident_incr(#table) as varchar) + ')'
else ''
end + ' ' +
( case when IS_NULLABLE = 'No' then 'NOT ' else '' end ) + 'NULL ' +
coalesce('DEFAULT '+COLUMN_DEFAULT,'') + ','
from information_schema.columns where table_name = #table
order by ordinal_position
-- primary key
declare #pkname varchar(100)
select #pkname = constraint_name from information_schema.table_constraints
where table_name = #table and constraint_type='PRIMARY KEY'
if ( #pkname is not null ) begin
insert into #sql(s) values(' PRIMARY KEY (')
insert into #sql(s)
select ' ['+COLUMN_NAME+'],' from information_schema.key_column_usage
where constraint_name = #pkname
order by ordinal_position
-- remove trailing comma
update #sql set s=left(s,len(s)-1) where id=##identity
insert into #sql(s) values (' )')
end
else begin
-- remove trailing comma
update #sql set s=left(s,len(s)-1) where id=##identity
end
-- closing bracket
insert into #sql(s) values( ')' )
-- result!
select s from #sql order by id
this will give you the output like
create table [client_table] (
[colA] varchar(250) NOT NULL DEFAULT (''),
[colB] int NOT NULL DEFAULT(0)
)

Drop set of columns with only null values from a table using SQL Server 2008

Take for example this example as an illustration so you can see what Î'm trying to do.
This is how the final table of the pivoted information looks like.
Create Table [#Comparative]
(
Branch char(32),
[2004_January] numeric (18,2),
[2005_January] numeric (18,2),
[2006_January] numeric (18,2),
[2007_January] numeric (18,2),
[2008_January] numeric (18,2),
)
INSERT INTO [#Comparative]
VALUES ('Angeles', NULL, 13550.20, 7820.50, NULL, NULL),
('Detroit', NULL, 13550.20, 7820.50, NULL, NULL),
('New York', NULL, 13550.20, 7820.50, NULL, NULL),
('Arizona', NULL, 13550.20, 7820.50, NULL, NULL)
Select * from [#Comparative]
How could i create a procedure or statement
to drop the set of columns that contains only NULL values taking
into account the columns on the table will be changing as the table is created from other
query that takes information of daily sales to group sum(sales) monthly depending
on the interval of the selected date.
Dynamically create a SQL statement and then run that command. This script drop set of columns with only null values from a temporary table(passed as parameter in SP).
CREATE PROC dbo.dropColumn
#tempTableName nvarchar(100)
AS
BEGIN
DECLARE #dml nvarchar(max) = N''
SELECT #dml += 'IF (SELECT MIN(' + QUOTENAME(c.name) + ') FROM [dbo].' + QUOTENAME(#tempTableName) + ') IS NULL' + CHAR(13) + CHAR(10) +
'BEGIN' + CHAR(13) + CHAR(10) +
' EXEC (''ALTER TABLE [dbo].' + QUOTENAME(#tempTableName) + ' DROP COLUMN ' + QUOTENAME(c.name) + ''')' + CHAR(13) + CHAR(10) +
'END' + CHAR(13) + CHAR(10)
FROM tempdb.sys.tables t JOIN tempdb.sys.columns c ON t.object_id = c.object_id
WHERE t.object_id = OBJECT_ID('[tempdb].[dbo].' + QUOTENAME(#tempTableName))
--PRINT #dml
EXEC sp_executesql #dml
END
EXEC dbo.dropColumn '#Comparative'
Result:
Branch 2005_January 2006_January
----------------------------------------------------------------
Angeles 13550.20 7820.50
Detroit 13550.20 7820.50
New York 13550.20 7820.50
Arizona 13550.20 7820.50
try this : this is one example.
CREATE Stored Procedure.
CREATE PROCEDURE TestSP
(
#IsDroped BIT
)AS
BEGIN
declare #test int
declare #testcount int
set #testcount = (select COUNT(*) from mtp )
set #test = (select distinct 1 from mtp where name is null group by name having COUNT(*)=#testcount )
if #test = 1 AND #IsDroped = 1
begin
alter table mtp drop column name
end
END
Execute this SP
EXEC TestSP 1

Converting Select results into Insert script - SQL Server

I have SQL Server 2008, SQL Server Management Studio.
I need to select data from a table in one database and insert into another table in another database.
How can I convert the returned results from my select into INSERT INTO ...?
Clarification from comments: While I believe this could be solved by a INSERT INTO SELECT or SELECT INTO, I do need to generate INSERT INTO ....
Here is another method, which may be easier than installing plugins or external tools in some situations:
Do a select [whatever you need]INTO temp.table_namefrom [... etc ...].
Right-click on the database in the Object Explorer => Tasks => Generate Scripts
Select temp.table_name in the "Choose Objects" screen, click Next.
In the "Specify how scripts should be saved" screen:
Click Advanced, find the "Types of data to Script" property, select "Data only", close the advanced properties.
Select "Save to new query window" (unless you have thousands of records).
Click Next, wait for the job to complete, observe the resulting INSERT statements appear in a new query window.
Use Find & Replace to change all [temp.table_name] to [your_table_name].
drop table [temp.table_name].
In SSMS:
Right click on the database > Tasks > Generate Scripts
Next
Select "Select specific database objects" and check the table you want scripted, Next
Click Advanced > in the list of options, scroll down to the bottom and look for the "Types of data to script" and change it to "Data Only" > OK
Select "Save to new query window" > Next > Next > Finish
All 180 rows now written as 180 insert statements!
Native method:
for example if you have table
Users(Id, name)
You can do this:
select 'insert into Table values(Id=' + Id + ', name=' + name + ')' from Users
1- Explanation of Scripts
A)Syntax for inserting data in table is as below
Insert into table(col1,col2,col3,col4,col5)
-- To achieve this part i
--have used below variable
------#CSV_COLUMN-------
values(Col1 data in quote, Col2..quote,..Col5..quote)
-- To achieve this part
-- i.e column data in
--quote i have used
--below variable
----#QUOTED_DATA---
C)To get above data from existing
table we have to write the select
query in such way that the output
will be in form of as above scripts
D)Then Finally i have Concatenated
above variable to create
final script that's will
generate insert script on execution
E)
#TEXT='SELECT ''INSERT INTO
'+#TABLE_NAME+'('+#CSV_COLUMN+')VALUES('''+'+'+SUBSTRING(#QUOTED_DATA,1,LEN(#QUOTED_DATA)-5)+'+'+''')'''+' Insert_Scripts FROM '+#TABLE_NAME + #FILTER_CONDITION
F)And Finally Executed the above query EXECUTE(TEXT)
G)QUOTENAME() function is used to wrap
column data inside quote
H)ISNULL is used because if any row has NULL
data for any column the query fails
and return NULL thats why to avoid
that i have used ISNULL
I)And created the sp sp_generate_insertscripts
for same
1- Just put the table name for which you want insert script
2- Filter condition if you want specific results
----------Final Procedure To generate Script------
CREATE PROCEDURE sp_generate_insertscripts
(
#TABLE_NAME VARCHAR(MAX),
#FILTER_CONDITION VARCHAR(MAX)=''
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #CSV_COLUMN VARCHAR(MAX),
#QUOTED_DATA VARCHAR(MAX),
#TEXT VARCHAR(MAX)
SELECT #CSV_COLUMN=STUFF
(
(
SELECT ',['+ NAME +']' FROM sys.all_columns
WHERE OBJECT_ID=OBJECT_ID(#TABLE_NAME) AND
is_identity!=1 FOR XML PATH('')
),1,1,''
)
SELECT #QUOTED_DATA=STUFF
(
(
SELECT ' ISNULL(QUOTENAME('+NAME+','+QUOTENAME('''','''''')+'),'+'''NULL'''+')+'','''+'+' FROM sys.all_columns
WHERE OBJECT_ID=OBJECT_ID(#TABLE_NAME) AND
is_identity!=1 FOR XML PATH('')
),1,1,''
)
SELECT #TEXT='SELECT ''INSERT INTO '+#TABLE_NAME+'('+#CSV_COLUMN+')VALUES('''+'+'+SUBSTRING(#QUOTED_DATA,1,LEN(#QUOTED_DATA)-5)+'+'+''')'''+' Insert_Scripts FROM '+#TABLE_NAME + #FILTER_CONDITION
--SELECT #CSV_COLUMN AS CSV_COLUMN,#QUOTED_DATA AS QUOTED_DATA,#TEXT TEXT
EXECUTE (#TEXT)
SET NOCOUNT OFF
END
SSMS Toolpack (which is FREE as in beer) has a variety of great features - including generating INSERT statements from tables.
Update: for SQL Server Management Studio 2012 (and newer), SSMS Toolpack is no longer free, but requires a modest licensing fee.
It's possible to do via Visual Studio SQL Server Object Explorer.
You can click "View Data" from context menu for necessary table, filter results and save result as script.
Using visual studio, do the following
Create a project of type SQL Server-->SQL Server Database Project
open the sql server explorer CTL-\ , CTL-S
add a SQL Server by right clicking on the SQL SERVER icon. Selcet ADD NEW SERVER
navigate down to the table you are interested in
right click--> VIEW DATA
Click the top left cell to highlight everything (ctl-A doesnt seem to work)
Right Click -->SCript
This is fabulous. I have tried everything listed above over the years. I know there is a tool out there that will do this and much more, cant think of the name of it. But it is very expensive.
Good luck. I just figured this out. Have not tested it extensively w/ text fields etc, but it looks like it gets you a long ways down the road.
Greg
Create a separate table using into statement
For example
Select * into Test_123 from [dbo].[Employee] where Name like '%Test%'
Go to the Database
Right Click the Database
Click on Generate Script
Select your table
Select advanace option and select the Attribute "Data Only"
Select the file "open in new query"
Sql will generate script for you
This is a more versatile solution (that can do a little more than the question asks), and can be used in a query window without having to create a new stored proc - useful in production databases for instance where you don't have write access.
To use the code, please modify according to the in line comments which explain its usage. You can then just run this query in a query window and it will print the INSERT statements you require.
SET NOCOUNT ON
-- Set the ID you wish to filter on here
DECLARE #id AS INT = 123
DECLARE #tables TABLE (Name NVARCHAR(128), IdField NVARCHAR(128), IdInsert BIT, Excluded NVARCHAR(128))
-- Add any tables you wish to generate INSERT statements for here. The fields are as thus:
-- Name: Your table name
-- IdField: The field on which to filter the dataset
-- IdInsert: If the primary key field is to be included in the INSERT statement
-- Excluded: Any fields you do not wish to include in the INSERT statement
INSERT INTO #tables (Name, IdField, IdInsert, Excluded) VALUES ('MyTable1', 'Id', 0, 'Created,Modified')
INSERT INTO #tables (Name, IdField, IdInsert, Excluded) VALUES ('MyTable2', 'Id', 1, 'Created,Modified')
DECLARE #numberTypes TABLE (sysId TINYINT)
-- This will ensure INT and BIT types are not surrounded with quotes in the
-- resultant INSERT statement, but you may need to add more (from sys.types)
INSERT #numberTypes(SysId) VALUES(56),(104)
DECLARE #rows INT = (SELECT COUNT(*) FROM #tables)
DECLARE #cnt INT = 1
DECLARE #results TABLE (Sql NVARCHAR(4000))
WHILE #cnt <= #rows
BEGIN
DECLARE #tablename AS NVARCHAR(128)
DECLARE #idField AS NVARCHAR(128)
DECLARE #idInsert AS BIT
DECLARE #excluded AS NVARCHAR(128)
SELECT
#tablename = Name,
#idField = IdField,
#idInsert = IdInsert,
#excluded = Excluded
FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS RowId FROM #tables) t WHERE t.RowId = #cnt
DECLARE #excludedFields TABLE (FieldName NVARCHAR(128))
DECLARE #xml AS XML = CAST(('<X>' + REPLACE(#excluded, ',', '</X><X>') + '</X>') AS XML)
INSERT INTO #excludedFields SELECT N.value('.', 'NVARCHAR(128)') FROM #xml.nodes('X') AS T(N)
DECLARE #setIdentity NVARCHAR(128) = 'SET IDENTITY_INSERT ' + #tablename
DECLARE #execsql AS NVARCHAR(4000) = 'SELECT ''' + CASE WHEN #idInsert = 1 THEN #setIdentity + ' ON' + CHAR(13) ELSE '' END + 'INSERT INTO ' + #tablename + ' ('
SELECT #execsql = #execsql +
STUFF
(
(
SELECT CASE WHEN NOT EXISTS(SELECT * FROM #excludedFields WHERE FieldName = name) THEN ', ' + name ELSE '' END
FROM sys.columns
WHERE object_id = OBJECT_ID('dbo.' + #tablename)
FOR XML PATH('')
), 1, 2, ''
) +
')' + CHAR(13) + 'VALUES (' +
STUFF
(
(
SELECT
CASE WHEN NOT EXISTS(SELECT * FROM #excludedFields WHERE FieldName = name) THEN
''', '' + ISNULL(' +
CASE WHEN EXISTS(SELECT * FROM #numberTypes WHERE SysId = system_type_id) THEN '' ELSE ''''''''' + ' END +
'CAST(' + name + ' AS VARCHAR)' +
CASE WHEN EXISTS(SELECT * FROM #numberTypes WHERE SysId = system_type_id) THEN '' ELSE ' + ''''''''' END +
', ''NULL'') + '
ELSE ''
END
FROM sys.columns
WHERE object_id = OBJECT_ID('dbo.' + #tablename)
FOR XML PATH('')
), 1, 3, ''
) +
''')' + CASE WHEN #idInsert = 1 THEN CHAR(13) + #setIdentity + ' OFF' ELSE '' END +
''' FROM ' + #tablename + ' WHERE ' + #idField + ' = ' + CAST(#id AS VARCHAR)
INSERT #results EXEC (#execsql)
DELETE #excludedFields
SET #cnt = #cnt + 1
END
DECLARE cur CURSOR FOR SELECT Sql FROM #results
OPEN cur
DECLARE #sql NVARCHAR(4000)
FETCH NEXT FROM cur INTO #sql
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #sql
FETCH NEXT FROM cur INTO #sql
END
CLOSE cur
DEALLOCATE cur
You can Choose 'Result to File' option in SSMS and export your select result to file and make your changes in result file and finally using BCP - Bulk copy you can insert in table 1 in database 2.
I think for bulk insert you have to convert .rpt file to .csv file
Hope it will help.
I had a similar problem, but I needed to be able to create an INSERT statement from a query (with filters etc.)
So I created following procedure:
CREATE PROCEDURE dbo.ConvertQueryToInsert (#input NVARCHAR(max), #target NVARCHAR(max)) AS BEGIN
DECLARE #fields NVARCHAR(max);
DECLARE #select NVARCHAR(max);
-- Get the defintion from sys.columns and assemble a string with the fields/transformations for the dynamic query
SELECT
#fields = COALESCE(#fields + ', ', '') + '[' + name +']',
#select = COALESCE(#select + ', ', '') + ''''''' + ISNULL(CAST([' + name + '] AS NVARCHAR(max)), ''NULL'')+'''''''
FROM tempdb.sys.columns
WHERE [object_id] = OBJECT_ID(N'tempdb..'+#input);
-- Run the a dynamic query with the fields from #select into a new temp table
CREATE TABLE #ConvertQueryToInsertTemp (strings nvarchar(max))
DECLARE #stmt NVARCHAR(max) = 'INSERT INTO #ConvertQueryToInsertTemp SELECT '''+ #select + ''' AS [strings] FROM '+#input
exec sp_executesql #stmt
-- Output the final insert statement
SELECT 'INSERT INTO ' + #target + ' (' + #fields + ') VALUES (' + REPLACE(strings, '''NULL''', 'NULL') +')' FROM #ConvertQueryToInsertTemp
-- Clean up temp tables
DROP TABLE #ConvertQueryToInsertTemp
SET #stmt = 'DROP TABLE ' + #input
exec sp_executesql #stmt
END
You can then use it by writing the output of your query into a temp table and running the procedure:
-- Example table
CREATE TABLE Dummy (Id INT, Comment NVARCHAR(50), TimeStamp DATETIME)
INSERT INTO Dummy VALUES (1 , 'Foo', GetDate()), (2, 'Bar', GetDate()), (3, 'Foo Bar', GetDate())
-- Run query and procedure
SELECT * INTO #TempTableForConvert FROM Dummy WHERE Id < 3
EXEC dbo.ConvertQueryToInsert '#TempTableForConvert', 'dbo.Dummy'
Note:
This procedure only casts the values to a string which can cause the data to look a bit different. With DATETIME for example the seconds will be lost.
I created the following procedure:
if object_id('tool.create_insert', 'P') is null
begin
exec('create procedure tool.create_insert as');
end;
go
alter procedure tool.create_insert(#schema varchar(200) = 'dbo',
#table varchar(200),
#where varchar(max) = null,
#top int = null,
#insert varchar(max) output)
as
begin
declare #insert_fields varchar(max),
#select varchar(max),
#error varchar(500),
#query varchar(max);
declare #values table(description varchar(max));
set nocount on;
-- Get columns
select #insert_fields = isnull(#insert_fields + ', ', '') + c.name,
#select = case type_name(c.system_type_id)
when 'varchar' then isnull(#select + ' + '', '' + ', '') + ' isnull('''''''' + cast(' + c.name + ' as varchar) + '''''''', ''null'')'
when 'datetime' then isnull(#select + ' + '', '' + ', '') + ' isnull('''''''' + convert(varchar, ' + c.name + ', 121) + '''''''', ''null'')'
else isnull(#select + ' + '', '' + ', '') + 'isnull(cast(' + c.name + ' as varchar), ''null'')'
end
from sys.columns c with(nolock)
inner join sys.tables t with(nolock) on t.object_id = c.object_id
inner join sys.schemas s with(nolock) on s.schema_id = t.schema_id
where s.name = #schema
and t.name = #table;
-- If there's no columns...
if #insert_fields is null or #select is null
begin
set #error = 'There''s no ' + #schema + '.' + #table + ' inside the target database.';
raiserror(#error, 16, 1);
return;
end;
set #insert_fields = 'insert into ' + #schema + '.' + #table + '(' + #insert_fields + ')';
if isnull(#where, '') <> '' and charindex('where', ltrim(rtrim(#where))) < 1
begin
set #where = 'where ' + #where;
end
else
begin
set #where = '';
end;
set #query = 'select ' + isnull('top(' + cast(#top as varchar) + ')', '') + #select + ' from ' + #schema + '.' + #table + ' with (nolock) ' + #where;
insert into #values(description)
exec(#query);
set #insert = isnull(#insert + char(10), '') + '--' + upper(#schema + '.' + #table);
select #insert = #insert + char(10) + #insert_fields + char(10) + 'values(' + v.description + ');' + char(10) + 'go' + char(10)
from #values v
where isnull(v.description, '') <> '';
end;
go
Then you can use it that way:
declare #insert varchar(max),
#part varchar(max),
#start int,
#end int;
set #start = 1;
exec tool.create_insert #schema = 'dbo',
#table = 'customer',
#where = 'id = 1',
#insert = #insert output;
-- Print one line to avoid the maximum 8000 characters problem
while len(#insert) > 0
begin
set #end = charindex(char(10), #insert);
if #end = 0
begin
set #end = len(#insert) + 1;
end;
print substring(#insert, #start, #end - 1);
set #insert = substring(#insert, #end + 1, len(#insert) - #end + 1);
end;
The output would be something like that:
--DBO.CUSTOMER
insert into dbo.customer(id, name, type)
values(1, 'CUSTOMER NAME', 'F');
go
If you just want to get a range of rows, use the #top parameter as bellow:
declare #insert varchar(max),
#part varchar(max),
#start int,
#end int;
set #start = 1;
exec tool.create_insert #schema = 'dbo',
#table = 'customer',
#top = 100,
#insert = #insert output;
-- Print one line to avoid the maximum 8000 characters problem
while len(#insert) > 0
begin
set #end = charindex(char(10), #insert);
if #end = 0
begin
set #end = len(#insert) + 1;
end;
print substring(#insert, #start, #end - 1);
set #insert = substring(#insert, #end + 1, len(#insert) - #end + 1);
end;
You can Use Sql Server Integration Service Packages specifically designed for Import and Export operation.
VS has a package for developing these packages if your fully install Sql Server.
Integration Services in Business Intelligence Development Studio
I think its also possible with adhoc queries
you can export result to excel file and then import that file into your datatable object or use it as it is and then import the excel file into the second database
have a look at this link
this can help u alot.
http://vscontrols.blogspot.com/2010/09/import-and-export-excel-to-sql-server.html
If you are using Oracle (or configure the application to the SQL Server) then Oracle SQL Developer does this for you. choose 'unload' for a table and follow the options through (untick DDL if you don't want all the table create stuff).
I found this SMSMS Boost addon, which is free and does exactly this among other things. You can right click on the results and select Script data as.
You can use this Q2C.SSMSPlugin, which is free and open source. You can right click and select "Execute Query To Command... -> Query To Insert...". Enjoy)
You can use an INSERT INTO SELECT statement, to insert the results of a select query into a table. http://www.w3schools.com/sql/sql_insert_into_select.asp
Example:
INSERT INTO Customers (CustomerName, Country)
SELECT SupplierName, Country
FROM Suppliers
WHERE Country='Germany'