【问题标题】:My store procedure only executes my first select statement while I wrote three?我的存储过程只执行我的第一个选择语句,而我写了三个?
【发布时间】:2019-05-12 06:20:59
【问题描述】:

这是我的桌子:

CREATE TABLE [dbo].[InfoTable] 
(
    [Id]               INT IDENTITY (1, 1) NOT NULL,
    [TimeSpanColumn]   NVARCHAR(50) NULL,
    [TimeStampColumn]  DATETIME     NULL,
    [TimeStringColumn] NVARCHAR(50) NULL,
    [TotalSecColumn]   NVARCHAR(50) NULL,

    PRIMARY KEY CLUSTERED ([Id] ASC)
)

我想在 2 个给定日期之间选择 timespans 并将它们子串到另一个表中,如下所示:

 Col1    Col2      col3
 [hh]  |  [mm]  |  [ss]
 ----------------------
 02       55       36
 54       32       41

我的存储过程:

CREATE PROCEDURE sumBetweenDates
    @QueryFromDate DateTime,
    @QueryToDate DateTime
AS
    SELECT 
        SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 1, 2))) as hh
    FROM 
        InfoTable 
    WHERE
        TimeStampColumn BETWEEN @QueryFromDate AND @QueryToDate
    GROUP BY 
        TimeStampColumn

    SELECT 
        SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 3, 2))) AS mm
    FROM 
        InfoTable 
    WHERE
        TimeStampColumn BETWEEN @QueryFromDate AND @QueryToDate
    GROUP BY 
        TimeStampColumn

    SELECT 
        SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 5, 2))) AS ss
    FROM 
        InfoTable 
    WHERE
        TimeStampColumn BETWEEN @QueryFromDate AND @QueryToDate
    GROUP BY 
        TimeStampColumn

它只返回第一次查询的结果。例如:

[hh]
02
54

我怎样才能做到我所说的?

我无法为这些 select 语句分配变量,因为在它们按 timestampcolumn 分组之后可能有多个值

【问题讨论】:

  • 您如何确定它只返回一个结果集?您是在使用 Management Studio 执行该过程还是使用其他客户端?
  • @Damien_The_Unbeliever 我只是在我的 c# 程序中执行了存储过程,并用它只显示一列的结果填充了我的 datagridview。
  • 你想总结什么?

标签: sql sql-server select insert


【解决方案1】:

鉴于您声明的期望结果,我认为您只需要一个包含所有 3 个聚合的 SELECT

SELECT SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 1, 2))) as hh,
  SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 3, 2))) as mm,
  SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 5, 2))) as ss
FROM InfoTable 
where TimeStampColumn between @QueryFromDate and @QueryToDate
GROUP BY TimeStampColumn

但是你的评论:

我只是在我的 c# 程序中执行了存储过程,并用它只显示一列的结果填充了我的 datagridview。

如果您有多个 SELECT 语句,则必须特别注意阅读它们的方式。如果您使用的是SqlDataReader,则可以使用NextResult 方法从一个结果集前进到下一个结果集。如果使用某种形式的数据适配器或类似形式,您需要注意它如何描述如何使用多个结果集。例如。你会寻找填充 DataSetDataTable 的东西。

【讨论】:

  • 是的,这就是我想要的。以及如何在插入新表或 InfoTable 时获得相同的结果?
  • @absolute455 - INSERT 有许多不同的变体。您可能对INSERT (...) VALUES (...) 很熟悉,StepUp 的回答显示INSERT (...) EXEC。但也有INSERT (...) SELECT ...。但是避免创建临时表,因为您将逻辑查询分解为多个块。而是使用子查询/CTE 编写单个查询来表达要完成的整个 任务。
  • 感谢您的建议,但无法理解其含义。 temp tables 是什么意思?我知道代码背后的逻辑含义,但我不明白你对breaking a logical query into multiple chuncks 的定义我也不知道CTEs 和你最后一句话exoressing an entire task 的含义。
  • 当我写这段代码时:Insert into InfoTable(hh,mm,ss) select SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 1, 2))), SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 3, 2))), SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 5, 2))) FROM InfoTable where TimeStampColumn between @QueryFromDate and @QueryToDate GROUP BY TimeStampColumn
【解决方案2】:

如果你想计算列之间的数据,那么只需创建一个临时表来存储存储过程的结果并计算所需的值。

