如何复制除标识列以外的每一列的行(SQL Server 2005)

时间:2011-08-04 23:36:23

标签: sql-server sql-server-2005 sql

我的代码:

SELECT * INTO #t FROM CTABLE WHERE CID = @cid   --get data, put into a temp table


ALTER TABLE #t
DROP COLUMN CID       -- remove primary key column CID


INSERT INTO CTABLE SELECT * FROM #t   -- insert record to table
DROP TABLE #t                                -- drop temp table

错误是:

Msg 8101,
An explicit value for the identity column in table 'CTABLE' can only 
be specified when a column list is used and IDENTITY_INSERT is ON.

我确实设置了

SET IDENTITY_INSERT CTABLE OFF
GO

7 个答案:

答案 0 :(得分:9)

DECLARE 
    @cid INT,
    @o   INT,
    @t   NVARCHAR(255),
    @c   NVARCHAR(MAX),
    @sql NVARCHAR(MAX);

SELECT
    @cid = 10,
    @t   = N'dbo.CTABLE',
    @o   = OBJECT_ID(@t);

SELECT @c = COALESCE(@c, '') + ',' + QUOTENAME(name)
    FROM sys.columns
    WHERE [object_id] = @o
    AND is_identity = 0;

SELECT @c = STUFF(@c, 1, 1, '');

SET @sql = 'SELECT ' + @c + ' INTO #t 
    FROM ' + @t + ' WHERE CID = ' + RTRIM(@cid) + ';

    INSERT ' + @t + '('+ @c + ') 
    SELECT ' + @c + ' FROM #t;' 

PRINT @sql;
-- exec sp_executeSQL @sql;

但是,构建以下SQL并完全避免使用#temp表似乎要容易得多:

SET @sql = 'INSERT ' + @t + '(' + @c + ') 
    SELECT ' + @c + ' FROM ' + @t + '
    WHERE CID = ' + RTRIM(@cid);

PRINT @sql;
-- exec sp_executeSQL @sql;

答案 1 :(得分:4)

试试这个:

SELECT * INTO #t FROM CTABLE WHERE CID = @cid
ALTER TABLE #t
DROP COLUMN CID

INSERT CTABLE --Notice that INTO is removed here.
SELECT top(1) * FROM #t
DROP TABLE #t

测试脚本(在SQL 2005中测试):

CREATE TABLE #TestIDNT
(
    ID INT IDENTITY(1,1) PRIMARY KEY,
    TITLE   VARCHAR(20)
)

INSERT #TestIDNT
SELECT 'Cybenate'

答案 2 :(得分:1)

尝试指定列:

INSERT INTO CTABLE 
(col2, col3, col4)
SELECT col2, col3, col4
FROM #t

似乎可能认为您正在尝试插入PK字段,因为您没有明确定义要插入的列。如果Identity插件已关闭且您指定了非pk列,那么您不应该收到该错误。

答案 3 :(得分:1)

这是一个动态构建列列表的示例 - 不包括主键列 - 并执行INSERT

declare @tablename nvarchar(100), @column nvarchar(100), @cid int, @sql nvarchar(max)
set @tablename = N'ctable'
set @cid = 1
set @sql = N''

declare example cursor for

select column_name
  from information_schema.columns
 where table_name = @tablename 
   and column_name not in (
        select column_name
          from information_schema.key_column_usage
         where constraint_name in (select constraint_name from information_schema.table_constraints)
           and table_name = @tablename
)

open example
fetch next from example into @column
while @@fetch_status = 0
begin
    set @sql = @sql + N'[' + @column + N'],'
    fetch next from example into @column
end
set @sql = substring(@sql, 1, len(@sql)-1)
close example
deallocate example
set @sql = N'insert into ' + @tablename + '(' + @sql + N') select top(1) ' + @sql + ' from #t'
--select @sql
exec sp_executesql @sql

答案 4 :(得分:0)

尝试使用EXEC调用INSERT语句:

SELECT * INTO #t FROM CTABLE WHERE CID = @cid

ALTER TABLE #t
DROP COLUMN CID

EXEC('INSERT INTO CTABLE SELECT top(1) * FROM #t')
DROP TABLE #t

答案 5 :(得分:0)

你不能这样做:

INSERT INTO CTABLE SELECT top(1) * FROM #t 

因为列列表不一样。您已从#t中删除了PK列,因此#t中的列少于CTABLE中的列。这相当于以下内容:

INSERT INTO CTABLE(pk, col1, col2, col3, ...) 
select top(1) col1, col2, col3, ...
from #t

由于显而易见的原因,这不起作用。同样,如果您没有插入所有列,则无法指定*通配符来执行插入操作。在不包含PK的情况下执行插入的唯一方法是指定每列。您可以通过动态sql生成列列表,但是您必须以这种或那种方式指定它们。

答案 6 :(得分:0)

如果使用SQL Server Management Studio和您的问题,除了标识列之外,您有太多字段无法输入它们,请右键单击该表并单击“脚本表为”/“选择到”/“新建查询窗口”。

这将提供您可以复制的字段列表。粘贴到您自己的查询中,然后只删除标识列。