错误:记录"旧"尚未分配

Jho*_*uza 6 postgresql triggers

我在这个简单的触发器中遇到了困难.我的目的是在插入新寄存器之前验证是否存在具有相同字段内容的寄存器"tag_id".如果NEW tag_id与我的表"coordenadas"上的任何寄存器的tag_id相同,那么它会更新,如果没有,则会插入一个新的.当我尝试插入某事时,我收到错误:

ERROR:  record "old" is not assigned yet
DETAIL:  The tuple structure of a not-yet-assigned record is indeterminate.
CONTEXT:  PL/pgSQL function verifica_coo() line 7 at IF
Run Code Online (Sandbox Code Playgroud)

我有这张桌子:

    CREATE TABLE public.coordenadas
    (
      id bigint NOT NULL,
      pos_data timestamp without time zone,
      pos_latitude double precision,
      pos_longitude double precision,
      tag_id bigint NOT NULL,
      gado_id bigint NOT NULL,
      CONSTRAINT coordenadas_pkey PRIMARY KEY (id),
      CONSTRAINT coordenadas_gado_id_fkey FOREIGN KEY (gado_id)
      REFERENCES public.gado (gado_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
      CONSTRAINT fkj14dwmpa6g037ardymqc2q4lj FOREIGN KEY (tag_id)
      REFERENCES public.tag (tag_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
      CONSTRAINT fktawrw6tlliq4ace5p7io87c5p FOREIGN KEY (gado_id)
      REFERENCES public.gado (gado_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
Run Code Online (Sandbox Code Playgroud)

这个触发器:

CREATE TRIGGER verifica_coo
BEFORE INSERT OR UPDATE ON coordenadas
   FOR EACH ROW EXECUTE PROCEDURE verifica_coo();
Run Code Online (Sandbox Code Playgroud)

这个功能:

CREATE OR REPLACE FUNCTION public.verifica_coo()
  RETURNS trigger AS $verifica_coo$

    BEGIN
        --
        -- Verifica se é para inserir ou atualizar os dados na tabela.
        --
       IF (NEW.tag_id != OLD.tag_id ) THEN

            INSERT INTO coordenadas (pos_data,pos_latitude,pos_longitude,tag_id,gado_id) 
            VALUES (NEW.pos_data,NEW.pos_latitude,NEW.pos_longitude,NEW.tag_id,NEW.gado_id);
        ELSE 
            UPDATE coordenadas SET pos_data = NEW.pos_data, pos_latitude = NEW.pos_latitude, pos_longitude = NEW.pos_longitude WHERE tag_id = NEW.tag_id;
        END IF;
            RETURN NEW;

    END;
$verifica_coo$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION public.verifica_coo()
  OWNER TO postgres;
Run Code Online (Sandbox Code Playgroud)

我的插入:

INSERT INTO coordenadas (pos_data,pos_latitude,pos_longitude,tag_id,gado_id) VALUES ('21/08/2016', '-23.563844' ,'-46.322525', '2','2');
Run Code Online (Sandbox Code Playgroud)

e4c*_*4c5 17

这是因为:

数据类型RECORD; 变量在行级触发器中保存旧数据库行以进行UPDATE/DELETE操作.此变量在语句级触发器和INSERT操作中未分配.

因此,您首先需要检查是否正在进行插入或更新.该信息在TG_OP中可用

IF TG_OP = 'UPDATE' THEN
    -- some code involving OLD 
ELSE 
    -- other code
Run Code Online (Sandbox Code Playgroud)

  • 之所以得出这个答案,是因为我在我的服务器上遇到了与“OLD IS NULL”条件相同的错误,但在我的本地环境中却没有。事实证明,在版本 11 及更高版本上,“OLD”在“INSERT”广告上为空,条件工作正常,但我的服务器使用版本 10(其中“OLD”未分配),并且该行在问题中引发了相同的错误。如果有人遇到同样的问题,这个答案将会有所帮助。 (2认同)