【问题标题】:SQL Stored Procedure with While loop and results inserted into temp table带有 While 循环的 SQL 存储过程和插入临时表的结果
【发布时间】:2014-08-28 21:44:57
【问题描述】:

我正在尝试创建一个带有循环的动态存储过程,该循环将数据插入到 SQL Server 2008 中的临时表中。

到目前为止,我有这段代码,但不确定创建表的逻辑是否正确,我不确定将查询的插入部分放在哪里。

CREATE PROCEDURE [dbo].[SP_NominalRecord]
@ORGCODE VARCHAR(6),
@CurrentPeriod INT,
@ENDPeriod INT, 
@Nominal INT

AS 
BEGIN 
SET NOCOUNT ON;
DECLARE @SQL NVARCHAR(MAX)

 SET @ENDPeriod = @CurrentPeriod-5

IF OBJECT_ID('tempdb..#TempResults')IS NOT NULL DROP TABLE #TempResults

WHILE (@CurrentPeriod<> @ENDPeriod)--loop through until endperiod is reached

    BEGIN
        CREATE TABLE #TempResults(ID bigint IDENTITY(1,1) NOT NULL PRIMARY KEY, CostCode INT, CostDescr VARCHAR(50), BankACType CHAR(2), FinPeriodNr SMALLINT, 
                BalJan DECIMAL(12, 2), BalFeb DECIMAL(12, 2), BalMar DECIMAL(12, 2),
                BalApr DECIMAL(12, 2), BalMay DECIMAL(12, 2), BalJun DECIMAL(12, 2),
                BalJul DECIMAL(12, 2), BalAug DECIMAL(12, 2), BalSep DECIMAL(12, 2),
                BalOct DECIMAL(12, 2), BalNov DECIMAL(12, 2), BalDec DECIMAL(12, 2), Balance DECIMAL(12, 2))


    SET @SQL = N'SELECT CostCodes.CostCode, CostCodes.CostDescr, CostCodes.BankACType, CostCodeBalance' + @ORGCODE + '.FinPeriodNr, 
                CostCodeBalance' + @ORGCODE + '.BalJan, CostCodeBalance' + @ORGCODE + '.BalFeb, CostCodeBalance' + @ORGCODE + '.BalMar,
                CostCodeBalance' + @ORGCODE + '.BalApr, CostCodeBalance' + @ORGCODE + '.BalMay, CostCodeBalance' + @ORGCODE + '.BalJun,
                CostCodeBalance' + @ORGCODE + '.BalJul, CostCodeBalance' + @ORGCODE + '.BalAug, CostCodeBalance' + @ORGCODE + '.BalSep,
                CostCodeBalance' + @ORGCODE + '.BalOct, CostCodeBalance' + @ORGCODE + '.BalNov, CostCodeBalance' + @ORGCODE + '.BalDec,
                Sum(CostCodeBalance' + @ORGCODE + '.BalJan + CostCodeBalance' + @ORGCODE + '.BalFeb + CostCodeBalance' + @ORGCODE + '.BalMar +
                CostCodeBalance' + @ORGCODE + '.BalApr + CostCodeBalance' + @ORGCODE + '.BalMay + CostCodeBalance' + @ORGCODE + '.BalJun +
                CostCodeBalance' + @ORGCODE + '.BalJul + CostCodeBalance' + @ORGCODE + '.BalAug + CostCodeBalance' + @ORGCODE + '.BalSep +
                CostCodeBalance' + @ORGCODE + '.BalOct + CostCodeBalance' + @ORGCODE + '.BalNov + CostCodeBalance' + @ORGCODE + '.BalDec) AS Balance

        FROM CostCodeBalance' + @ORGCODE + ' INNER JOIN CostCodes ON CostCodeBalance' + @ORGCODE + '.CostCode = CostCodes.CostCode 

        WHERE Costcodes.Costcode = @Nominal AND CostCodeBalance' + @ORGCODE + '.FinPeriodNr =@CurrentPeriod

        GROUP BY CostCodes.CostCode, CostCodes.CostDescr, CostCodes.BankACType, CostCodeBalance' + @ORGCODE + '.FinPeriodNr, 
                CostCodeBalance' + @ORGCODE + '.BalJan, CostCodeBalance' + @ORGCODE + '.BalFeb, CostCodeBalance' + @ORGCODE + '.BalMar,
                CostCodeBalance' + @ORGCODE + '.BalApr, CostCodeBalance' + @ORGCODE + '.BalMay, CostCodeBalance' + @ORGCODE + '.BalJun,
                CostCodeBalance' + @ORGCODE + '.BalJul, CostCodeBalance' + @ORGCODE + '.BalAug, CostCodeBalance' + @ORGCODE + '.BalSep,
                CostCodeBalance' + @ORGCODE + '.BalOct, CostCodeBalance' + @ORGCODE + '.BalNov, CostCodeBalance' + @ORGCODE + '.BalDec;';

    SET @CurrentPeriod = @CurrentPeriod -1; --subtrace current period by 1
    END

    EXEC sp_executesql @sql, N'@ORGCODE VARCHAR(6),@CurrentPeriod INT, @ENDPeriod INT, @NOMINAL INT', @ORGCODE,@CurrentPeriod, @ENDPeriod, @NOMINAL; 

    SELECT * FROM #TempResults --to select the results of the code above

