首页 > 解决方案 > 无论如何要测试SQL中的函数吗?

问题描述

我有以下问题。我做了一个检查日期、仓库是否已满等的功能。

这是代码,我添加了注释,因此更清晰易懂:

SET SERVEROUTPUT ON
CREATE OR REPLACE
PROCEDURE Anlieferung (P_Artikelbezeichnung VARCHAR, P_Datum date, P_Stueck INT) AS
_inputQuantity int;
_currentQuantity int;
_inputItem int;
_articleNummber int;
_quanitityToInput int:=P_Stueck;
_maximumLnr int;

BEGIN 
  FOR v_rec IN (SELECT * FROM lager) LOOP -- implicit cursor
  _currentQuantity:=0;
  
  SELECT artikel.anr -- Adding our article nummber in our variable called "_articleNummber"
  INTO _articleNummber
  FROM artikel
  WHERE artikel.bezeichnung = P_Artikelbezeichnung;
  
  FOR buchung IN(SELECT * FROM lagerbuchung lag --Checking the lnr and the date
  WHERE lag.lnr = v_rec.lnr AND P_Datum >= lag.datum)
  LOOP
  --Menge in _currentQuantity einfügen
  _currentQuantity:=_currentQuantity + buchung.stueck; --Adding our current quantity in our variable called "_currentQuantity"
  END LOOP;
  
  
  IF(v_rec.stueckkap > _currentQuantity OR _quanitityToInput >0) --Checking our capacity
  THEN
  _inputItem:=v_rec.stueckkap - _currentQuantity;
  
  IF(_inputItem <= _quanitityToInput)
  THEN
  _inputQuantity:= _inputItem;
  _quanitityToInput:=_quanitityToInput - _inputItem;
  ELSE
  _inputQuantity:= _quanitityToInput;
  _quanitityToInput:=0;
  END IF;
  
  SELECT COALESCE(MAX(lfndnr),0) -- If we have null in our table, we will also get null in return 
  INTO _maximumLnr
  FROM lagerbuchung;
  
  _maximumLnr:=_maximumLnr +1;
  
  --Inserting our new values in our table
  INSERT INTO lagerbuchung (lfndnr, datum, stueck, anr, lnr) VALUES (_maximumLnr, P_Datum, _inputQuantity, _articleNummber, v_rec.lnr);
  
  END IF;
  END LOOP;
END Anlieferung;
/

SELECT l.LNR, SUM(lb.STUECK) FROM LAGER l JOIN LAGERBUCHUNG lb on l.lnr = lb.lnr group by l.lnr order by l.lnr;
EXEC Anlieferung('Apfel', '27.11.2015', 160);
SELECT l.LNR, SUM(lb.STUECK) FROM LAGER l JOIN LAGERBUCHUNG lb on l.lnr = lb.lnr group by l.lnr order by l.lnr;

所以基本上如果我只运行这个函数,我不会得到任何错误。但是当我使用测试日期运行它时,我收到以下错误:

Fehler beim Start in Zeile : 166 in Befehl -
EXEC Anlieferung('Apfel', '27.11.2015', 160)
Fehlerbericht -
ORA-06550: line 1, column 7:
PLS-00905: object IF4EBIHORACM.ANLIEFERUNG is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:

我试图调试它并输入不同的测试日期,但仍然是同样的错误。

标签: sqloracle

解决方案


编译该过程后,请运行:

SHOW ERRORS

或(假设您将其作为拥有用户而不是作为 DBA 用户进行编译;如果您不是拥有用户,则使用ALL_ERRORS):

SELECT * FROM USER_ERRORS;

要么会为您提供程序中的错误列表,然后您可以对其进行调试并修复错误,以便程序正常工作。


更新

评论

2/1 PLS-00103: Encountered the symbol "_" when expecting one of the following: begin function pragma procedure subtype type <an identifier> <a double-quoted delimited-identifier> current cursor delete exists prior external language

可能是因为我的变量?它们以下划线开头

数据库对象名称和限定符文档中:

数据库对象命名规则

每个数据库对象都有一个名称。在 SQL 语句中,您使用带引号的标识符或不带引号的标识符来表示对象的名称。

  • 带引号的标识符以双引号 (") 开头和结尾。如果您使用带引号的标识符命名架构对象,则在引用该对象时必须使用双引号。
  • 不带引号的标识符不被任何标点符号包围。

...

  1. 不带引号的标识符必须以数据库字符集中的字母字符开头。带引号的标识符可以以任何字符开头。

您有许多以下划线开头的变量标识符。这告诉您解决方案是将变量名称更改为以字母字符开头(或使用带引号的标识符并用双引号将标识符括起来;但不要使用带引号的标识符,只需在下划线):

CREATE OR REPLACE PROCEDURE Anlieferung (
  P_Artikelbezeichnung VARCHAR,
  P_Datum              date,
  P_Stueck             INT
)
AS
  v_inputQuantity    int;
  v_currentQuantity  int;
  v_inputItem        int;
  v_articleNummber   int;
  v_quanitityToInput int:=P_Stueck;
  v_maximumLnr       int;
BEGIN
...

另外,不要使用:

SELECT COALESCE(MAX(lfndnr),0) -- If we have null in our table, we will also get null in return 
INTO _maximumLnr
FROM lagerbuchung;
  
_maximumLnr:=_maximumLnr +1;

因为如果同时调用该过程两次,它可能会生成重复值。

相反,为该列创建一个序列并从该序列中获取下一个值。

CREATE SEQUENCE lagerbuchung__lfndnr__seq START WITH 213 INCREMENT BY 1;

(从当前最大值多 1 开始。)

然后在您的程序中使用:

INSERT INTO lagerbuchung (
  lfndnr,
  datum,
  stueck,
  anr,
  ln
) VALUES (
  lagerbuchung__lfndnr__seq.NEXTVAL,
  P_Datum,
  v_inputQuantity,
  v_articleNummber,
  v_rec.lnr
);

推荐阅读