【问题标题】:What's wrong with my INSERT statement? 44我的 INSERT 语句有什么问题? 44
【发布时间】:2014-09-02 03:51:24
【问题描述】:

我正在使用 SQL Server 2008 并希望创建一个过程,该过程只需从一个表中获取数据并将其插入到另一个表中。这是我目前所拥有的:

CREATE PROCEDURE consomVspPools (@start DATE, @end DATE)
AS
CREATE TABLE dbo.temp (pool NVARCHAR (250), endUsedCapacityInKB FLOAT, 
                         startUsedCapacityInKB FLOAT)
WHILE (@end >= @start)
BEGIN
      INSERT INTO temp
      SELECT pool, MAX(capacityInKB), MAX(freeCapacityInKB)
      FROM Vsp_Pool
      WHERE dateCollecte IN (DATEADD(day, -1, @end), @end)
      GROUP BY pool
      SET @end = DATEADD(day, -1, @end)
END
SELECT *
FROM temp
DROP TABLE dbo.temp

我现在知道代码并没有真正做太多,但我必须对其进行大量简化以缩小我的错误(无论如何这对我没有多大帮助)。我得到的错误是:

“列名或提供的值的数量与表定义不匹配”

我是 SQL 新手,所以这可能很明显,但我看不出来,一切对我来说似乎都是为了。

编辑1:

所以这是我知道的代码,按照建议升级:

CREATE PROCEDURE consomVspPools (@start DATE, @end DATE)
AS
CREATE TABLE #dbo.temp (pool NVARCHAR (250), endUsedCapacityInKB FLOAT, 
                      startUsedCapacityInKB FLOAT)
WHILE (@end >= @start)
BEGIN
      INSERT INTO temp (pool, endUsedCapacityInKB, startUsedCapacityInKB)
      SELECT pool, MAX(capacityInKB), MAX(freeCapacityInKB)
      FROM Vsp_Pool
      WHERE dateCollecte IN (DATEADD(day, -1, @end), @end)
      GROUP BY pool
      SET @end = DATEADD(day, -1, @end)
END
SELECT *
FROM temp
DROP TABLE #dbo.temp

但这给了我以下错误:

“无效的列名‘池’”

仅供参考,表 Vsp_Pool 和 temp 中都存在池。

【问题讨论】:

  • 我将从使用一些最佳实践开始 - 完全限定您的对象(database.schema.temp、database.schema.vsp_pool),列出您的插入列(INSERT INTO database.schema.temp (pool, endUsedCapacityInKB, startUsedCapacityInKB) SELECT ...),并使用临时表:CREATE TABLE #Temp...
  • 另一件事。这是在一个过程中,您正在创建一个持久表。此过程将在第二次运行时失败,因为表 temp 已经存在。我建议将其更改为临时表。创建表#temp...
  • 我刚刚注意到你也把桌子放在了最后。啊!!!不需要持久表甚至临时表。只需在单个 select 语句中选择您想要的数据。
  • 就像我说的,这是一个非常简化的代码版本,我不能在一个语句中选择所有我想要的。我将需要使用另一个软件对列进行计算,并且基于我对 SQL 的所有了解(我承认这一点并不多),我想要执行的计算无法用 SQL 完成。所以我宁愿像这样在表格中保留列并从那里开始工作。
  • @user3779627,在任何情况下都不要在存储过程中创建永久表。这只是一个不好的做法。学习使用临时表。

标签: sql-server sql-server-2008 insert while-loop do-while


【解决方案1】:

您需要在“插入”语句中包含列名。

INSERT INTO temp (poolVal, maxcapacity, maxfreecapacity)

可能有助于在我的示例中为 select 语句中的列名称提供别名。#

pool 是一个关键字,可以使用其他任何名称作为您的字段名称。

【讨论】:

  • 实际上,虽然这确实是一种最佳做法,但在技术上并不是必需的。我必须对其进行测试以确定,但我能够在不列出列名的情况下插入。
  • 如果我这样做,我会收到“关键字 WHERE 附近的语法错误”
  • @Dave.Gugg,如果列数多于他添加的列数(列将为空),则需要。无论如何,这是我永远不会通过代码审查的东西。您需要能够告诉您插入的列将与您插入的列完全匹配。在未列出列的情况下编写插入语句是不负责任的。如果您这样做,您将遇到数据完整性问题,这远远超出了最佳实践。
【解决方案2】:
Put if condition because while is in infinite loop:


CREATE PROCEDURE consomVspPools (@start DATE, @end DATE)
AS
CREATE TABLE dbo.temp (pool NVARCHAR (250), endUsedCapacityInKB FLOAT, 
                         startUsedCapacityInKB FLOAT)
if (@end >= @start)
BEGIN
      INSERT INTO temp
      SELECT pool, MAX(capacityInKB), MAX(freeCapacityInKB)
      FROM Vsp_Pool
      WHERE (dateCollecte >= (DATEADD(day, -1, @end)) and  (dateCollecte <= @end)
      GROUP BY pool
      SET @end = DATEADD(day, -1, @end)
END
SELECT *
FROM temp
DROP TABLE dbo.temp

【讨论】:

  • 我认为循环很好,因为我在每次循环迭代后使用 SET 减小 @end 的值
  • 只需检查解决方案
【解决方案3】:

您可能听说过 SQL 是一种声明性语言,而不是过程性语言。这意味着你应该声明如何你想做什么,而不是说如何。 SQL 引擎针对这种行为进行了优化。由于这个原因,通常不使用 WHILE 语句。不知道你的数据库结构,我最好的猜测是,你应该尝试这样的事情:

CREATE PROCEDURE consomVspPools (@start DATE, @end DATE)
AS

BEGIN
    SELECT *
    FROM
        (
        SELECT dateCollecte, pool, MAX(capacityInKB), MAX(freeCapacityInKB)
        FROM Vsp_Pool 

        -- Is "dateCollecte" a typo? Might be your issue.
        WHERE dateCollecte BETWEEN @start AND @end
        GROUP BY dateCollecte, pool
        )
END

查看BETWEEN 声明。另请注意,我正在从查询结果中查询并完全避免使用临时表。这里的要点是开始分组思考。如果一个查询感觉就像您正在遍历并自动更新每个条目而不是作为一个集合,那么可能有一种更好的、经过 SQL 优化的方式来重写它。

【讨论】:

  • 对于我在这里的示例代码,你是对的,这会更好,但对于我必须做的事情,它不会做。就像我说的那样,我简化了很多代码,只是为了知道我在 INSERT 中的错误,但我已经尝试了 BETWEEN(这是我的第一个想法),但它并没有完全符合我的目标。
  • 那么我的猜测是使用 INSERT 语句中的列名,如@user3195030 所说,然后更改 WHERE 语句中的错字。我很确定“dateCollecte”应该是“dateCollected”我错了吗?
  • 另外,也许将IN语句更改为两个等于语句WHERE dateCollected == DATEADD(day, -1, @end) OR dateCollected == @end
  • 如果您检查编辑,我已按照建议添加了列名,并且 dateCollecte 不是错字,它是法语啊啊啊!我会尝试 equals 但我之前使用过 IN 并且效果很好......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-30
  • 2013-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多