大约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可以看到这个并且说“哦,是的!这很容易重写。这会很简单,就像这样......”
答案 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