在 SQL Server 中生成 INSERT 语句
这是“在 SQL Server 中生成 INSERT 语句”的替代方案。
引言
Sumit Amir 提供的关于**在 SQL Server 中生成 INSERT 语句**的解决方案自发布以来一直非常有帮助。原始脚本非常适合将数据插入到空表中。当表已经包含数据时,它存在一个限制,即没有进行测试来确定记录是否已经存在。
使用代码
为本文更新了“InsertGenerator”的原始存储过程,以包含额外的参数,允许提供一个或两个键列。这些列用于构建一个测试,以检查每个 INSERT 语句的记录是否已经存在。
IF EXISTS (SELECT * FROM dbo.sysobjects
WHERE id = OBJECT_ID(N'[dbo].[InsertGenerator]') AND OBJECTPROPERTY(id,N'IsProcedure') = 1)
DROP PROCEDURE [dbo].[InsertGenerator]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
CREATE PROC [dbo].[InsertGenerator]
(
@tableName varchar(100),
@KeyColumn1 varchar(100)='',
@KeyColumn2 varchar(100)=''
)
AS
-- Generating INSERT statements in SQL Server
-- From CodeProject By Sumit Amar | 17 Jan 2005
-- Updated By Imtiaz Lorgat 19 May 2012
-- to validate if record exists - supports 2 field Unique index
--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
OPEN cursCol
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(1000) --data types returned for respective columns
DECLARE @FieldVal nvarchar(1000) -- save value for the current field
DECLARE @KeyVal nvarchar(1000) -- save value for the current field
DECLARE @KeyTest0 nvarchar(1000) -- used to test if key exists
DECLARE @KeyTest1 nvarchar(1000) -- used to test if key exists
DECLARE @KeyTest2 nvarchar(1000) -- used to test if key exists
SET @KeyTest0=''
IF @KeyColumn1<>''
SET @KeyTest0='IF not exists (Select * from '+@tableName
SET @KeyTest1=''
SET @KeyTest2=''
SET @string='INSERT '+@tableName+'('
SET @stringData=''
SET @FieldVal=''
SET @KeyVal=''
DECLARE @colName nvarchar(50)
FETCH NEXT FROM cursCol INTO @colName,@dataType
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 @FieldVal=''''+'''+isnull('''''+'''''+'+@colName+'+'''''+''''',''NULL'')+'',''+'
SET @KeyVal='''+isnull('''''+'''''+'+@colName+'+'''''+''''',''NULL'')+'',''+'
SET @stringData=@stringData+@FieldVal
END
ELSE
if @dataType in ('text','ntext','xml') --if the datatype is text or something else
BEGIN
SET @FieldVal='''''''''+isnull(cast('+@colName+' as varchar(max)),'''')+'''''',''+'
SET @stringData=@stringData+@FieldVal
END
ELSE
IF @dataType = 'money' --because money doesn't get converted from varchar implicitly
BEGIN
SET @FieldVal='''convert(money,''''''+isnull(cast('+@colName+' as varchar(200)),''0.0000'')+''''''),''+'
SET @stringData=@stringData+@FieldVal
END
ELSE
IF @dataType='datetime'
BEGIN
SET @FieldVal='''convert(datetime,'+'''+isnull('''''+'''''+convert(varchar(200),'+@colName+',121)+'''''+''''',''NULL'')+'',121),''+'
SET @stringData=@stringData+@FieldVal
END
ELSE
IF @dataType='image'
BEGIN
SET @FieldVal='''''''''+isnull(cast(convert(varbinary,'+@colName+') as varchar(6)),''0'')+'''''',''+'
SET @stringData=@stringData+@FieldVal
END
ELSE --presuming the data type is int,bit,numeric,decimal
BEGIN
SET @FieldVal=''''+'''+isnull('''''+'''''+convert(varchar(200),'+@colName+')+'''''+''''',''NULL'')+'',''+'
SET @KeyVal='''+isnull('''''+'''''+convert(varchar(200),'+@colName+')+'''''+''''',''NULL'')+'',''+'
SET @stringData=@stringData+@FieldVal
END
--Build key test
IF @KeyColumn1=@colName
begin
SET @KeyTest1 = ' WHERE [' + @KeyColumn1 + ']='
SET @KeyTest1 = @KeyTest1+@KeyVal+']'
end
IF @KeyColumn2=@colName
begin
SET @KeyTest2 = ' AND [' + @KeyColumn2 + ']='
SET @KeyTest2 = @KeyTest2+@KeyVal+']'
end
SET @string=@string+'['+@colName+'],'
FETCH NEXT FROM cursCol INTO @colName,@dataType
END
DECLARE @Query nvarchar(max)
-- Build the test string to check if record exists
if @KeyTest0<>''
begin
if @Keycolumn1<>''
SET @KeyTest0 = @KeyTest0 + substring(@KeyTest1,0,len(@KeyTest1)-4)
if @Keycolumn2<>''
begin
SET @KeyTest0 = @KeyTest0 + ''''
SET @KeyTest0 = @KeyTest0 + substring(@KeyTest2,0,len(@KeyTest2)-4)
end
SET @KeyTest0 = @KeyTest0 + ''')'
SET @query ='SELECT '''+substring(@KeyTest0,0,len(@KeyTest0)) + ') '
end
else
SET @query ='SELECT '''+substring(@KeyTest0,0,len(@KeyTest0))
SET @query = @query + substring(@string,0,len(@string)) + ') '
SET @query = @query + 'VALUES(''+ ' + substring(@stringData,0,len(@stringData)-2)+'''+'')'' FROM '+@tableName
exec sp_executesql @query
CLOSE cursCol
DEALLOCATE cursCol
GO
关注点
SQL 2008 R2 具有一个非常有用的向导,可以生成脚本,用于模式创建或数据插入。本次修订添加了检查记录是否存在的功能,从而允许合并数据。
历史
- Ver 0.1b 添加于 2003 年 12 月 5 日 - Sumit Amir
- Ver 0.1c 更新于 2012 年 5 月 19 日 - Imtiaz Lorgat