將表里的數(shù)據(jù)批量生成INSERT語(yǔ)句的存儲(chǔ)過(guò)程 增強(qiáng)版
有時(shí)候,我們需要將某個(gè)表里的數(shù)據(jù)全部或者根據(jù)查詢(xún)條件導(dǎo)出來(lái),遷移到另一個(gè)相同結(jié)構(gòu)的庫(kù)中
目前SQL Server里面是沒(méi)有相關(guān)的工具根據(jù)查詢(xún)條件來(lái)生成INSERT語(yǔ)句的,只有借助第三方工具(third party tools)
這種腳本網(wǎng)上也有很多,但是網(wǎng)上的腳本還是欠缺一些規(guī)范和功能,例如:我只想導(dǎo)出特定查詢(xún)條件的數(shù)據(jù),網(wǎng)上的腳本都是導(dǎo)出全表數(shù)據(jù)
如果表很大,對(duì)性能會(huì)有很大影響
這里有一個(gè)存儲(chǔ)過(guò)程(適用于SQLServer2005 或以上版本)
-- Author: <樺仔>
-- Blog: <http://www.cnblogs.com/lyhabc/>
-- Create date: <//>
-- Description: <根據(jù)查詢(xún)條件導(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下面都有同一張表,那么腳本只會(huì)生成其中一個(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í)候他只會(huì)生成dbo這個(gè)schema下面的表insert腳本
INSERT INTO [dbo].[customer]([city],[region]) VALUES('1','2')
這個(gè)腳本有一個(gè)缺陷
無(wú)論你的表的字段是什麼數(shù)據(jù)類(lèi)型,導(dǎo)出來(lái)的時(shí)候只能是字符
表結(jié)構(gòu)
CREATE TABLE [dbo].[customer](city int,region int)
導(dǎo)出來(lái)的insert腳本
INSERT INTO [dbo].[customer]([city],[region]) VALUES('1','2')
我這里演示一下怎麼用
有兩種方式
1、導(dǎo)全表數(shù)據(jù)
InsertGenerator 'customer', null
或
InsertGenerator 'customer', ' '

2、根據(jù)查詢(xún)條件導(dǎo)數(shù)據(jù)
InsertGenerator 'customer', 'city=3'
或者
InsertGenerator 'customer', 'city=3 and region=8'

點(diǎn)擊一下,選擇全部

然后復(fù)制

新建一個(gè)查詢(xún)窗口,然后粘貼

其實(shí)SQLServer的技巧有很多
最后,大家可以看一下代碼,非常簡(jiǎn)單,如果要支持SQLServer2000,只要改一下代碼就可以了
補(bǔ)充:創(chuàng)建一張測(cè)試表
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]
測(cè)試
InsertGenerator 'testinsert' ,'' InsertGenerator 'testinsert' ,'name=''nihao''' InsertGenerator 'testinsert' ,'name=''nihao'' and cash=8.8'
datetime類(lèi)型會(huì)有一些問(wèn)題
生成的結(jié)果會(huì)自動(dòng)幫你轉(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ù)類(lèi)型 :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'銷(xiāo)售組',N'中國(guó)你好有限公司XX分公司','05 5 2015 5:58PM') INSERT INTO [Department] ([DepartmentID],[Name],[GroupName],[Company],[ModifiedDate]) values (2,N'售后部',N'銷(xiāo)售組',N'中國(guó)你好有限公司XX分公司','05 5 2015 5:58PM')
以上所述是本文給大家分享的將表里的數(shù)據(jù)批量生成INSERT語(yǔ)句的存儲(chǔ)過(guò)程 增強(qiáng)版,希望大家喜歡。
- PHP用mysql_insert_id()函數(shù)獲得剛插入數(shù)據(jù)或當(dāng)前發(fā)布文章的ID
- MyBatis中insert操作返回主鍵的實(shí)現(xiàn)方法
- jQuery中的insertBefore(),insertAfter(),after(),before()區(qū)別介紹
- Oracle+Mybatis的foreach insert批量插入報(bào)錯(cuò)的快速解決辦法
- MySQL觸發(fā)器 Update觸發(fā)Insert失敗
- MyBatis批量插入(insert)數(shù)據(jù)操作
- 詳解MySQL數(shù)據(jù)庫(kù)insert和update語(yǔ)句
- MySQL中insert語(yǔ)句的使用與優(yōu)化教程
- C++ primer基礎(chǔ)之容器insert
相關(guān)文章
sqlserver 2000中每個(gè)服務(wù)器角色的解釋
sqlserver 2000中每個(gè)服務(wù)器角色的解釋,方便大家以后對(duì)于數(shù)據(jù)庫(kù)權(quán)限有所了解。2011-03-03
SQL?Server?Agent?服務(wù)啟動(dòng)后又停止問(wèn)題
這篇文章主要介紹了SQL?Server?Agent?服務(wù)啟動(dòng)后又停止問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
人工智能自動(dòng)sql優(yōu)化工具--SQLTuning for SQL Server
SQL語(yǔ)句是對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作的惟一途徑,對(duì)數(shù)據(jù)庫(kù)系統(tǒng)的性能起著決定性的作用。對(duì)于同一條件下的SQL語(yǔ)句寫(xiě)法有很多,其中一些寫(xiě)法往往對(duì)性能又有很大影響。但是每個(gè)人掌握SQL語(yǔ)言的水平不同,如何才能保證寫(xiě)出高性能的SQL呢?2014-08-08
數(shù)據(jù)庫(kù)性能優(yōu)化三:程序操作優(yōu)化提升性能
程序訪問(wèn)優(yōu)化也可以認(rèn)為是訪問(wèn)SQL語(yǔ)句的優(yōu)化,一個(gè)好的SQL語(yǔ)句是可以減少非常多的程序性能的,下面列出常用錯(cuò)誤習(xí)慣,并且提出相應(yīng)的解決方案2013-01-01
sqlserver中將varchar類(lèi)型轉(zhuǎn)換為int型再進(jìn)行排序的方法
sql中把varchar類(lèi)型轉(zhuǎn)換為int型然后進(jìn)行排序,如果我們數(shù)據(jù)庫(kù)的ID設(shè)置為varchar型的 在查詢(xún)的時(shí)候order by id的話(huà)2012-06-06
Spark臨時(shí)表tempView的注冊(cè)/使用/注銷(xiāo)/注意事項(xiàng)(推薦)
transformation是根據(jù)原有RDD創(chuàng)建一個(gè)新的RDD,而action則把RDD操作后的結(jié)果返回給driver,這篇文章主要介紹了Spark臨時(shí)表tempView的注冊(cè)/使用/注銷(xiāo)/注意事項(xiàng)的相關(guān)資料,需要的朋友可以參考下2022-10-10
Linux安裝ODBC連接SQLServer數(shù)據(jù)庫(kù)的步驟
這篇文章主要介紹了Linux安裝ODBC連接SQLServer數(shù)據(jù)庫(kù)?,本文分步驟給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04