END

我对 SQL 还是很陌生,所以请告诉我你的想法。我将其称为 Access 2013 的传递查询。

【问题讨论】:

  • 首先,把“SELECT * FROM #TempResults”放在while外面。
  • 为什么不写动态sql插入数据而不是选择数据呢?此外,create table #TempResult 是否应该移出while 循环?也许在drop table之后
  • 您可能想要查看别名 - 它们允许您为表(或列)提供替代名称,这意味着您只需要将 @ORGCODE 连接到该字符串中一次。另外,不要命名以sp_ 开头的存储过程——这是为微软的系统过程保留的。
  • 不知道为什么我收到了否定...至少解释一下为什么我得到否定所以我理解...
  • 老实说,这里最大的问题是缺乏标准化。为什么需要将每个 ORGCODE 的数据存储在自己的表中?我会在表中包含一列 ORGCODE。然后你需要做的就是添加一个where子句,你根本不需要动态sql。

标签: sql sql-server-2008 ms-access stored-procedures while-loop


【解决方案1】:

您需要在查询中检查一些事项:

  1. @ENDPeriod 是输入变量吗,因为您已对其进行了硬编码 SET @ENDPeriod = @CurrentPeriod-5 的值确保它是 正确的逻辑。
  2. CostCodeBalance' + @ORGCODE + '.FinPeriodNr 如果这是一个整数值,那么您可以将其与 CostCodeBalance' + @ORGCODE + '.FinPeriodNr BETWEEN @CurrentPeriod AND @ENDPeriod 进行比较。

所以将你的存储过程重写为:

CREATE PROCEDURE [dbo].[SP_NominalRecord]
@ORGCODE VARCHAR(6),
@CurrentPeriod INT,
@ENDPeriod INT, 
@Nominal INT

AS 
BEGIN 
SET NOCOUNT ON;
DECLARE @SQL NVARCHAR(MAX), 
        @END INT;

SET @ENDPeriod = @CurrentPeriod-5 -- Please verify if this logic is actually required

IF OBJECT_ID('tempdb..#TempResults')IS NOT NULL DROP TABLE #TempResults

