2012-03-08 52 views
0

postgresql 9.1数据库写入从机器自动发送的数据。这工作正常。postgresql触发功能 - 重复或缺少数据

我有一个AFTER INSERT ... FOR EACH ROW触发器 - 这也适用。 触发器通过查看另一个表以及它触发的字段中是否有值。

我有两个问题 - a。有些机器发送的结果不止一个。我使用LIMIT 1来防止重复,这意味着我错过了发送多个结果的机器的数据。什么是替代这个? b。有些机器共享相同的测试代码,我无法找到一种合格的方法,以便在使用NEW值时使它在SELECT中成为特定机器。这里是代码

CREATE FUNCTION testcode_matches() 
    RETURNS TRIGGER as $$ 
DECLARE 
    var INTEGER; 
    name text; 
    short text; 
    id integer; 
BEGIN 
    SELECT count("TestID") from testcode WHERE "testcode"."Parameter" = NEW."Parameter" into var; 
    IF var > 0 THEN 
     SELECT "TestName", "ShortTestName", "TestID" 
     from testcode where "Parameter" = NEW."Parameter" Limit 1 into name, short, id; 

     INSERT INTO finaldata /* various fields */ 
     SELECT /* various fields */ name, short, id 
     from obx 
     WHERE "obx"."Parameter" = NEW."Parameter" 
     LIMIT 1; 
    END if; 
    RETURN NEW; 
END; 
$$ language plpgsql; 
+0

你从'从testcode其中 “参数”= NEW “参数”'查询期待不止一个ID?在这种情况下:限制1;导致一个随机的id被检索(并插入finaldata)。恕我直言,你可以把所有{testcode,obx}放入子查询中,并省略所有变量。该查询将成为纯SQL。 ASO:你能添加表格定义和触发器吗? – wildplasser 2012-03-08 14:30:53

+0

我收到了另一个答案,下面的答案帮了我,但我对学习子查询感兴趣。你能建议一个链接让我看看吗?触发器本身是 - 表“公共”的触发器结构。“obx” - ---------------------------- CREATE TRIGGER“finaldata_matches”AFTER INSERT ON“public”。“obx” FOR EACH ROW EXECUTE PROCEDURE“testcode_matches”(); – user1044111 2012-03-09 15:12:30

回答

0

纯SQL版本,没有所有可变的东西。 (不为人知的细节省略或猜到)(未经测试)

CREATE FUNCTION testcode_matches() 
    RETURNS TRIGGER as $meat$ 
BEGIN 

    INSERT INTO finaldata (name, short, id /* various fields */) 
    SELECT tc.name, tc.shorttestname, tc.id /* various fields */ 
    FROM testcode tc 
    JOIN obx ON obx.parameter = tc.parameter 
    WHERE tc.parameter = NEW.parameter 
    AND tc.id = NEW.id -- is this the PK for testcode ?? 
       ; 
    RETURN NEW; 
END; 
$meat$ language sql; 

更新:

set search_path='tmp'; 

DROP TABLE obx CASCADE; 
CREATE TABLE obx 
     (parameter INTEGER NOT NULL PRIMARY KEY 
     ); 

DROP TABLE testcode CASCADE; 
CREATE TABLE testcode 
     (ID INTEGER NOT NULL PRIMARY KEY 
     , parameter INTEGER NOT NULL REFERENCES obx(parameter) 
     , zname VARCHAR 
     , shorttestname VARCHAR 
     ); 

DROP TABLE finaldata CASCADE; 
CREATE TABLE finaldata 
     (ID INTEGER NOT NULL PRIMARY KEY 
     , zname VARCHAR 
     , shorttestname VARCHAR 
     ); 


DROP FUNCTION testcode_matches(); 
CREATE FUNCTION testcode_matches() 
    RETURNS TRIGGER 
    AS $meat$ 
BEGIN 

    INSERT INTO finaldata (id, zname, shorttestname /* various fields */) 
    SELECT tc.id, tc.zname, tc.shorttestname /* various fields */ 
    FROM testcode tc 
    JOIN obx ON obx.parameter = tc.parameter 
    WHERE tc.parameter = NEW.parameter 
    AND tc.id = NEW.id -- is this the PK for testcode ?? 
       ; 
    RETURN NEW; 
END; 
$meat$ language plpgsql; 

DROP TRIGGER testcode_ins; 
CREATE TRIGGER testcode_ins 
     AFTER INSERT ON testcode 
     FOR EACH ROW 
     EXECUTE PROCEDURE testcode_matches() 
     ; 
+0

这是一个很大的帮助,并已经整理出第一个问题。除非我连接到从机器获取数据数据的数据库,否则我需要检查第二个和它的难度。我不得不改变语言。 “[Err]错误:SQL函数不能返回类型触发器”,所以我改为“$ meat $ language plpgsql;”你已经把我放在了正确的方向 - 非常感谢 – user1044111 2012-03-09 15:06:26

+0

你对SQL函数无法返回TRIGGER的权利。 (下一次,下一次,**请添加一些有用的东西**像表定义等问题,并避免猜测。) – wildplasser 2012-03-09 15:34:30

+0

我几乎在那里。我已经了解了你的CASCADE函数以及写触发函数的另一种方法。我已经转发了这份工作的进一步细节,感谢您的帮助。 – user1044111 2012-03-15 16:21:09