SQL 服务器:table 中的重复行,同时使用 select 更改某些值*
SQL Server : Duplicate row in table while changing some values with select *
我需要在 table 中插入一个几乎重复的行,同时更改一些值。
例如,插入具有新 ID(我不想要自动 ID)和不同名称但所有其他值相同的重复行。
问题是我需要做一个 select *
我知道有一种方法可以从 select 插入并以这种方式更改值:
insert into Table1(id,name,surname) select newid(),'David',surname from Table1 where id=1
但我不想征集所有字段,而是想使用 select *,所以如果添加了字段,我就不必更改我的存储过程。
我想要这样的东西:
insert into Table1 (
update (SELECT *
FROM Table1
WHERE id= 1 ) t
set t.id= newid(),name='David')
有办法吗?
不,因为 SELECT *
将始终包含 id
列。
一般来说,你应该避免在任何地方使用 SELECT *,除非是交互式查询。编译存储过程时,查询文本将被解析并替换为正确的列,从而使您的存储过程在每次结构更改时都无效。
您可以使用临时哈希 table 来完成此操作。
SELECT *
INTO #temp
FROM Table1
WHERE id= 1;
UPDATE #temp
SET ID = newid(),
Name='David'
INSERT INTO Table1 SELECT * FROM #temp;
请注意,当客户端与数据库服务器断开连接时,#temp table 会自动删除。
此外,如前所述,我更喜欢单独使用列名而不是 *。
示例:SQL Fiddle
我使用的代码:
declare @table sysname
declare @excludecols nvarchar(max)
declare @uniqueWhereToCopy nvarchar(max)
declare @valuesToChange nvarchar(max)
--copy settings
set @table = 'orsrg' --the tablename
set @excludecols='' --columnnames to exclude from the copy, seperated by commas
set @uniqueWhereToCopy = 'ID=1188'
set @valuesToChange = 'regel='' 4''' --columnName=<value>,columnName2=<value2>, .... (needed for unique indexes)
set @excludecols=@excludecols + ','
set @valuesToChange=@valuesToChange + ','
--get the columnnames to copy
declare @sqlcolumns nvarchar(max)
set @sqlcolumns = ''
SELECT @sqlcolumns = @sqlcolumns + name from
(select '[' + c.name + '], ' as name FROM sys.COLUMNS c inner join sys.objects o
on c.object_id = o.object_id
WHERE o.name = @table
and is_identity = 0 /*exclude identity*/
and is_rowguidcol = 0 /*exclude rowguids*/
and is_computed = 0 /*exclude computed columns*/
and system_type_id <> 189 /*exclude timestamp*/
and charindex(c.name, @excludecols,1) = 0 /*exclude user specified columns*/)q
--get the select columns and values
declare @sqlselectvalues nvarchar(max)
set @sqlselectvalues = @sqlcolumns
while len(@valuesToChange)>1
begin
declare @colValueSet nvarchar(max)
declare @colname sysname
declare @value nvarchar(max)
set @colValueSet = left(@valuesToChange,charindex(',',@valuesToChange,1)-1)
set @valuesToChange = substring(@valuesToChange,charindex(',',@valuesToChange,1)+1,len(@valuesToChange))
set @colname = '[' + left(@colValueSet,charindex('=',@colValueSet,1)-1) +']'
set @value = substring(@colValueSet,charindex('=',@colValueSet,1)+1,len(@colValueSet))
set @sqlselectvalues = REPLACE(@sqlselectvalues,@colname,@value)
end
--remove the last comma
set @sqlcolumns = left(@sqlcolumns, len(@sqlcolumns)-1)
set @sqlselectvalues = left(@sqlselectvalues, len(@sqlselectvalues)-1)
--create the statement
declare @stmt nvarchar(max)
set @stmt = 'Insert into ' + @table + '(' + @sqlcolumns + ') select ' + @sqlselectvalues + ' from ' + @table + ' with (nolock) where ' + @uniqueWhereToCopy
--copy the row
exec sp_executesql @stmt
我需要在 table 中插入一个几乎重复的行,同时更改一些值。
例如,插入具有新 ID(我不想要自动 ID)和不同名称但所有其他值相同的重复行。 问题是我需要做一个 select *
我知道有一种方法可以从 select 插入并以这种方式更改值:
insert into Table1(id,name,surname) select newid(),'David',surname from Table1 where id=1
但我不想征集所有字段,而是想使用 select *,所以如果添加了字段,我就不必更改我的存储过程。
我想要这样的东西:
insert into Table1 (
update (SELECT *
FROM Table1
WHERE id= 1 ) t
set t.id= newid(),name='David')
有办法吗?
不,因为 SELECT *
将始终包含 id
列。
一般来说,你应该避免在任何地方使用 SELECT *,除非是交互式查询。编译存储过程时,查询文本将被解析并替换为正确的列,从而使您的存储过程在每次结构更改时都无效。
您可以使用临时哈希 table 来完成此操作。
SELECT *
INTO #temp
FROM Table1
WHERE id= 1;
UPDATE #temp
SET ID = newid(),
Name='David'
INSERT INTO Table1 SELECT * FROM #temp;
请注意,当客户端与数据库服务器断开连接时,#temp table 会自动删除。
此外,如前所述,我更喜欢单独使用列名而不是 *。
示例:SQL Fiddle
我使用的代码:
declare @table sysname
declare @excludecols nvarchar(max)
declare @uniqueWhereToCopy nvarchar(max)
declare @valuesToChange nvarchar(max)
--copy settings
set @table = 'orsrg' --the tablename
set @excludecols='' --columnnames to exclude from the copy, seperated by commas
set @uniqueWhereToCopy = 'ID=1188'
set @valuesToChange = 'regel='' 4''' --columnName=<value>,columnName2=<value2>, .... (needed for unique indexes)
set @excludecols=@excludecols + ','
set @valuesToChange=@valuesToChange + ','
--get the columnnames to copy
declare @sqlcolumns nvarchar(max)
set @sqlcolumns = ''
SELECT @sqlcolumns = @sqlcolumns + name from
(select '[' + c.name + '], ' as name FROM sys.COLUMNS c inner join sys.objects o
on c.object_id = o.object_id
WHERE o.name = @table
and is_identity = 0 /*exclude identity*/
and is_rowguidcol = 0 /*exclude rowguids*/
and is_computed = 0 /*exclude computed columns*/
and system_type_id <> 189 /*exclude timestamp*/
and charindex(c.name, @excludecols,1) = 0 /*exclude user specified columns*/)q
--get the select columns and values
declare @sqlselectvalues nvarchar(max)
set @sqlselectvalues = @sqlcolumns
while len(@valuesToChange)>1
begin
declare @colValueSet nvarchar(max)
declare @colname sysname
declare @value nvarchar(max)
set @colValueSet = left(@valuesToChange,charindex(',',@valuesToChange,1)-1)
set @valuesToChange = substring(@valuesToChange,charindex(',',@valuesToChange,1)+1,len(@valuesToChange))
set @colname = '[' + left(@colValueSet,charindex('=',@colValueSet,1)-1) +']'
set @value = substring(@colValueSet,charindex('=',@colValueSet,1)+1,len(@colValueSet))
set @sqlselectvalues = REPLACE(@sqlselectvalues,@colname,@value)
end
--remove the last comma
set @sqlcolumns = left(@sqlcolumns, len(@sqlcolumns)-1)
set @sqlselectvalues = left(@sqlselectvalues, len(@sqlselectvalues)-1)
--create the statement
declare @stmt nvarchar(max)
set @stmt = 'Insert into ' + @table + '(' + @sqlcolumns + ') select ' + @sqlselectvalues + ' from ' + @table + ' with (nolock) where ' + @uniqueWhereToCopy
--copy the row
exec sp_executesql @stmt