如何将函数中的参数传递给创建TRIGGER?

时间:2017-05-30 06:02:27

标签: sql postgresql

我正在尝试制作一个TRIGGER响应表格中的更新(约会),然后调用一个程序( proc1())。该过程需要获取参数,以便在不同的表( medical_folder )上插入基于这些参数的新行。程序不能有参数,但经过一些搜索后我发现你可以使用类似下面的方法来强迫你的方式:

Passing arguments to a trigger function

以上述为基础,我制作了以下UDF:

CREATE OR REPLACE FUNCTION AppointmentUpdate(docAMKA bigint, patAMKA bigint, dateNtime timestamp, conclusion varchar(500),cure2 varchar(500), drug_id integer)
RETURNS void AS $$
DECLARE
    patAMKAv2 text;
    drug_idv3 text;
BEGIN
    patAMKAv2 := cast(AppointmentUpdate.patAMKA as text);
    drug_idv3 := cast(AppointmentUpdate.drug_id as text);
    DROP TRIGGER IF EXISTS tr1 on appointments;
    CREATE TRIGGER tr1 BEFORE UPDATE ON appointments
    EXECUTE PROCEDURE proc1(patAMKAv2,cure2,drug_idv3);
    UPDATE appointments
    SET diagnosis = conclusion
    WHERE patientamka = patAMKA
        AND doctoramka = docAMKA
        AND t = dateNtime;
END;
$$ LANGUAGE plpgsql;

我的程序如下:

CREATE OR REPLACE FUNCTION proc1() 
RETURNS trigger AS $$
declare
  newid integer;
BEGIN
  newid =((select max(medical_folder.id) from medical_folder)+1);
  INSERT INTO medical_folder AS Medf(id,patient,cure,drug_id)
  VALUES(newid,cast(TG_ARGV[0] as bigint),TG_ARGV[1],cast(TG_ARGV[2] as integer));
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

如果我按原样运行它,我在 proc1()这里cast(TG_ARGV[0] as bigint)收到错误,似乎在UDF中发送参数而不是发送参数的值他们自己(例如我这样做EXECUTE PROCEDURE proc1(324,cure2,234);这个EXECUTE PROCEDURE proc1(patAMKAv2,cure2,drug_idv3);。有没有什么办法可以强迫它取代价值呢?

P.S .:我现在可以在不使用TRIGGER的情况下轻松完成,只需制作一个可以完成所有操作的UDF,但不幸的是我必须使用TRIGGER。

PS2:我尝试使用 function_name.variable_name 而不是 var_name 也尝试使用 $ 1,$ 2,$ 3,...,$ n

1 个答案:

答案 0 :(得分:0)

来自CREATE TRIGGER docs

  

<强>参数
  执行触发器时要提供给函数的可选逗号分隔的参数列表。参数是文字字符串常量。 这里也可以写出简单的名称和数字常量,但它们都将被转换为字符串。

http://rextester.com/OCA59277

您可以通过动态SQL(see EXECUTE)实现您的目标。但我相信你过于复杂。您想要做的只是获取参与UPDATE语句的行或ID。 PostgreSQL的DML语句(INSERTUPDATE&amp; DELETE)只有RETURNING条款。此外,您实际上可以使用writeable CTEs在单个语句中编写更多DML(子)语句。这样的事情就足够了:

WITH upd AS (
  UPDATE    appointments
  SET       diagnosis   = conclusion
  WHERE     patientamka = patAMKA
  AND       doctoramka  = docAMKA
  AND       t           = dateNtime
  RETURNING *
)
INSERT INTO medical_folder(patient, cure, drug_id)
SELECT patAMKAv2, cure2, drug_idv3
FROM   upd;

注意:在写这篇文章时,我意识到你实际上并没有使用UPDATE中的任何字段,但使用FROM upd将确保尽可能多的行插入medical_folderappointments更新了- (void)viewDidLoad { [super viewDidLoad]; self.preferredContentSize = CGSizeMake((self.view.frame.size.width / 100) * 65, (self.view.frame.size.height / 100) * 65); } 。这是您最初的基于触发器的逻辑。