【发布时间】:2010-10-17 08:53:24
【问题描述】:
我希望能够将具有标识列的表中的数据插入 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,随后插入失败并出现错误“表'#Tmp_MyTable'中标识列的显式值只能在使用列列表并且IDENTITY_INSERT为ON时指定。”
在 TSQL 中有没有办法删除临时表中列的标识属性而不显式列出所有列?我特别想使用“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' 中的标识列指定显式值。” em> - 我特别不想使用上面解释的列列表。
更新 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 建议仅将键存储在临时表中也是一个不错的建议,尽管在这种特定情况下,我更喜欢将所有列都放在临时表中是有原因的。
【问题讨论】:
-
它对我有用,看我回答...
-
更新 3 中的解决方案对我来说非常有用。我试图将 UPDATE 的 OUTPUT 放入临时表中而不指定列(大约 100 个!)
标签: sql sql-server-2005 tsql