复制整行(不知道字段名称)

时间:2012-06-24 20:44:52

标签: sql-server-2008 tsql identity

使用SQL Server 2008,我想复制表格的一行,而不知道字段名称。我的关键问题是:随着时间的推移,随着时间的推移,我希望这个复制脚本继续发挥作用,而我不必写出30多个不断变化的字段,呃。

当然,问题还在于 IDENTITY字段无法复制

我的代码下面的代码,但我想知道是否有一个比我抛出的文本字符串SQL语句更合适的方法?

所以提前谢谢你。这是我的(是,工作)代码 - 我欢迎有关改进它的建议。 托德

alter procedure spEventCopy
   @EventID int
as
begin

   -- VARS...
   declare @SQL varchar(8000)

   -- LIST ALL FIELDS (*EXCLUDE* IDENTITY FIELDS).
   -- USE [BRACKETS] FOR ANY SILLY FIELD-NAMES WITH SPACES, OR RESERVED WORDS...
   select @SQL = coalesce(@SQL + ', ', '') + '[' + column_name + ']'
   from INFORMATION_SCHEMA.COLUMNS
   where TABLE_NAME = 'EventsTable'
     and COLUMNPROPERTY(OBJECT_ID('EventsTable'), COLUMN_NAME, 'IsIdentity') = 0

   -- FINISH SQL COPY STATEMENT...
   set @SQL = 'insert into EventsTable '
            + ' select ' + @SQL
            + ' from EventsTable '
            + ' where EventID = ' + ltrim(str(@EventID))

   -- COPY ROW...
   exec(@SQL)

   -- REMEMBER NEW ID...
   set @EventID = @@IDENTITY

   -- (do other stuff here)

   -- DONE...
   -- JUST FOR KICKS, RETURN THE SQL STATEMENT SO I CAN REVIEW IT IF I WISH...
   select EventID = @EventID, SQL = @SQL

end

2 个答案:

答案 0 :(得分:4)

不,没有任何神奇的方式可以说“选择除<foo>之外的所有列” - 您正在这样做的方式就是如何做到这一点(另外一个答案中的黑客除外) )。

以下是我将如何更改您的代码,这些更改(有些是超链接,因此您可以阅读我对原因的看法):

ALTER PROCEDURE dbo.spEventCopy
   @EventID INT
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @sql NVARCHAR(MAX) = N'';

    SELECT @sql += ',' + QUOTENAME(name)
      FROM sys.columns
      WHERE [object_id] = OBJECT_ID('dbo.EventsTable')
      AND is_identity = 0;

    SET @sql = STUFF(@sql, 1, 1, '');

    SET @sql = N'INSERT dbo.EventsTable(' + @sql + ')
      SELECT ' + @sql + ' FROM dbo.EventsTable
      WHERE EventID = ' + CONVERT(VARCHAR(12), @EventID) + ';';

    EXEC sp_executesql @sql;

    SELECT @EventID = SCOPE_IDENTITY();

    -- do stuff with the new row here

    SELECT EventID = @EventID, SQL = @SQL;
END

答案 1 :(得分:2)

如果您知道调用了您的标识列(并且它不会更改列),您可以这样做:

SELECT * INTO #dummy FROM EventsTable where EventID = @EventID;

ALTER TABLE #dummy
DROP COLUMN MyIdentityColumn

INSERT EventsTable SELECT * FROM #dummy
DROP TABLE #dummy

由于一个表只能包含一个标识列,因此在查询中指定不应该限制太多。

正如Aaron Bertrand指出的那样,这种方法存在风险。请阅读以下评论中的讨论。