如何使用美元报价传递NEW的价值?

时间:2016-07-12 04:51:11

标签: sql postgresql plpgsql quotes postgresql-9.5

我无法访问NEW查询字符串中crosstab()行的值。

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引用。

我需要帮助来完成我的项目。我坚持这一部分。

2 个答案:

答案 0 :(得分: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一样,您不应该需要INSERT UPDATEcrosstab()似乎也有点矫枉过正。< / LI>

这是一个很大的混乱。

走出困境,我受过教育的猜测是你想要这个:

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表可防止在INSERT出现空白时失去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
          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;

由于我们现在汇总,结果排是有保证的,我们不必防止丢失它。

除了: &#34;串行&#34;是not a reserved word。但它是常见伪数据类型的名称,因此我仍然不会将其用作列名,以避免混淆错误情况。

答案 1 :(得分:0)

BTW,对于某些未来的参考文献可能对某些人有用。

这条线对我不起作用。

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

它会返回此错误。

  

缺少表格“new”的子句条目。

相反,我使用它。

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