让我举个例子。

  1. 创建存储过程

    CREATE PROCEDURE sumBetweenDates
    @QueryFromDate DateTime,
    @QueryToDate DateTime
    AS
    
    SELECT DISTINCT * FROM (VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 
        12)) AS X(a, a1, a2)
    /*
    --Insert your query here instead of above test values.
    SELECT SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 1, 2))) as hh,
        SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 3, 2))) as mm,
        SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 5, 2))) as ss
    FROM InfoTable 
    WHERE TimeStampColumn between @QueryFromDate and @QueryToDate
    GROUP BY TimeStampColumn
    */        
    
  2. 创建一个表变量来存储存储过程的结果,然后从存储过程sumBetweenDates '2018-12-1', '2018-12-1' 中插入数据。然后在SELECT 声明中你可以做任何你想做的事:

    Declare @T Table (col1 INT, col2 INT, col3 int)
    Insert @T Exec sumBetweenDates '2018-12-1', '2018-12-1'
    
    SELECT 
      t.col1
    , t.col2
    , t.col3 
    , t.col3 - t.col1 CalculatedColumn
    FROM @T t
    

这里是@T 是一个表变量。 Declare @T Table (col1 INT, col2 INT, col3 int)。你可以通过阅读this cool article了解它们之间的区别。

This answer will help to you 如何使用exec stored procedure 向表中插入数据。

In addition, you can read an MSDN article about INSERT using EXEC statement.

【讨论】:

  • 我无法为这些选择语句分配一个变量,因为在它们按timestampcolumn 分组之后可能有多个结果。
  • "如果你想从存储过程中返回数据,那么你需要使用return语句:"我不同意,你应该使用OUTPUT参数,对于标量值;对于初学者来说,你不限于 1。对于数据集,您可以使用INSERT INTO... EXEC... 语法。
  • @Larnu 是的,你是对的,我已经更准确地看到了问题并编辑了我的答案。
  • 你会参考我的链接来阅读insert exec吗?我无法理解你的回答。什么@t。我正在编写sumBetweenDates,所以现在您使用它,但我在该存储过程中没有任何代码sumBetweenDates 实际上是什么?如果它是我的存储过程那么它不完整我没有完全写出来我遇到了问题所以我来到这个网站你指的是什么?
  • 感谢您身临其境的回答。你帮了我很多。真的谢谢你
【解决方案3】:

您的存储过程只包含第一个SELECT 语句,因为您没有使用BEGIN/END

CREATE PROCEDURE sumBetweenDates (
    @QueryFromDate DateTime,
    @QueryToDate DateTime
) AS
BEGIN
    SELECT SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 1, 2))) as hh
    FROM InfoTable 
    WHERE TimeStampColumn between @QueryFromDate and @QueryToDate
    GROUP BY TimeStampColumn;

    SELECT SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 3, 2))) as mm
    FROM InfoTable 
    WHERE TimeStampColumn BETWEEN @QueryFromDate and @QueryToDate
    GROUP BY TimeStampColumn;

    SELECT SUM(CONVERT(INT, SUBSTRING(TimeStringColumn, 5, 2))) as ss
    FROM InfoTable 
    WHERE TimeStampColumn BETWEEN @QueryFromDate and @QueryToDate
    GROUP BY TimeStampColumn;
END;  -- sumBetweenDates

我不确定你想要什么。根据样本数据,您似乎想要:

CREATE PROCEDURE sumBetweenDates (
    @QueryFromDate DateTime,
    @QueryToDate DateTime
) AS
BEGIN
    SELECT DISTINCT CONVERT(INT, SUBSTRING(TimeStringColumn, 1, 2))) as hh,
           CONVERT(INT, SUBSTRING(TimeStringColumn, 3, 2))) as mm,
           CONVERT(INT, SUBSTRING(TimeStringColumn, 5, 2))) as ss               
    FROM InfoTable 
    WHERE TimeStampColumn BETWEEN @QueryFromDate AND @QueryToDate;
END;

但是,这似乎不是特别有用,并且您会猜想您想总结一些东西。

【讨论】:

  • 我不认为你需要 BEGIN/END。在CREATE PROCEDURE 和“header”的剩余位之后,存储过程的主体就是该批次中剩余的所有内容。
猜你喜欢
  • 1970-01-01
  • 2013-02-10
  • 1970-01-01
  • 2019-11-29
  • 1970-01-01
  • 1970-01-01
  • 2017-09-19
  • 2021-11-14
  • 1970-01-01
相关资源
最近更新 更多