寻找SQL重写解决方案

时间:2014-12-29 20:42:39

标签: sql-server vb.net

大约5年前,一个很长的SQL程序是由一个在这里工作的人创建的。

这些过程在带有VB代码的ASP.NET数据库中使用。文本框值被硬编码为所有数据库条目的值,无论字段需要何种类型。

示例:

dim sqlCommand as String = "EXEC dbo.StoredProcedureN N'" & textbox1.Value & "'"
dim oledb as New OleDbCommand(sqlCommand)

所有这些都包含在Try / Catch块中。如果引发异常,网页将显示“未找到记录。”

由于我们的数据库是Microsoft SQL数据库,因此我用OleDbCommand对象替换了SqlCommand个对象。我也知道SqlClient命名空间以及它将会做什么和不会做什么。使用OleDb包不是这样。

然后,我通过声明所有存储过程调用并将这些参数与数据库中声明的内容相匹配来清理VB代码。

示例:

Using cmd = new SqlCommand("StoredProcedureN")
  cmd.Parameters.Add("@value1", SqlDbType.NVarChar, 50).Value = textbox1.Value

所以,这很好,除非现在我们知道许多存储过程已经失败,我们认为没有记录。

以下是我现在遇到的2个错误:

  

将varchar数据类型转换为日期时间数据类型会导致超出范围的值。

  

子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。

现在,我遇到的问题是我善于理解他在存储过程中尝试做什么。

看看他的代码,几乎看起来整个事情都可以用一个查询编写,因此变成了 View ,但我的SQL技能还不够好让我理解如何在几个简短的步骤中写下所有这些。

我确实需要修复这些存储过程,以便在将数据库从旧版Windows 2003服务器迁移到新服务器时维护此代码。

我创建了一个SQL Fiddle,它为此存储过程中使用的所有表创建模式:

http://sqlfiddle.com/#!3/1a6c2/2/1

对于那些想要只看到SQL的人:

ALTER PROCEDURE [dbo].[PtsInitialView20141229](@afeNum nvarchar(50)) AS BEGIN
  SET NOCOUNT ON;
  DECLARE @ptsSummary TABLE (
  costCodeDesc NVarChar(50),
  costCode NVarChar(50),
  userDesc NVarChar(50),
  approvedAmt Money,
  commitTotal Money,
  stotal Money,
  estCost Money,
  finalCost Money,
  amountDiff Money,
  percentDiff Decimal(18,2),
  noteID Int,
  lastInvoiceTran Char(12),
  lastUserSave Char(12),
  updateIndicator Int
  );
  DECLARE @mproSummary TABLE (
  detCostCode NVarChar(50),
  mproTotal Money
);
DECLARE @ptsUserSummary TABLE ( -- Summarize user table by AFE number and cost code
  userCostCode NVarChar(50),
  userDescribe NVarChar(50),
  userEstimate money,
  userNoteID int,
  userNote NVarChar(MAX)
);
DECLARE @lawsonApproved TABLE ( -- Summarize Lawson Activity table budget by afe and cost code line items
  lawActCostCode NVarChar(50),
  lawActAmount money
);
DECLARE @ptsUserNoteSummary TABLE (
  noteCostCode NVarChar(50),
  userNoteID [int] IDENTITY (1,1) NOT NULL,
  noteText NVarChar(MAX)
);

INSERT INTO @ptsSummary (costCodeDesc, costCode, stotal, lastInvoiceTran) 
  SELECT LEFT(A.description, 20), L.acctCategory, CONVERT(money, SUM(L.tranAmount)), MAX(L.runDate) 
  FROM dbo.lawAPdata L, dbo.mpro_actCodes A 
  WHERE activity = @afeNum and L.acctCategory = A.actCode 
  GROUP BY A.description, L.acctCategory;

INSERT INTO @mproSummary (mproTotal, detCostCode) 
  SELECT SUM((pdqty-pdccqty)*pdprice), pdafecat 
  FROM mpro_detail 
  WHERE pdponum IN (SELECT phponum FROM dbo.mpro_header WHERE (phafeno=@afeNum)) 
  GROUP BY pdafecat;

INSERT INTO @ptsUserSummary (userCostCode, userDescribe, userEstimate) 
  SELECT costCode, userDescription, EstimatedFinal 
  FROM dbo.ptsUserTableMay09 
  WHERE afeNumber=@afeNum;

INSERT INTO @lawsonApproved (lawActCostCode, lawActAmount) 
  SELECT activityCode, acAmount 
  FROM dbo.lawACApproved 
  WHERE afeNumber=@afeNum;

