Как скопировать строку с каждым столбцом, кроме столбца идентификаторов (SQL Server 2005) - PullRequest
8 голосов
/ 05 августа 2011

Мой код:

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 ]

9 голосов
/ 05 августа 2011
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;
4 голосов
/ 05 августа 2011

Попробуйте это:

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'
1 голос
/ 05 августа 2011

Вот пример для динамического построения списка столбцов - исключая столбцы первичного ключа - и выполнения 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
1 голос
/ 05 августа 2011

Попробуйте указать столбцы:

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

Похоже, вы думаете, что вы пытаетесь вставить в поле PK, поскольку вы не определяете явно столбцы для вставки. Если вставка Identity отключена и вы указываете столбцы, отличные от pk, вы не должны получать эту ошибку.

0 голосов
/ 29 сентября 2013

Если вы используете SQL Server Management Studio и ваши проблемы, у вас слишком много полей, чтобы их можно было набрать, кроме столбца идентификаторов, затем щелкните правой кнопкой мыши таблицу и выберите «Сценарий таблицы как» / «Выбрать в» / «Окно нового запроса» ».

Это предоставит список полей, которые вы можете скопировать и вставить в свой запрос, а затем просто удалить столбец идентификаторов.

0 голосов
/ 05 августа 2011

Вы не можете сделать это:

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

Поскольку списки столбцов не совпадают.Вы удалили столбец PK из #t, поэтому у вас в столбце #t на 1 меньше, чем в CTABLE.Это эквивалентно следующему:

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

Это не будет работать по понятным причинам.Точно так же вы не сможете указать подстановочный знак * для выполнения вставки, если вы не вставляете все столбцы.Единственный способ выполнить вставку без включения PK - указать каждый столбец.Вы можете создать список столбцов с помощью динамического sql, но вам придется указать их так или иначе.

0 голосов
/ 05 августа 2011

Попробуйте вызвать оператор INSERT с помощью EXEC:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...