ranio Ответов: 2

Как избежать проблемы не удается вставить явное значение в столбец временной метки при попытке вставить данные ?


Как избежать проблемы невозможно вставить явное значение в столбец временной метки. Используйте вставку со списком столбцов, чтобы исключить столбец timestamp, или вставьте значение по умолчанию в столбец timestamp при попытке вставить данные в таблицу?

На самом деле я вставляю данные в таблицы с помощью identity insert в БД, полученную из таблиц аналогичного типа в другой БД. Я получаю проблему для таблиц, имеющих столбец с меткой времени типа данных.
Ошибка выглядит следующим образом:
Cannot insert an explicit value into a timestamp column. Use INSERT with a column list to exclude the timestamp column, or insert a DEFAULT into the timestamp column.
Insertion to all other tables are fine.I am using generic script for the same as below  .

<pre lang="SQL">The script is as below:

&lt;pre lang=&quot;sql&quot;&gt;
/* One Time Script for Inserting into Existing Archival DB fetching already existing data from Temporary Archival DB*/

BEGIN

DECLARE @Query NVARCHAR(MAX)

--Pass/Set Archival DB(Existing Archival DB)
DECLARE @ArchivalDB NVARCHAR(MAX)
SET @ArchivalDB=&#39;FTS_DIB_ARCH3&#39;

--Pass/Set Temp Archival DB(Temp Archival DB where existing data is stored temporarily)
DECLARE @TempArchivalDB NVARCHAR(MAX)
SET @TempArchivalDB=&#39;FTS_DIB_ARCH2&#39;

--Pass/Set Schema Name
DECLARE @TABLE_SCHEMA NVARCHAR(MAX)
SET @TABLE_SCHEMA= &#39;dbo&#39;

DECLARE @TableName NVARCHAR(MAX)


BEGIN TRY                
              

--Created a  Cursor named IDENTITYINSERTOFF to fetch all Identity Insert Tables IN Archival DB 
--and Pass the Table one by one to Parameter @TableName 

DECLARE IDENTITYINSERTOFF CURSOR FOR 
select TABLE_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_SCHEMA =&#39;DBO&#39;
and COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, &#39;IsIdentity&#39;) = 1
ORDER BY ORDINAL_POSITION

OPEN IDENTITYINSERTOFF 
Fetch next from IDENTITYINSERTOFF into 
@TableName 

--Ended 

WHILE @@FETCH_STATUS = 0  
BEGIN
       
        --PRINT @ArchivalDB
       
        --Insert into Existing Archive DB with Schema Name passed above
        
        SET @Query = N&#39;INSERT INTO &#39; + @ArchivalDB+&#39;.&#39;+ @TABLE_SCHEMA+&#39;.&#39;+ @TableName + &#39;(&#39;;

        --Pass  Columns for each Identity Insert Tables
        SELECT @Query= @Query + QUOTENAME(COLUMN_NAME) + N&#39; ,&#39;
        FROM  INFORMATION_SCHEMA.COLUMNS 
        WHERE TABLE_NAME = @TableName
        ORDER BY ORDINAL_POSITION;;
         --Ended
        --Trim the Comma at the end of Insert Query
        SET @Query= LEFT(@Query, NULLIF(LEN(@Query)-1,-1))
         -- Close the Brace of the Dynamic Create Table Syntax
        SET @Query = @Query + N&#39;)&#39;;  
        
        --Select from Temp Archive DB (Tables with Identity Insert Off) with data&#39;
        SELECT @Query = @Query + N&#39;SELECT &#39;;
        --Pass  Columns for each Identity Insert Tables
        SELECT @Query= @Query + QUOTENAME(COLUMN_NAME) + N&#39; ,&#39;
        FROM  INFORMATION_SCHEMA.COLUMNS 
        WHERE TABLE_NAME = @TableName
        ORDER BY ORDINAL_POSITION;;
         --Ended
        --Trim the Comma at the end of Select from Query 
        SET @Query= LEFT(@Query, NULLIF(LEN(@Query)-1,-1))
        --Select from  Temp Archive DB with Schema Name passed above (where existing data is stored temporarily)
        SET @Query= + @Query + N&#39; FROM &#39; + @TempArchivalDB+&#39;.&#39;+ @TABLE_SCHEMA+&#39;.&#39;+ @TableName ;
       
        --PRINT &#39;K&#39;
        --To Print the Insert into Select From Query
         PRINT @Query

       -- Execute the Insert into Select From Query(Saving data to Existing Archival DB from Termp Archival Tables)
        EXECUTE sp_executesql @Query
        --Ended
       --Fetch the next value from the Cursor titled IDENTITYINSERTOFF
        Fetch next from IDENTITYINSERTOFF into 
        @TableName
        --Ended 
