簡體   English   中英

PL / pgSQL函數沒有返回預期值

[英]PL/pgSQL function not returning expected value

我在plpgsql中編寫了一個觸發器函數,它在一個表上進行了INSTER AFTER INSERT操作。

觸發器函數調用另外兩個函數,第一個函數不返回正確的值。 我的智慧結束了,搜索沒有找到任何答案。

凸輪有人對這個問題有所了解嗎?

觸發功能如下:

CREATE TRIGGER timetotaketrigger
  AFTER INSERT
  ON "Prescription Schema"."TimeToTake"
  FOR EACH ROW
  EXECUTE PROCEDURE failtimetotakeinsert();

上述觸發器按預期工作。

正在調用failtimetotakeinsert,源是:

CREATE OR REPLACE FUNCTION failtimetotakeinsert()
RETURNS trigger AS '
DECLARE

    -- declare variables to hold the information from
    -- the row being inserted
    -- and save the data from the new row
    drug_name character(32);
    drug_strength character(8);
    drug_strength_unit character(16);
    drug_dosage integer;

    row_counts integer = 0;
    frequency integer = 0;
    difference integer = 0;

 BEGIN
RAISE NOTICE ''Frequency at the start is %'',frequency;
    -- save the data from the new row
    drug_name = NEW."DrugName";
    drug_strength = NEW."DrugStrength";
    drug_strength_unit = NEW."DrugStrengthUnit";
    drug_dosage = NEW."DrugDosage";

    -- get the frequency 
    SELECT INTO frequency GetPrescriptionFrequency(drug_name,
                                    drug_strength,
                                    drug_strength_unit,
                                    drug_dosage);

RAISE NOTICE ''frequency is %'',frequency;        
    -- count the rows from the current table
    SELECT INTO row_counts CountTimeToTake(drug_name,drug_strength,
                                           drug_strength_unit,drug_dosage);
RAISE NOTICE ''row counts are %'',row_counts;

    -- work out the difference
    difference = row_counts - frequency;
RAISE NOTICE ''Difference is %'',difference;
    -- now check the two figures
    IF difference > 0 THEN
        RAISE EXCEPTION ''More rows than frequency requires'';
    END IF;

    RETURN NULL;
 END;
'  LANGUAGE 'plpgsql'

我遇到的問題是在這一個中調用的第一個函數,因為它從PgAdmin sql environemtn調用時還沒有返回值,結果是我所期望的。

CREATE OR REPLACE FUNCTION GetPrescriptionFrequency
    (character, character, character, integer)
RETURNS integer AS '
#variable_conflict error
DECLARE
   -- Declare drug_name,
   --         drug_strength,
   --         drug_strength_unit and
   --         drug_dosage as an alias for the argument variables
   -- normally referenced with the $1,$2,$3 and $4 identifiers

   drug_name ALIAS FOR $1;
   drug_strength ALIAS FOR $2;
   drug_strength_unit ALIAS FOR $3;
   drug_dosage ALIAS FOR $4;

   -- declare a variable to hold the count

   freq integer := 0;

BEGIN

  SELECT INTO freq COUNT(*) 
      FROM "Prescription Schema"."PrescriptionItem" 
      WHERE "PrescriptionItem"."DrugName" = drug_name AND
            "PrescriptionItem"."DrugStrength" = drug_strength AND
            "PrescriptionItem"."DrugStrengthUnit" = drug_strength_unit AND
            "PrescriptionItem"."DrugDosage" = drug_dosage;
--       IF NOT FOUND THEN
--          RAISE EXCEPTION ''prescription item not found %'', drug_strength;
--       END IF;
   IF freq IS NULL THEN 
     RETURN 0;
   ELSE
     RETURN freq;
   END IF;
END;
' LANGUAGE 'plpgsql'

另一個函數表現正常,但我也包括了源代碼:

CREATE OR REPLACE FUNCTION CountTimeToTake(character,character,character,integer)
    RETURNS integer AS '
DECLARE
   -- Declare drug_name,
   --         drug_strength,
   --         drug_strength_unit and
   --         drug_dosage as an alias for the argument variables
   -- normally referenced with the $1,$2,$3 and $4 identifiers

   drug_name ALIAS FOR $1;
   drug_strength ALIAS FOR $2;
   drug_strength_unit ALIAS FOR $3;
   drug_dosage ALIAS FOR $4;
   -- declare a variable to hold the count
   row_count integer := 0;