UPDATE @ptsSummary 
  SET commitTotal=(SELECT mproTotal FROM @mproSummary WHERE detCostCode=costCode);

INSERT INTO @ptsSummary (costCodeDesc, costCode, approvedAmt, stotal, estCost, finalCost) 
  SELECT LEFT(A.description,20), L.lawActCostCode, L.lawActAmount, '0', '0', '0' 
  FROM dbo.mpro_actCodes A, @lawsonApproved L 
  WHERE L.lawActCostCode = A.actCode AND L.lawActCostCode NOT IN (SELECT costCode from @ptsSummary);

INSERT INTO @ptsSummary (costCodeDesc, costCode, approvedAmt, commitTotal, stotal, estCost, finalCost) 
  SELECT LEFT(A.description, 20), L.detCostCode, '', L.mproTotal, '', '', '' 
  FROM dbo.mpro_actCodes A, @mproSummary L 
  WHERE L.detCostCode = A.actCode AND L.detCostCode NOT IN (SELECT costCode from @ptsSummary);

UPDATE @ptsSummary 
  SET approvedAmt=(SELECT SUM(lawActAmount) 
  FROM @lawsonApproved 
  WHERE lawActCostCode=costCode 
  GROUP BY lawActCostCode);

UPDATE @ptsSummary 
  SET finalCost = (SELECT SUM(userEstimate) 
  FROM @ptsUserSummary 
  WHERE UserCostCode=costCode 
  GROUP BY userCostCode);

UPDATE @ptsSummary 
  SET commitTotal = (SELECT mproTotal FROM @mproSummary WHERE detCostCode=costCode);

INSERT INTO @ptsSummary (costCodeDesc, costCode, userDesc, stotal, finalCost) 
  SELECT LEFT(A.description, 20), U.userCostCode, U.userDescribe, '0', U.userEstimate 
  FROM @ptsUserSummary U, dbo.mpro_actCodes A 
  WHERE U.userCostCode = A.actCode and userCostCode not in (SELECT costCode from @ptsSummary);

UPDATE @ptsSummary 
  SET userDesc=(SELECT userDescribe FROM @ptsUserSummary WHERE userCostCode=costCode);

UPDATE @ptsSummary 
  SET lastUserSave=(SELECT MAX(lastModified) FROM dbo.ptsUserHistoryMay09 WHERE afeNumber=@afeNum);

INSERT INTO @ptsUserNoteSummary (noteCostCode, noteText) 
  SELECT costCode, lineNote 
  FROM dbo.ptsUserNoteTable 
  WHERE afeNumber=@afeNum 
  ORDER BY costCode ASC;

UPDATE @ptsSummary 
  SET noteID=(SELECT userNoteID FROM @ptsUserNoteSummary WHERE noteCostCode=costCode);

UPDATE @ptsSummary 
  SET estCost=(finalCost - stotal);

UPDATE @ptsSummary 
  SET estCost=0 WHERE estCost IS NULL;

UPDATE @ptsSummary 
  SET finalCost=0 WHERE finalCost IS NULL;

UPDATE @ptsSummary 
  SET approvedAmt=0 WHERE approvedAmt IS NULL;

UPDATE @ptsSummary SET updateIndicator=
    CASE
        WHEN lastInvoiceTran Is NULL THEN 0
        WHEN costCode = '99998' THEN 0
        WHEN CAST(lastInvoiceTran AS DATETIME) <= CAST(lastUserSave AS DATETIME) THEN 0
        ELSE 1
    END;

UPDATE @ptsSummary SET amountDiff= 
    CASE 
        WHEN ((stotal+estCost)<approvedAmt) THEN (approvedAmt*-1)+(stotal+estCost)
        ELSE (stotal+estCost) - approvedAmt
    END;

UPDATE @ptsSummary SET percentDiff=
    CASE 
        WHEN (approvedAmt != 0) THEN amountDiff/(approvedAmt/100)
        ELSE '0'
    END;

SELECT costCode + ' - ' + costCodeDesc AS costCodeDesc, costCode, userDesc, CAST(approvedAmt AS decimal(18,0)) AS approvedAmt, CAST(commitTotal AS decimal(18,0)) AS commitTotal, CAST(stotal AS decimal(18,0)) AS stotal, CAST(estCost AS decimal(18,0)) AS estCost, CAST(finalCost AS decimal(18,0)) AS finalCost, CAST(amountDiff AS decimal(18,0)) AS amountDiff, CAST(percentDiff AS decimal(18,0)) AS percentDiff, noteID, updateIndicator 
FROM @ptsSummary 
ORDER BY costCode ASC;

