我有这样的存储过程,在任何表的插入命令后执行
Create Procedure [dbo].[HistoryInsert](
@TableName nVarchar(500),
@RecordId bigInt
)
As
declare @Query nVarChar(max)
if Not Exists (Select Top 1 1
From Information_schema.tables
Where Table_Name = @TableName + 'History')
Set @Query = 'Select * Into ' + @TableName + 'History FROM ' + @TableName
Else
Set @Query = 'Insert Into ' + @TableName + 'History Select * FROM ' + @TableName
Exec(@Query)
Exec(@Query)
首次执行此过程时,会创建历史记录表。当第二次执行此过程时,插入失败,因为创建的表具有标识column.how,可以从表中为所有列选择没有列的增量标识属性。
答案 0 :(得分:4)
您的代码看起来像是试图保留数据更改的历史记录。请考虑使用Change Data Capture而不是滚动自己的解决方案。
允许指定identity
列的插入的一种方法是identity_insert:
SET IDENTITY_INSERT TableName ON
你可以在你的第二个执行官中打开它。由于您要复制整个表,因此在复制之前必须清除历史记录表,例如使用truncate
:
Set @Query =
'truncate table ' + @TableName + 'History; ' +
'set identity_insert ' + @TableName 'History on; ' +
'Insert Into ' + @TableName + 'History Select * FROM ' + @TableName '; ' +
'set identity_insert ' + @TableName 'History off; '
更好的解决方案是修改第一个exec以创建没有identity
列的表。我还没有找到一种切实可行的方法。 SQL Server要求您删除列并重新创建它,这将导致非常繁琐的动态SQL。
答案 1 :(得分:0)
Andomar是对的,如果你可以使用Change Data Capture。但是,如果你仍然坚持使用不支持它的版本,你仍然可以解决这个问题。
根据Microsoft ...
当新表中选择现有标识列时,新建 列继承IDENTITY属性,除非以下之一 条件是真的:
- SELECT语句包含连接,GROUP BY子句或聚合函数。
- 使用UNION连接多个SELECT语句。
- 标识列在选择列表中列出多次。
- 标识列是表达式的一部分。
- 标识列来自远程数据源。
因此,例如,如果你知道标识列的名称,你可以做这样的事情,而不需要知道任何其他列:
Exec('select ' + @identityColName + ' as id_temp123, * into ' + @TableName + 'History from ' + @TableName)
Exec('alter table ' + @TableName + ' drop column id_temp123')
这也保留了列顺序。
您可以通过查看信息架构以编程方式查找标识列(如果有)。例如:
select TABLE_NAME + '.' + COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where
TABLE_SCHEMA = 'dbo' and
TABLE_NAME = 'MyTable' and
columnProperty(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
答案 2 :(得分:0)
有一些救生员
select *
into #tmp_table
from Table
union all
select *
from Table
where 1<>1
使用联合都弃用SQL Endgine来继承约束和身份。
When an existing identity column is selected into a new table, the new column inherits the IDENTITY property, unless one of the following conditions is true: - The SELECT statement contains a join, GROUP BY clause, or aggregate function. - Multiple SELECT statements are joined by using UNION. - The identity column is listed more than one time in the select list. - The identity column is part of an expression. - The identity column is from a remote data source.
答案 3 :(得分:0)
尝试以下查询:我发现此查询正常运行。这将选择没有标识= 1的列中的数据
DECLARE @Temp NVARCHAR(MAX);
DECLARE @SQL NVARCHAR(MAX);
SET @Temp = '';
SELECT @Temp = @Temp + COLUMN_NAME + ', ' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ='Person' AND columnProperty(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') != 1
SET @SQL = 'SELECT ' + SUBSTRING(@Temp, 0, LEN(@Temp)) +' FROM [Person]';
EXECUTE SP_EXECUTESQL @SQL;
您可以从sys.columns表中获取列名详细信息
尝试以下查询:
SELECT * FROM SYS.COLUMNS
WHERE object_id = OBJECT_ID('dbo.TableName')
AND [Name] <> 'ColumnName'
DECLARE @sql as VARCHAR(8000)
SET @sql = 'SELECT '
SELECT @sql += [Name] + ', ' FROM SYS.COLUMNS
WHERE object_id = OBJECT_ID('dbo.TableName')
AND [Name] <> 'ColumnName'
SELECT @sql += ' FROM Dbo.TableName'
EXEC(@sql)