--WHILE (@CurrentPeriod<> @ENDPeriod)--loop through until endperiod is reached 
-- No need of while loop so commented    
    --BEGIN

        CREATE TABLE #TempResults
        (ID bigint IDENTITY(1,1) NOT NULL PRIMARY KEY,
         CostCode INT,
         CostDescr VARCHAR(50),
         BankACType CHAR(2),
         FinPeriodNr SMALLINT,
         BalJan DECIMAL(12, 2),
         BalFeb DECIMAL(12, 2),
         BalMar DECIMAL(12, 2),
         BalApr DECIMAL(12, 2),
         BalMay DECIMAL(12, 2),
         BalJun DECIMAL(12, 2),
         BalJul DECIMAL(12, 2),
         BalAug DECIMAL(12, 2),
         BalSep DECIMAL(12, 2),
         BalOct DECIMAL(12, 2),
         BalNov DECIMAL(12, 2),
         BalDec DECIMAL(12, 2),
         Balance DECIMAL(12, 2))


    SET @SQL = N'
    SELECT CostCodes.CostCode,
    CostCodes.CostDescr,
    CostCodes.BankACType,
    CostCodeBalance' + @ORGCODE + '.FinPeriodNr, 
    CostCodeBalance' + @ORGCODE + '.BalJan,
    CostCodeBalance' + @ORGCODE + '.BalFeb,
    CostCodeBalance' + @ORGCODE + '.BalMar,
    CostCodeBalance' + @ORGCODE + '.BalApr,
    CostCodeBalance' + @ORGCODE + '.BalMay,
    CostCodeBalance' + @ORGCODE + '.BalJun,
    CostCodeBalance' + @ORGCODE + '.BalJul,
    CostCodeBalance' + @ORGCODE + '.BalAug,
    CostCodeBalance' + @ORGCODE + '.BalSep,
    CostCodeBalance' + @ORGCODE + '.BalOct,
    CostCodeBalance' + @ORGCODE + '.BalNov,
    CostCodeBalance' + @ORGCODE + '.BalDec,
    Sum(CostCodeBalance' + @ORGCODE + '.BalJan
    + CostCodeBalance' + @ORGCODE + '.BalFeb +
    CostCodeBalance' + @ORGCODE + '.BalMar +
    CostCodeBalance' + @ORGCODE + '.BalApr +
    CostCodeBalance' + @ORGCODE + '.BalMay + 
    CostCodeBalance' + @ORGCODE + '.BalJun +
    CostCodeBalance' + @ORGCODE + '.BalJul + 
    CostCodeBalance' + @ORGCODE + '.BalAug + 
    CostCodeBalance' + @ORGCODE + '.BalSep +
    CostCodeBalance' + @ORGCODE + '.BalOct + 
    CostCodeBalance' + @ORGCODE + '.BalNov + 
    CostCodeBalance' + @ORGCODE + '.BalDec) AS Balance
    FROM CostCodeBalance' + @ORGCODE + ' 
    INNER JOIN CostCodes ON CostCodeBalance' + @ORGCODE + '.CostCode 
    = CostCodes.CostCode 
    WHERE Costcodes.Costcode = @Nominal 
    AND CostCodeBalance' + @ORGCODE + '.FinPeriodNr 
    BETWEEN @CurrentPeriod  AND @ENDPeriod
    GROUP BY CostCodes.CostCode,
    CostCodes.CostDescr, 
    CostCodes.BankACType, 
    CostCodeBalance' + @ORGCODE + '.FinPeriodNr, 
    CostCodeBalance' + @ORGCODE + '.BalJan,
    CostCodeBalance' + @ORGCODE + '.BalFeb,
    CostCodeBalance' + @ORGCODE + '.BalMar,
    CostCodeBalance' + @ORGCODE + '.BalApr,
    CostCodeBalance' + @ORGCODE + '.BalMay,
    CostCodeBalance' + @ORGCODE + '.BalJun,
    CostCodeBalance' + @ORGCODE + '.BalJul,
    CostCodeBalance' + @ORGCODE + '.BalAug,
    CostCodeBalance' + @ORGCODE + '.BalSep,
    CostCodeBalance' + @ORGCODE + '.BalOct,
    CostCodeBalance' + @ORGCODE + '.BalNov, 
    CostCodeBalance' + @ORGCODE + '.BalDec;';

    --SET @CurrentPeriod = @CurrentPeriod -1; --subtrace current period by 1
    --END

    EXEC sp_executesql @sql, N'@ORGCODE VARCHAR(6),@CurrentPeriod INT, @ENDPeriod INT
    , @NOMINAL INT', @ORGCODE,@CurrentPeriod, @ENDPeriod, @NOMINAL; 

    SELECT * FROM #TempResults --to select the results of the code above

END

【讨论】:

  • FROM CostCodeBalance' + @ORGCODE + ' as ccb INNER JOIN 让您只需使用 ccb 在其他任何地方引用该表,并避免数百次重复 + @ORGCODE +
  • 感谢@Damien_The_Unbeliever ..指出这一点。我将更新查询..:)
  • @Deepshikha 您使用BETWEEN 的想法是我需要的确切替代方案,它做同样的事情但不那么复杂。谢谢
猜你喜欢
  • 1970-01-01
  • 2018-07-05
  • 2020-01-26
  • 2015-03-05
  • 2018-07-05
  • 1970-01-01
  • 2018-11-16
  • 1970-01-01
相关资源
最近更新 更多