【问题标题】:SQL Server 2008 R2 - why does my temp table think it has an identity column?SQL Server 2008 R2 - 为什么我的临时表认为它有一个标识列?
【发布时间】:2024-01-18 21:49:01
【问题描述】:

我正在尝试创建一个存储过程,该过程将能够通过使用部门 ID 来限制返回的记录数。我正在尝试通过加入临时表来限制记录。

当我运行下面的代码时,我得到了错误:

只有在使用列列表并且 IDENTITY_INSERT 为 ON 时,才能为表“#department”中的标识列指定显式值。

代码如下:

DECLARE @departmentID INT
SET @departmentID = 4

-- create temp department table --
select top 0 * into #department from PayrollDepartment

-- load temp department table
IF @departmentID < 1 OR @departmentID IS NULL
BEGIN
    INSERT INTO #department SELECT * FROM PayrollDepartment
END 
ELSE
BEGIN
    INSERT INTO #department SELECT * FROM PayrollDepartment WHERE PayrollDepartmentID =     @departmentID
END

我开始:

IF @departmentID < 1 OR @departmentID IS NULL
BEGIN
    SELECT * INTO #department FROM ApplicationEmployeeInfo..PayrollDepartment
END 
ELSE
BEGIN
    SELECT * INTO #department FROM ApplicationEmployeeInfo..PayrollDepartment WHERE PayrollDepartmentID = @departmentID
END

但我得到了错误:

数据库中已经有一个名为“#department”的对象

我不是 SQL 专家,所以也许有更好的方法来做到这一点?

【问题讨论】:

  • 之后你需要对#Department 做些什么吗?还是只是返回结果?
  • 如果您执行SELECT TOP 0 * INTO ...,您已经创建了表。您不能再次使用INTO。你需要INSERT ... SELECT
  • 这是一份报告。我正在尝试使存储过程“动态”,这样我就可以获得所有员工记录,或者只是部门的记录。我试图避免使用硬编码 SQL,并且我没有两个代码块(或存储过程),唯一的区别是 where 子句。

标签: sql sql-server-2008-r2 temp-tables identity-insert


【解决方案1】:

您的临时表有一个标识列,因为SELECT .. INTO 复制了原始表的表结构,该表有一个标识列。

我建议明确创建您的临时表,并列出您从部门中选择的列。在生产代码中几乎是never a good idea to use SELECT *,所以我建议明确列出您的选择并插入列:

CREATE TABLE #Department
(   PayrollDepartmentID INT NOT NULL,
    <more columns>
);

IF @departmentID < 1 OR @departmentID IS NULL
    BEGIN
        INSERT #Department (PayrollDepartmentID, <more columns>)
        SELECT  PayrollDepartmentID, <more columns>
        FROM    PayrollDepartment;
    END
ELSE
    BEGIN
        INSERT #Department (PayrollDepartmentID, <more columns>)
        SELECT  PayrollDepartmentID, <more columns>
        FROM    PayrollDepartment
        WHERE   PayrollDepartmentID = @departmentID;
    END
    

这似乎需要更多工作,而且肯定更冗长,但从长远来看,它是更好的实践和更稳健的做法。这也意味着您可以通过仅从 PayrollDepartment 获取您实际需要的列来避免冗余

【讨论】:

  • 感谢您的帮助!我找到的带有SELECT TOP 0 INTO 代码的页面说需要在事后添加主键。另一个建议使用SET IDENTITY_INSERT #department ON 会起作用(但它没有,当然没有列列表)
  • 没问题。我对SELECT .. INTO 语法没有任何反对意见,它对于即席查询非常方便,但正如我所说,我会多花 5 分钟来显式地编写和创建表。