选择进入,创建没有标识属性的表

时间:2012-09-22 14:14:23

标签: sql sql-server

我有这样的存储过程,在任何表的插入命令后执行

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,可以从表中为所有列选择没有列的增量标识属性。

4 个答案:

答案 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)