BEGIN

-- count the number of TimeToTake rows for the given
-- parameter values

   SELECT INTO row_count COUNT(*) FROM "Prescription Schema"."TimeToTake"
          WHERE "TimeToTake"."DrugName" = drug_name AND
                "TimeToTake"."DrugStrength" = drug_strength AND
                "TimeToTake"."DrugStrengthUnit" = drug_strength_unit AND
                "TimeToTake"."DrugDosage" = drug_dosage;

   return row_count;
END;
' LANGUAGE 'plpgsql'

我已經嘗試了我可以在互聯網上找到的所有內容以及之前的問題但無濟於事。 任何幫助將非常感謝。

觸發

簡化和重寫:

CREATE OR REPLACE FUNCTION failtimetotakeinsert()
  RETURNS trigger AS
$func$
BEGIN

IF GetPrescriptionFrequency(NEW."DrugName", NEW."DrugStrength"
                           ,NEW."DrugStrengthUnit", NEW."DrugDosage") 
          > CountTimeToTake(NEW."DrugName",NEW."DrugStrength"
                           ,NEW."DrugStrengthUnit",NEW."DrugDosage") THEN
   RAISE EXCEPTION 'More rows than frequency requires';
END IF;

RETURN NULL;

END
$func$   LANGUAGE plpgsql;

主要觀點

  • 美元引用函數體以避免引用問題是一種很好的做法。

  • plpgsqlLANGUAGE plpgsql的關鍵字,不必引用。

  • 永遠不要使用愚蠢的古式character(n)除非你肯定有。 它使用空白填充字符串操作並截斷字符串,很少有用。 它只是出於歷史原因和標准合規性。 只需使用text (實際上與varchar相同),或者如果您確實需要在類型級別強制執行最大長度,請使用varchar(n) 我只用99%的text 請務必閱讀有關字符類型的手冊 `

  • plpgsql中的賦值運算符是:= SQL-style =適用於ATM,但沒有記錄,可能會在沒有警告的情況下消失。

  • 刪除無意義的RAISE NOTICE 'Frequency at start is %', frequency; - 總是0

  • 從根本上簡化。

  • 如果函數CountTimeToTake()應該用camel case定義,你需要用雙引號括起來。 但從我看來,事實並非如此。

功能

修復,簡化和重寫:

CREATE OR REPLACE FUNCTION GetPrescriptionFrequency
    (_drug_name text, _drug_strength text, _drug_strength_unit text
                                         , _drug_dosage integer)
  RETURNS integer LANGUAGE sql AS 
$func$
SELECT count(*)::int
FROM  "Prescription Schema"."PrescriptionItem" p
WHERE  p."DrugName"         = _drug_name
AND    p."DrugStrength"     = _drug_strength
AND    p."DrugStrengthUnit" = _drug_strength_unit
AND    p."DrugDosage"       = _drug_dosage;
$func$

主要觀點

  • 在PostgreSQL 9.1中使用參數名稱而不是ALIAS

  • 這里使用數據類型character是完全錯誤的,可能是您的關鍵問題。 charactercharacter(1)的同義詞,並將字符串截斷為第一個字符。

  • 在plpgsql函數內的查詢中,變量和參數是可見的,並且優先於列名。 這可能會導致意外結果。 在這種情況下,您必須對列名進行表限定,以使它們明確無誤。
    最好使用不會與列名稱沖突的參數和變量名稱。 我習慣使用_前綴,我從不使用列名,但只要你避免命名沖突,任何東西都可以。

  • 我建議不要使用帶有PostgreSQL標識符的駝峰案例。 單獨使用小寫並為自己節省大量雙引號和混淆。

  • count()永遠不會返回NULL ,您不需要提供這種情況。 在這里引用手冊

應該注意,除了count之外,這些函數在沒有選擇行時返回空值。

  • count()返回bigint ,因此在此場景中bigintinteger

  • 對於這個簡單的例子, LANGUAGE sql函數可能做得更好。

  • 相應地修復你的其他函數CountTimeToTake()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM