1

SQL Server 2008 を使用して、フィールド名を知らずにテーブルの 1 行を複製したいと考えています。私の重要な問題: テーブルが成長し、時間の経過とともに変化するにつれて、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
4

2 に答える 2

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
于 2012-06-24T21:00:40.930 に答える
2

ID 列の名前がわかっている場合 (列が変更されない場合)、次のようにすることができます。

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

ALTER TABLE #dummy
DROP COLUMN MyIdentityColumn

INSERT EventsTable SELECT * FROM #dummy
DROP TABLE #dummy

テーブルはそれぞれ 1 つの ID 列しか持てないため、クエリでそれを指定してもあまり制限されるべきではありません。

Aaron Bertrand が指摘するように、このアプローチにはリスクが伴います。以下のコメントの議論を読んでください。

于 2012-06-24T21:00:14.003 に答える