将表里的数据批量生成INSERT语句的存储过程 增强版
将表里的数据批量生成INSERT语句的存储过程 增强版
有时候,我们需要将某个表里的数据全部或者根据查询条件导出来,迁移到另一个相同结构的库中
目前SQL Server里面是没有相关的工具根据查询条件来生成INSERT语句的,只有借助第三方工具(third party tools)
这种脚本网上也有很多,但是网上的脚本还是欠缺一些规范和功能,例如:我只想导出特定查询条件的数据,网上的脚本都是导出全表数据
如果表很大,对性能会有很大影响
这里有一个存储过程(适用于SQLServer2005 或以上版本)
-- Author: <桦仔>
-- Blog: <http://www.cnblogs.com/lyhabc/>
-- Create date: <2014/10/18>
-- Description: <根据查询条件导出表数据的insert脚本>
-- =============================================
CREATE PROCEDURE InsertGenerator
(
@tableName NVARCHAR(MAX),
@whereClause NVARCHAR(MAX)
)
AS --Then it includes a cursor to fetch column specific information (column name and the data type thereof)
--from information_schema.columns pseudo entity and loop through for building the INSERT and VALUES clauses
--of an INSERT DML statement. DECLARE @string NVARCHAR(MAX) --for storing the first half of INSERT statement
DECLARE @stringData NVARCHAR(MAX) --for storing the data (VALUES) related statement
DECLARE @dataType NVARCHAR(MAX) --data types returned for respective columns
DECLARE @schemaName NVARCHAR(MAX) --schema name returned from sys.schemas
DECLARE @schemaNameCount int--shema count
DECLARE @QueryString NVARCHAR(MAX) -- provide for the whole query, set @QueryString=' ' --如果有多个schema,选择其中一个schema
SELECT @schemaNameCount=COUNT(*)
FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE t.name = @tableName WHILE(@schemaNameCount>0)
BEGIN --如果有多个schema,依次指定
select @schemaName = name
from
(
SELECT ROW_NUMBER() over(order by s.schema_id) RowID,s.name
FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE t.name = @tableName
) as v
where RowID=@schemaNameCount --Declare a cursor to retrieve column specific information
--for the specified table
DECLARE cursCol CURSOR FAST_FORWARD
FOR
SELECT column_name ,
data_type
FROM information_schema.columns
WHERE table_name = @tableName
AND table_schema = @schemaName OPEN cursCol
SET @string = 'INSERT INTO [' + @schemaName + '].[' + @tableName + ']('
SET @stringData = '' DECLARE @colName NVARCHAR(500) FETCH NEXT FROM cursCol INTO @colName, @dataType PRINT @schemaName
PRINT @colName
IF @@fetch_status <> 0
BEGIN
PRINT 'Table ' + @tableName + ' not found, processing skipped.'
CLOSE curscol
DEALLOCATE curscol
RETURN
END WHILE @@FETCH_STATUS = 0
BEGIN
IF @dataType IN ( 'varchar', 'char', 'nchar', 'nvarchar' )
BEGIN
SET @stringData = @stringData + '''''''''+
isnull(' + @colName + ','''')+'''''',''+'
END
ELSE
IF @dataType IN ( 'text', 'ntext' ) --if the datatype
--is text or something else
BEGIN
SET @stringData = @stringData + '''''''''+
isnull(cast(' + @colName + ' as nvarchar(max)),'''')+'''''',''+'
END
ELSE
IF @dataType = 'money' --because money doesn't get converted
--from varchar implicitly
BEGIN
SET @stringData = @stringData
+ '''convert(money,''''''+
isnull(cast(' + @colName
+ ' as nvarchar(max)),''0.0000'')+''''''),''+'
END
ELSE
IF @dataType = 'datetime'
BEGIN
SET @stringData = @stringData
+ '''convert(datetime,''''''+
isnull(cast(' + @colName + ' as nvarchar(max)),'''')+''''''),''+'
END
ELSE
IF @dataType = 'image'
BEGIN
SET @stringData = @stringData + '''''''''+
isnull(cast(convert(varbinary,' + @colName + ')
as varchar(6)),'''')+'''''',''+'
END
ELSE --presuming the data type is int,bit,numeric,decimal
BEGIN
SET @stringData = @stringData + '''''''''+
isnull(cast(' + @colName + ' as nvarchar(max)),'''')+'''''',''+'
END SET @string = @string + '[' + @colName + ']' + ',' FETCH NEXT FROM cursCol INTO @colName, @dataType
END
--After both of the clauses are built, the VALUES clause contains a trailing comma which needs to be replaced with a single quote. The prefixed clause will only face removal of the trailing comma. DECLARE @Query NVARCHAR(MAX) -- provide for the whole query,
-- you may increase the size
PRINT @whereClause
IF ( @whereClause IS NOT NULL
AND @whereClause <> ''
)
BEGIN
SET @query = 'SELECT ''' + SUBSTRING(@string, 0, LEN(@string))
+ ') VALUES(''+ ' + SUBSTRING(@stringData, 0,
LEN(@stringData) - 2)
+ '''+'')''
FROM ' +@schemaName+'.'+ @tableName + ' WHERE ' + @whereClause
PRINT @query
-- EXEC sp_executesql @query --load and run the built query
--Eventually, close and de-allocate the cursor created for columns information.
END
ELSE
BEGIN
SET @query = 'SELECT ''' + SUBSTRING(@string, 0, LEN(@string))
+ ') VALUES(''+ ' + SUBSTRING(@stringData, 0,
LEN(@stringData) - 2)
+ '''+'')''
FROM ' + @schemaName+'.'+ @tableName END CLOSE cursCol
DEALLOCATE cursCol SET @schemaNameCount=@schemaNameCount-1
IF(@schemaNameCount=0)
BEGIN
SET @QueryString=@QueryString+@query
END
ELSE
BEGIN
SET @QueryString=@QueryString+@query+' UNION ALL '
END
PRINT convert(varchar(max),@schemaNameCount)+'---'+@QueryString
END
EXEC sp_executesql @QueryString --load and run the built query
--Eventually, close and de-allocate the cursor created for columns information.
这里要声明一下,如果你有多个schema,并且每个schema下面都有同一张表,那么脚本只会生成其中一个schema下面的表insert脚本
比如我现在有三个schema,下面都有customer这个表
CREATE TABLE dbo.[customer](city int,region int) CREATE SCHEMA test
CREATE TABLE test.[customer](city int,region int) CREATE SCHEMA test1
CREATE TABLE test1.[customer](city int,region int)
在执行脚本的时候他只会生成dbo这个schema下面的表insert脚本
INSERT INTO [dbo].[customer]([city],[region]) VALUES('','')
这个脚本有一个缺陷
无论你的表的字段是什麽数据类型,导出来的时候只能是字符
表结构
CREATE TABLE [dbo].[customer](city int,region int)
导出来的insert脚本
INSERT INTO [dbo].[customer]([city],[region]) VALUES('','')
我这里演示一下怎麽用
有两种方式
1、导全表数据
InsertGenerator 'customer', null
或
InsertGenerator 'customer', ' '

2、根据查询条件导数据
InsertGenerator 'customer', 'city=3'
或者
InsertGenerator 'customer', 'city=3 and region=8'

点击一下,选择全部

然后复制

新建一个查询窗口,然后粘贴

其实SQLServer的技巧有很多
最后,大家可以看一下代码,非常简单,如果要支持SQLServer2000,只要改一下代码就可以了
补充:创建一张测试表
CREATE TABLE testinsert (id INT,name VARCHAR(100),cash MONEY,dtime DATETIME) INSERT INTO [dbo].[testinsert]
( [id], [name], [cash], [dtime] )
VALUES ( 1, -- id - int
'nihao', -- name - varchar(100)
8.8, -- cash - money
GETDATE() -- dtime - datetime
) SELECT * FROM [dbo].[testinsert]
测试
InsertGenerator 'testinsert' ,'' InsertGenerator 'testinsert' ,'name=''nihao''' InsertGenerator 'testinsert' ,'name=''nihao'' and cash=8.8'
datetime类型会有一些问题
生成的结果会自动帮你转换
INSERT INTO [dbo].[testinsert]([id],[name],[cash],[dtime]) VALUES('','nihao',convert(money,'8.80'),convert(datetime,'02 8 2015 5:17PM'))
群里的人共享的另一个脚本
IF OBJECT_ID('spGenInsertSQL','P') IS NOT NULL
DROP PROC spGenInsertSQL
GO
CREATE proc spGenInsertSQL (@tablename varchar(256),@number BIGINT,@whereClause NVARCHAR(MAX))
as
begin
declare @sql varchar(8000)
declare @sqlValues varchar(8000)
set @sql =' ('
set @sqlValues = 'values (''+'
select @sqlValues = @sqlValues + cols + ' + '','' + ' ,@sql = @sql + '[' + name + '],'
from
(select case
when xtype in (48,52,56,59,60,62,104,106,108,122,127)
then 'case when '+ name +' is null then ''NULL'' else ' + 'cast('+ name + ' as varchar)'+' end'
when xtype in (58,61,40,41,42)
then 'case when '+ name +' is null then ''NULL'' else '+''''''''' + ' + 'cast('+ name +' as varchar)'+ '+'''''''''+' end'
when xtype in (167)
then 'case when '+ name +' is null then ''NULL'' else '+''''''''' + ' + 'replace('+ name+','''''''','''''''''''')' + '+'''''''''+' end'
when xtype in (231)
then 'case when '+ name +' is null then ''NULL'' else '+'''N'''''' + ' + 'replace('+ name+','''''''','''''''''''')' + '+'''''''''+' end'
when xtype in (175)
then 'case when '+ name +' is null then ''NULL'' else '+''''''''' + ' + 'cast(replace('+ name+','''''''','''''''''''') as Char(' + cast(length as varchar) + '))+'''''''''+' end'
when xtype in (239)
then 'case when '+ name +' is null then ''NULL'' else '+'''N'''''' + ' + 'cast(replace('+ name+','''''''','''''''''''') as Char(' + cast(length as varchar) + '))+'''''''''+' end'
else '''NULL'''
end as Cols,name
from syscolumns
where id = object_id(@tablename)
) T
IF (@number!=0 AND @number IS NOT NULL)
BEGIN
set @sql ='select top '+ CAST(@number AS VARCHAR(6000))+' ''INSERT INTO ['+ @tablename + ']' + left(@sql,len(@sql)-1)+') ' + left(@sqlValues,len(@sqlValues)-4) + ')'' from '+@tablename
print @sql
END
ELSE
BEGIN
set @sql ='select ''INSERT INTO ['+ @tablename + ']' + left(@sql,len(@sql)-1)+') ' + left(@sqlValues,len(@sqlValues)-4) + ')'' from '+@tablename
print @sql
END
PRINT @whereClause
IF ( @whereClause IS NOT NULL AND @whereClause <> '')
BEGIN
set @sql =@sql+' where '+@whereClause
print @sql
END
exec (@sql)
end
GO
调用示例
--非dbo默认架构需注意
--支持数据类型 :bigint,int, bit,char,datetime,date,time,decimal,money, nvarchar(50),tinyint, nvarchar(max),varchar(max),datetime2
--调用示例 如果top行或者where条件为空,只需要把参数填上null spGenInsertSQL 'customer' --表名
, 2 --top 行数
, 'city=3 and didian=''大连'' ' --where 条件 --导出全表 where条件为空
spGenInsertSQL 'customer' --表名
, null --top 行数
,null --where 条件 INSERT INTO [Department] ([DepartmentID],[Name],[GroupName],[Company],[ModifiedDate]) values (1,N'售后部',N'销售组',N'中国你好有限公司XX分公司','05 5 2015 5:58PM')
INSERT INTO [Department] ([DepartmentID],[Name],[GroupName],[Company],[ModifiedDate]) values (2,N'售后部',N'销售组',N'中国你好有限公司XX分公司','05 5 2015 5:58PM')
如有不对的地方,欢迎大家拍砖o(∩_∩)o
本文版权归作者所有,未经作者同意不得转载。
将表里的数据批量生成INSERT语句的存储过程 增强版的更多相关文章
- 将表里的数据批量生成INSERT语句的存储过程 继续增强版
文章继续 桦仔兄的文章 将表里的数据批量生成INSERT语句的存储过程 增强版 继续增强... 本来打算将该内容回复于桦仔兄的文章的下面的,但是不知为何博客园就是不让提交!.... 所以在这里贴出来吧 ...
- 将表里的数据批量生成INSERT语句的存储过程
有时候,我们需要将某个表里的数据全部导出来,迁移到另一个相同结构的库中,这里可以采取一个简便的方法,通过一个存储过程批量导出数据并生成SQL语句,非常方便.存储过程如下: )) as begin de ...
- 自由导入你的增量数据-根据条件将sqlserver表批量生成INSERT语句的存储过程实施笔记
文章标题: 自由导入你的增量数据-根据条件将sqlserver表批量生成INSERT语句的存储过程增强版 关键字 : mssql-scripter,SQL Server 文章分类: 技术分享 创建时间 ...
- 转载-用excel批量生成insert语句
用excel批量生成insert语句 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/h ...
- 用excel批量生成insert语句
excel表格中有A.B.C三列数据,分别对应TableName的UserId.UserName.UserPwd三个字段.如下图所示 在excel的D2的位置,也就是A.B.C列的后面一列,添加下面公 ...
- 生成Insert语句的存储过程
) drop procedure [dbo].[spGenInsertSQL] GO SET QUOTED_IDENTIFIER OFF GO SET ANSI_NULLS ON GO )) as b ...
- 使用java生成备份sqlserver数据表的insert语句
针对sqlserver数据表的备份工具很多,有时候条件限制需要我们自己生成insert语句,以便后期直接执行这些插入语句.下面提供了一个简单的思路,针对mysql或oracle有兴趣的以后可以试着修改 ...
- 使用excel中的数据快速生成sql语句
在小公司的话,总是会有要开发去导入历史数据(数据从旧系统迁移到新系统上)的时候.这个时候,现场实施或客户会给你一份EXCEL文档,里面包含了一些别的系统上的历史数据,然后就让你导入到现在的系统上面去. ...
- 批量生成sql语句,难得
在工作我们常常要批量生成sql文件,因为业务部门经常给我们的是excel文件,根据我的经验,推荐两种批量生成sql文件方式 1.excel批量生成sql ,sql语句如下 INSERT INTO Ta ...
随机推荐
- NuGet镜像上线试运行
为解决国内访问NuGet服务器速度不稳定的问题,我们用阿里云服务器搭建了一个NuGet镜像,目前已上线试运行. 使用NuGet镜像源的方法如下: 1)NuGet镜像源地址:https://nuget. ...
- “不给力啊,老湿!”:RSA加密与破解
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 加密和解密是自古就有技术了.经常看到侦探电影的桥段,勇敢又机智的主角,拿着一长串毫 ...
- 深入理解C#
简单认识.NET框架 (1)首先我们得知道 .NET框架具有两个主要组件:公共语言进行时CLR(Common Language Runtime)和框架类库FCL(Framework Class ...
- FragmentTabHost的基本用法
开通博客以来已经约莫1个月了.几次想提笔写写东西,但总是由于各种各样的原因并没有开始.现在,年假刚结束,项目也还没有开始,但最终促使我写这篇博客的是,看了一篇博友写的新年计划,说是要在新的一年中写50 ...
- C#中如何给Excel添加水印
我们知道Microsoft Excel并没有内置的功能直接给Excel表添加水印,但是其实我们可以用其他变通的方式来解决此问题,如通过添加页眉图片或艺术字的方法来模仿水印的外观.所以在这篇文章中,我将 ...
- 调用微信退款接口或发红包接口时出现System.Security.Cryptography.CryptographicException: 出现了内部错误 解决办法
我总结了一下出现证书无法加载的原因有以下三个 1.证书密码不正确,微信证书密码就是商户号 解决办法:请检查证书密码是不是和商户号一致 2.IIS设置错误,未加载用户配置文件 解决办法:找到网站使用的应 ...
- scanf类型不匹配造成死循环
int i = 0; while (flag) { printf("please input a number >>> "); scanf("% ...
- 装饰者模式 Decoration
1.什么是装饰者模式 动态给对象增加功能,从一个对象的外部来给对象添加功能,相当于改变了对象的外观,比用继承的方式更加的灵活.当使用装饰后,从外部系统的角度看,就不再是原来的那个对象了,而是使用一系列 ...
- 《如何使用Javascript判断浏览器终端设备》
WEB开发中如何通过Javascript来判断终端为PC.IOS(iphone).Android呢? 可以通过判断浏览器的userAgent,用正则来判断手机是否是ios和Android客户端. va ...
- Android之网络数据存储
一.网络保存数据介绍 可以使用网络来保存数据,在需要的时候从网络上获取数据,进而显示在App中. 用网络保存数据的方法有很多种,对于不同的网络数据采用不同的上传与获取方法. 本文利用LeanCloud ...