END


--Ended
--Close and Deallocate Cursor named IDENTITYINSERTOFF
CLOSE IDENTITYINSERTOFF  
DEALLOCATE IDENTITYINSERTOFF 
--Ended



END TRY 
           
BEGIN CATCH  
DECLARE @errMsg AS VARCHAR(MAX)       
SET @errMsg = ERROR_MESSAGE() 
--PRINT @errMsg
--Close and Deallocate Cursor named IDENTITYINSERTOFF
CLOSE IDENTITYINSERTOFF  
DEALLOCATE IDENTITYINSERTOFF
 --Ended 
  --RollBack the Transaction if there is any Issue 
  --ROLLBACK TRAN
  --Ended
              
END CATCH  

END
&lt;/pre&gt;</pre>


Что я уже пробовал:

Сценарий выглядит следующим образом:

/* One Time Script for Inserting into Existing Archival DB fetching already existing data from Temporary Archival DB*/

BEGIN

DECLARE @Query NVARCHAR(MAX)

--Pass/Set Archival DB(Existing Archival DB)
DECLARE @ArchivalDB NVARCHAR(MAX)
SET @ArchivalDB='FTS_DIB_ARCH3'

--Pass/Set Temp Archival DB(Temp Archival DB where existing data is stored temporarily)
DECLARE @TempArchivalDB NVARCHAR(MAX)
SET @TempArchivalDB='FTS_DIB_ARCH2'

--Pass/Set Schema Name
DECLARE @TABLE_SCHEMA NVARCHAR(MAX)
SET @TABLE_SCHEMA= 'dbo'

DECLARE @TableName NVARCHAR(MAX)


BEGIN TRY                
              

--Created a  Cursor named IDENTITYINSERTOFF to fetch all Identity Insert Tables IN Archival DB 
--and Pass the Table one by one to Parameter @TableName 

DECLARE IDENTITYINSERTOFF CURSOR FOR 
select TABLE_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_SCHEMA ='DBO'
and COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
ORDER BY ORDINAL_POSITION

OPEN IDENTITYINSERTOFF 
Fetch next from IDENTITYINSERTOFF into 
@TableName 

--Ended 

WHILE @@FETCH_STATUS = 0  
BEGIN
       
        --PRINT @ArchivalDB
       
        --Insert into Existing Archive DB with Schema Name passed above
        
        SET @Query = N'INSERT INTO ' + @ArchivalDB+'.'+ @TABLE_SCHEMA+'.'+ @TableName + '(';

        --Pass  Columns for each Identity Insert Tables
        SELECT @Query= @Query + QUOTENAME(COLUMN_NAME) + N' ,'
        FROM  INFORMATION_SCHEMA.COLUMNS 
        WHERE TABLE_NAME = @TableName
        ORDER BY ORDINAL_POSITION;;
         --Ended
        --Trim the Comma at the end of Insert Query
        SET @Query= LEFT(@Query, NULLIF(LEN(@Query)-1,-1))
         -- Close the Brace of the Dynamic Create Table Syntax
        SET @Query = @Query + N')';  
        
        --Select from Temp Archive DB (Tables with Identity Insert Off) with data'
        SELECT @Query = @Query + N'SELECT ';
        --Pass  Columns for each Identity Insert Tables
        SELECT @Query= @Query + QUOTENAME(COLUMN_NAME) + N' ,'
        FROM  INFORMATION_SCHEMA.COLUMNS 
        WHERE TABLE_NAME = @TableName
        ORDER BY ORDINAL_POSITION;;
         --Ended
        --Trim the Comma at the end of Select from Query 
        SET @Query= LEFT(@Query, NULLIF(LEN(@Query)-1,-1))
        --Select from  Temp Archive DB with Schema Name passed above (where existing data is stored temporarily)
        SET @Query= + @Query + N' FROM ' + @TempArchivalDB+'.'+ @TABLE_SCHEMA+'.'+ @TableName ;
       
        --PRINT 'K'
        --To Print the Insert into Select From Query
         PRINT @Query

       -- Execute the Insert into Select From Query(Saving data to Existing Archival DB from Termp Archival Tables)
        EXECUTE sp_executesql @Query
        --Ended
       --Fetch the next value from the Cursor titled IDENTITYINSERTOFF
        Fetch next from IDENTITYINSERTOFF into 
        @TableName
        --Ended 
