sql - 如何在SQL Server 2005中删除列的IDENTITY属性

标签 sql sql-server-2005 tsql

我希望能够将具有标识列的表中的数据插入SQL Server 2005中的临时表中。

TSQL看起来像:

-- Create empty temp table
SELECT *
INTO #Tmp_MyTable
FROM MyTable
WHERE 1=0
...
WHILE ...
BEGIN
    ...
    INSERT INTO #Tmp_MyTable
    SELECT TOP (@n) *
    FROM MyTable
    ...

END

上面的代码创建了带有标识列的#Tmp_Table,随后插入失败,并显示错误“仅在使用列列表且IDENTITY_INSERT为ON的情况下,才能为表'#Tmp_MyTable'中的标识列指定一个显式值”。

在TSQL中,有没有一种方法可以将临时表中的列的identity属性删除而无需显式列出的所有列?我特别想使用“SELECT *”,以便在将新列添加到MyTable时代码将继续工作。

我相信删除并重新创建该列将更改其位置,从而无法使用SELECT *。

更新:

我已尝试按照一个响应中的建议使用IDENTITY_INSERT。它不起作用-请参阅下面的复制内容。我究竟做错了什么?
-- Create test table
CREATE TABLE [dbo].[TestTable](
    [ID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NULL,
 CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)
) 
GO
-- Insert some data
INSERT INTO TestTable
(Name)
SELECT 'One'
UNION ALL
SELECT 'Two'
UNION ALL
SELECT 'Three'
GO
-- Create empty temp table
SELECT *
INTO #Tmp
FROM TestTable
WHERE 1=0

SET IDENTITY_INSERT #Tmp ON -- I also tried OFF / ON
INSERT INTO #Tmp
SELECT TOP 1 * FROM TestTable

SET IDENTITY_INSERT #Tmp OFF 
GO
-- Drop test table
DROP TABLE [dbo].[TestTable]
GO

请注意错误消息“当使用列列表并且IDENTITY_INSERT为ON时,只能在中指定表'#TmpMyTable'中标识列的显式值”。 -我特别不想使用如上所述的列列表。

更新2
尝试过the suggestion from Mike,但这给出了相同的错误:
-- Create empty temp table
SELECT *
INTO #Tmp
FROM (SELECT
      m1.*
      FROM TestTable                 m1
          LEFT OUTER JOIN TestTable  m2 ON m1.ID=m2.ID
      WHERE 1=0
 ) dt

INSERT INTO #Tmp
SELECT TOP 1 * FROM TestTable

至于为什么要这样做:MyTable是一个临时表,其中可以包含大量要合并到另一个表中的行。我想处理登台表中的行,插入/更新我的主表,并在每个事务处理N行的循环中从登台表中删除它们。我意识到还有其他方法可以实现这一目标。

更新3

我无法使Mike's solution工作,但是它建议了以下可行的解决方案:以非身份列为前缀并删除身份列:
SELECT CAST(1 AS NUMERIC(18,0)) AS ID2, *
INTO #Tmp
FROM TestTable
WHERE 1=0
ALTER TABLE #Tmp DROP COLUMN ID

INSERT INTO #Tmp
SELECT TOP 1 * FROM TestTable

Mike的建议只在临时表中存储键也是一个不错的建议,尽管在这种特定情况下,由于某些原因,我更倾向于将所有列都存储在临时表中。

最佳答案

如果您只是按照您的描述来处理行,那么最好仅在临时表中选择前N个主键值,例如:

CREATE TABLE #KeysToProcess
(
     TempID    int  not null primary key identity(1,1)
    ,YourKey1  int  not null
    ,YourKey2  int  not null
)

INSERT INTO #KeysToProcess (YourKey1,YourKey2)
SELECT TOP n YourKey1,YourKey2  FROM MyTable

键不应该经常更改(我希望如此),但是其他列可以这样做不会有任何危害。

得到插入的@@ ROWCOUNT,您可以在TempID上做一个简单的循环,其中从1到@@ ROWCOUNT

和/或

只需将#KeysToProcess加入您的MyKeys表即可,无需重复所有数据。

,这在我的SQL Server 2005上运行良好,其中MyTable.MyKey是一个标识列。
-- Create empty temp table
SELECT *
INTO #TmpMikeMike
FROM (SELECT
      m1.*
      FROM MyTable                 m1
          LEFT OUTER JOIN MyTable  m2 ON m1.MyKey=m2.MyKey
      WHERE 1=0
 ) dt

INSERT INTO #TmpMike
SELECT TOP 1 * FROM MyTable

SELECT * from #TmpMike

编辑
这项工作,没有任何错误...
-- Create empty temp table
SELECT *
INTO #Tmp_MyTable
FROM (SELECT
          m1.*
          FROM MyTable                 m1
              LEFT OUTER JOIN MyTable  m2 ON m1.KeyValue=m2.KeyValue
          WHERE 1=0
     ) dt
...
WHILE ...
BEGIN
    ...
    INSERT INTO #Tmp_MyTable
    SELECT TOP (@n) *
    FROM MyTable
    ...

END

,但是,您真正的问题是什么? 为什么在将“*”插入此临时表时需要循环?您也许可以改变策略并总体上提出更好的算法。

关于sql - 如何在SQL Server 2005中删除列的IDENTITY属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/713960/

相关文章:

mysql - 如何找到最接近的值并将其与记录合并?

sql - 修改SQL Server中的xml元素名称

sql - 计算每月 16 日到 15 日的小时数的存储过程

sql - 如果其他列为空,则选择一列

sql - 如何解决 MS-Access 中的 "Enter Parameter value"错误

sql - SQL Server 2000 中的 "db_owner"和 "the user that owns the database"有什么区别?

MySQL在某些日期之间找到重复的行

c# - Entity Framework 连接字符串问题

sql - 如何在 SQL Server 2005 中获取 (One Before Last) 行

sql-server-2005 - 在 Visual C++ 中执行查询的最简单方法是什么