將表里的數(shù)據(jù)批量生成INSERT語句的存儲過程 增強(qiáng)版
有時(shí)候,我們需要將某個(gè)表里的數(shù)據(jù)全部或者根據(jù)查詢條件導(dǎo)出來,遷移到另一個(gè)相同結(jié)構(gòu)的庫中
目前SQL Server里面是沒有相關(guān)的工具根據(jù)查詢條件來生成INSERT語句的,只有借助第三方工具(third party tools)
這種腳本網(wǎng)上也有很多,但是網(wǎng)上的腳本還是欠缺一些規(guī)范和功能,例如:我只想導(dǎo)出特定查詢條件的數(shù)據(jù),網(wǎng)上的腳本都是導(dǎo)出全表數(shù)據(jù)
如果表很大,對性能會有很大影響
這里有一個(gè)存儲過程(適用于SQLServer2005 或以上版本)
-- Author: <樺仔> -- Blog: <http://www.cnblogs.com/lyhabc/> -- Create date: <//> -- Description: <根據(jù)查詢條件導(dǎo)出表數(shù)據(jù)的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=' ' --如果有多個(gè)schema,選擇其中一個(gè)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>) BEGIN --如果有多個(gè)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() FETCH NEXT FROM cursCol INTO @colName, @dataType PRINT @schemaName PRINT @colName IF @@fetch_status <> BEGIN PRINT 'Table ' + @tableName + ' not found, processing skipped.' CLOSE curscol DEALLOCATE curscol RETURN END WHILE @@FETCH_STATUS = 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)),''.'')+''''''),''+' 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()),'''')+'''''',''+' 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, , LEN(@string)) + ') VALUES(''+ ' + SUBSTRING(@stringData, , LEN(@stringData) - ) + '''+'')'' 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, , LEN(@string)) + ') VALUES(''+ ' + SUBSTRING(@stringData, , LEN(@stringData) - ) + '''+'')'' FROM ' + @schemaName+'.'+ @tableName END CLOSE cursCol DEALLOCATE cursCol SET @schemaNameCount=@schemaNameCount- IF(@schemaNameCount=) 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.
這里要聲明一下,如果你有多個(gè)schema,并且每個(gè)schema下面都有同一張表,那么腳本只會生成其中一個(gè)schema下面的表insert腳本
比如我現(xiàn)在有三個(gè)schema,下面都有customer這個(gè)表
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)
在執(zhí)行腳本的時(shí)候他只會生成dbo這個(gè)schema下面的表insert腳本
INSERT INTO [dbo].[customer]([city],[region]) VALUES('1','2')
這個(gè)腳本有一個(gè)缺陷
無論你的表的字段是什麼數(shù)據(jù)類型,導(dǎo)出來的時(shí)候只能是字符
表結(jié)構(gòu)
CREATE TABLE [dbo].[customer](city int,region int)
導(dǎo)出來的insert腳本
INSERT INTO [dbo].[customer]([city],[region]) VALUES('1','2')
我這里演示一下怎麼用
有兩種方式
1、導(dǎo)全表數(shù)據(jù)
InsertGenerator 'customer', null
或
InsertGenerator 'customer', ' '
2、根據(jù)查詢條件導(dǎo)數(shù)據(jù)
InsertGenerator 'customer', 'city=3'
或者
InsertGenerator 'customer', 'city=3 and region=8'
點(diǎn)擊一下,選擇全部
然后復(fù)制
新建一個(gè)查詢窗口,然后粘貼
其實(shí)SQLServer的技巧有很多
最后,大家可以看一下代碼,非常簡單,如果要支持SQLServer2000,只要改一下代碼就可以了
補(bǔ)充:創(chuàng)建一張測試表
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類型會有一些問題
生成的結(jié)果會自動幫你轉(zhuǎn)換
INSERT INTO [dbo].[testinsert]([id],[name],[cash],[dtime]) VALUES('1','nihao',convert(money,'8.80'),convert(datetime,'02 8 2015 5:17PM'))
--------------------------------------------------------------------------------
群里的人共享的另一個(gè)腳本
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
調(diào)用示例
--非dbo默認(rèn)架構(gòu)需注意 --支持?jǐn)?shù)據(jù)類型 :bigint,int, bit,char,datetime,date,time,decimal,money, nvarchar(50),tinyint, nvarchar(max),varchar(max),datetime2 --調(diào)用示例 如果top行或者where條件為空,只需要把參數(shù)填上null spGenInsertSQL 'customer' --表名 , 2 --top 行數(shù) , 'city=3 and didian=''大連'' ' --where 條件 --導(dǎo)出全表 where條件為空 spGenInsertSQL 'customer' --表名 , null --top 行數(shù) ,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')
以上所述是本文給大家分享的將表里的數(shù)據(jù)批量生成INSERT語句的存儲過程 增強(qiáng)版,希望大家喜歡。
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。