END


--Ended
--Close and Deallocate Cursor named IDENTITYINSERTOFF
CLOSE IDENTITYINSERTOFF  
DEALLOCATE IDENTITYINSERTOFF 
--Ended



END TRY 
           
BEGIN CATCH  
DECLARE @errMsg AS VARCHAR(MAX)       
SET @errMsg = ERROR_MESSAGE() 
--PRINT @errMsg
--Close and Deallocate Cursor named IDENTITYINSERTOFF
CLOSE IDENTITYINSERTOFF  
DEALLOCATE IDENTITYINSERTOFF
 --Ended 
  --RollBack the Transaction if there is any Issue 
  --ROLLBACK TRAN
  --Ended
              
END CATCH  

END

Richard Deeming

Мы должны угадать, какую "проблему" вы получаете?

Нажмите кнопку "улучшить вопрос" и добавьте правильное описание проблемы. Включите полную информацию о любых сообщениях об ошибках.

phil.o

Поле метки времени автоматически заполняется значением метки времени при создании записи.
Таким образом, столбцы меток времени не должны назначаться во время команд вставки или обновления.
Вы должны фильтровать их так, чтобы они не обрабатывались.

2 Ответов

Рейтинг:
1

CHill60

Если вам важно сохранить исходную метку времени, измените типы столбцов меток времени в вашей архивной базе данных на varbinary(8) и вы должны быть в состоянии скопировать данные прямо через него.

Если вы не возражаете против использования новой временной метки, то при вставке строк в целевую таблицу используйте слово DEFAULT.

Тривиальный пример для демонстрации

create table tt
(
	ts timestamp,
	i int,
	v varchar
)

Я могу вставлять такие значения, как это
INSERT INTO tt VALUES(DEFAULT, 1, '1')
INSERT INTO tt VALUES(DEFAULT, 2, '2')
или вот так
INSERT INTO tt (i,v) VALUES( 3, '3')
INSERT INTO tt (i,v) VALUES( 4, '4')

Если я создам архивную таблицу для этой таблицы, используя varbinary(8) для эквивалента столбца timestamp
create table tt_archive
(
	ts varbinary(8),
	i int,
	v varchar
)
Я могу скопировать данные на него, используя это
insert into tt_archive select * from tt

Обратите внимание, что вы не сможете использовать функцию метки времени в таблице архивирования


Рейтинг:
1

kiran vemasani

To illustrate, here’s a table that contains a timestamp column:

CREATE TABLE Team (
    TeamID     INT NOT NULL PRIMARY KEY IDENTITY(1, 1),
    TeamName   VARCHAR(50),
    TIMESTAMP )


Inserting a new row in this table and specifying a value to the timestamp column will generate this error:

INSERT INTO Team ( TeamName,Timestamp )
VALUES ( 'Miami Marlins', @@DBTS )

Error Message:

Msg 273, Level 16, State 1, Line 1
Cannot insert an explicit value into a timestamp column.  Use INSERT with a column
list to exclude the timestamp column, or insert a DEFAULT into the timestamp column.

SOLUTION:

There are 2 ways of working around this issue, as the error message suggests. 

First method:

The first method is not to include the timestamp column in the list of columns specified in the INSERT statement:

INSERT INTO Team ( TeamName )
VALUES ( 'New York Yankees' )

Second Method:

The second method is to specify DEFAULT as the value in the timestamp column, as can be seen in the following statement:

INSERT INTO Team ( TeamName, Timestamp )
VALUES ( 'Miami Marlins', DEFAULT )


CHill60

Вы ничего не добавили к решению, которое я опубликовал 2 года назад.