2016-07-12 29 views
0

我無法訪問我的crosstab()查詢字符串中的NEW行的值。如何使用美元報價來傳遞NEW的價值?

CREATE OR REPLACE FUNCTION insert_fx() 
    RETURNS TRIGGER AS 
$BODY$ 
BEGIN 
    INSERT INTO outputtb (serial,date, judge) 
    VALUES (NEW.serial, NEW.date, NEW.tjudge) RETURNING serial INTO newserial; 

    UPDATE outputtb 
    SET (reading1, 
     reading2, 
     reading3) = 
     (SELECT ct."reading1", 
       ct."reading2", 
       ct."reading3" 
     FROM crosstab($$ 
       SELECT tb2. serial,tb2. readings,tb2. value 
       FROM DATA AS tb2 
       INNER JOIN outputtb AS tb1 USING (serial) 
       WHERE tb2.serial = $$||NEW.serno||$$ 
       ORDER BY 1 ASC $$, $$ 
       VALUES ('reading1'),('reading2'),('reading3')$$ 
       ) ct ("Serial" VARCHAR(50),"Reading1" FLOAT8, "Reading2" FLOAT8, "Reading3" FLOAT8)) 
    WHERE sn = NEW.serno; 
    RETURN NEW; 
END; 
$BODY$ 
LANGUAGE plpgsql VOLATILE; 

CREATE TRIGGER insert_tg 
BEFORE INSERT ON details 
FOR EACH ROW EXECUTE PROCEDURE insert_fx(); 

它返回此錯誤:

ERROR: syntax error at or near "CC1027HCA0GESKN00CC000FT0000" 
LINE 6: tb2. serial = 043611007853619CC1027HCA0GESKN00CC000FT... 

我認爲它不接受字符,它只接受整數。也許引用需要一些修改,我不熟悉pgsql引用。

我需要幫助來完成我的項目。我被困在這一部分。

+0

您實際上並不需要'crosstab()'。並使用插入**和**更新是矯枉過正。這可以通過一個'insert'語句完成(btw:'serial'是一個保留字,不應該作爲列名使用) –

+0

@a_horse_with_no_name謝謝mate。是的,它是一個矯枉過正的插入和更新。我跟隨你和ErwinBrandstetter的建議。 – tacticz03

回答

2

錯誤消息的直接原因是您將字符串NEW.serno連接起來而未引用它。要安全地修復使用format() or quote_literal() or quote_nullable()

... 
    UPDATE outputtb 
    SET   (reading1, reading2, reading3) 
    = (SELECT ct.reading1, ct.reading2, ct.reading3 
     FROM crosstab(
      'SELECT serial, t2.readings, t2.value 
      FROM data  t2 
      JOIN outputtb t1 USING (serial) 
      WHERE serial = ' || quote_nullable(NEW.serno) || ' 
      ORDER BY 1' 
      , $$VALUES ('reading1'),('reading2'),('reading3')$$ 
      ) ct (serial text, reading1 float8, reading2 float8, reading3 float8)) 
    WHERE sn = NEW.serno; 
... 

基礎:

順便我也固定不正確的大小寫混合的標識符:

但也有更多的問題:

  • newserial尚未聲明,也沒有使用。
  • outputtb查詢傳遞到crosstab()是無意義的噪音。
  • @a_horse commented,你不應該需要INSERTUPDATE,和crosstab()也似乎是矯枉過正。

這是一個很大的混亂。


走出去的肢體,我的猜測是你想要的:

CREATE OR REPLACE FUNCTION insert_fx() 
    RETURNS TRIGGER AS 
$func$ 
BEGIN 
    INSERT INTO outputtb (serial, date, judge, reading1, reading2, reading3) 
    SELECT NEW.serial, NEW.date, NEW.tjudge, ct.* 
    FROM (SELECT 1) dummy 
    LEFT JOIN crosstab (
    'SELECT serial, readings, value 
     FROM data 
     WHERE serial = ' || quote_nullable(NEW.serno) || ' 
     ORDER BY 1' 
    , $$VALUES ('reading1'),('reading2'),('reading3')$$ 
    ) ct (serial text, reading1 float8, reading2 float8, reading3 float8) ON true; 

    RETURN NEW; 
END 
$func$ LANGUAGE plpgsql; 

LEFT JOINdummy表防止丟失INSERTcrosstab()出現空。

這可以簡化爲:

CREATE OR REPLACE FUNCTION insert_fx() 
    RETURNS TRIGGER AS 
$func$ 
BEGIN 
    INSERT INTO outputtb (serial, date, judge, reading1, reading2, reading3) 
    SELECT NEW.serial, NEW.date, NEW.tjudge 
      min(value) FILTER (WHERE readings = 'reading1') 
      min(value) FILTER (WHERE readings = 'reading2') 
      min(value) FILTER (WHERE readings = 'reading3') 
    FROM data 
    WHERE serial = NEW.serno; 

    RETURN NEW; 
END 
$func$ LANGUAGE plpgsql; 

既然我們現在聚集,結果排了保證,而我們沒有抵禦失去它。

Aside: 「serial」is not a reserved word。但它是一個常見的僞數據類型的名稱,所以我仍然不會將它用作列名以避免混淆錯誤情況。

+0

嗨@ErwinBrandstetter。 我認爲crosstab只會在我的工作,但你的真棒。 感謝您的回答,您的簡化代碼有效。 非常感謝。你是最好的。 – tacticz03

+0

@tacticz03:'crosstab()'速度非常快,但是開銷不會支付來自max的單個結果行。 3個輸入行。 –

+0

嗨@erwinbrandstetter,我遇到了一些問題。我注意到,在我的兩個表(細節和數據表)插入異步執行。首先插入細節表,然後在數據表上插入行。我的問題是您提供的答案無法獲取數據表的行。你可以幫我嗎? – tacticz03

0

順便說一句,對於一些未來的參考文獻,可能有助於某人需要它。

這條線沒有爲我工作。

serial = ' || quote_nullable(NEW.serno) || ' 

它返回此錯誤。

Missing from clause entry for table "new".

相反,我用這個。

serial = $$||quote_literal(NEW.serno)||$$ 
+0

這沒有任何意義。美元報價和單引號也一樣。您在報價之外有錯誤。看起來像你在誤讀它:這段代碼片段*結束*一個引號,連接一個值並開始一個新的引用.. –