END

这个存储过程可以写成视图吗?

没有?然后可以清理哪些部分,以便留在这里的开发人员知道如何阅读它?每个人似乎都迷失在RAM中创建的所有临时表中。

我不明白它的某些部分,比如这个INSERT命令:

INSERT INTO @ptsSummary (costCodeDesc, costCode, stotal, lastInvoiceTran) 
  SELECT LEFT(A.description, 20), L.acctCategory, CONVERT(money, SUM(L.tranAmount)), MAX(L.runDate) 
  FROM dbo.lawAPdata L, dbo.mpro_actCodes A 
  WHERE activity = @afeNum and L.acctCategory = A.actCode 
  GROUP BY A.description, L.acctCategory;

这是加入这两个表的那种吗?

FROM dbo.lawAPdata L JOIN dbo.mpro_actCodes A ON (L.acctCategory=A.actCode)

如果一些SQL guro可以看到这个并且说“哦,是的!这很容易重写。这会很简单,就像这样......”

1 个答案:

答案 0 :(得分:2)

她我们走了

1-更改此声明

UPDATE @ptsSummary 
  SET commitTotal=(SELECT mproTotal FROM @mproSummary WHERE detCostCode=costCode);

UPDATE s set s.commitTotal=p.mproTotal
FROM  @ptsSummary s 
INNER JOIN @mproSummary p on p.detCostCode=s.costCode

2-更改以下声明

UPDATE @ptsSummary 
  SET approvedAmt=(SELECT SUM(lawActAmount) 
  FROM @lawsonApproved 
  WHERE lawActCostCode=costCode 
  GROUP BY lawActCostCode);

UPDATE s set s.approvedAmt=p.Total
FROM @ptsSummary s
INNER JOIN (SELECT lawActCostCode,SUM(lawActAmount) as Total
            FROM @lawsonApproved 
            GROUP BY lawActCostCode) as p
WHERE p.lawActCostCode=s.costCode;

3-这个陈述重复两次,删除第二个

UPDATE @ptsSummary 
  SET commitTotal = (SELECT mproTotal FROM @mproSummary WHERE detCostCode=costCode);

4-更改以下声明

UPDATE @ptsSummary 
  SET finalCost = (SELECT SUM(userEstimate) 
  FROM @ptsUserSummary 
  WHERE UserCostCode=costCode 
  GROUP BY userCostCode);

UPDATE s set s.finalCost=p.Total
FROM @ptsSummary s
INNER JOIN (SELECT userCostCode, SUM(userEstimate) as Total
  FROM @ptsUserSummary 
  GROUP BY userCostCode) as p
WHERE p.UserCostCode=s.costCode 

并且您可以将此应用于包含分组

的所有更新

关于这个陈述

INSERT INTO @ptsSummary (costCodeDesc, costCode, stotal, lastInvoiceTran) 
  SELECT LEFT(A.description, 20), L.acctCategory, CONVERT(money, SUM(L.tranAmount)), MAX(L.runDate) 
  FROM dbo.lawAPdata L, dbo.mpro_actCodes A 
  WHERE activity = @afeNum and L.acctCategory = A.actCode 
  GROUP BY A.description, L.acctCategory;

似乎A只是一个用于获取描述字段的查找表,这可以用这种方式重写

INSERT INTO @ptsSummary (costCodeDesc, costCode, stotal, lastInvoiceTran) 
  SELECT LEFT(A.description, 20), L.acctCategory, CONVERT(money, SUM(L.tranAmount)), MAX(L.runDate) 
  FROM dbo.lawAPdata L
  INNER JOIN dbo.mpro_actCodes A ON L.acctCategory= A.actCode
  WHERE activity = @afeNum
  GROUP BY A.description, L.acctCategory;

在此编辑

可以修剪这些语句并在声明中使用约束和默认值

UPDATE @ptsSummary 
  SET estCost=(finalCost - stotal);

UPDATE @ptsSummary 
  SET estCost=0 WHERE estCost IS NULL;

UPDATE @ptsSummary 
  SET finalCost=0 WHERE finalCost IS NULL;

UPDATE @ptsSummary 
  SET approvedAmt=0 WHERE approvedAmt IS NULL;

希望这会有所帮助,但我需要时间来解密这段代码:P