在AFTER INSERT或UPDATE触发器中从PostgreSQL中获取违反外键约束

时间:2017-10-15 19:41:26

标签: postgresql triggers

我有两个表,documentsevents。插入或更新文档时,我想更新事件表。

-- Create the document store table
CREATE TABLE documents (
  id TEXT PRIMARY KEY,
  parent TEXT REFERENCES documents,
  data JSONB,
  created TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
  updated TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()
);

-- Create the normalized event table
CREATE TABLE events (
  document TEXT REFERENCES documents,
  type TEXT NOT NULL,
  eventDate date NOT NULL,
  title TEXT,
  subtitle TEXT,
  description TEXT,
  PRIMARY KEY(document, type, eventDate)
);

我有一个辅助功能和触发器:

-- Keep the update documentDB column valid
CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated = now();
    RETURN NEW;
END;
$$ language 'plpgsql';

CREATE TRIGGER trigger_patents_updated BEFORE UPDATE ON documents
  FOR EACH ROW EXECUTE PROCEDURE update_modified_column();

-- Put a document
CREATE OR REPLACE FUNCTION PutDocument(in_data JSON)
RETURNS TEXT AS $$
DECLARE
    r_id TEXT;
BEGIN
    INSERT INTO documents (id, parent, data) VALUES (in_data::JSONB->>'id',
      in_data::JSONB->>'parent', in_data::JSONB)
    ON CONFLICT (id) DO UPDATE SET data=in_data::JSONB RETURNING id
      INTO r_id;
    RETURN r_id;
END;
$$ language 'plpgsql';

然后我有了应该更新事件表的触发器

-- Create birthday events
CREATE OR REPLACE FUNCTION document_to_event_birthday()
RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO events (document, type, eventDate, title, subtitle, description)
    VALUES(NEW.data->'id', 'BIRTH', to_date(NEW.data->'birth'->>'date', 'YYYY-MM-DD'), 'title', 'subtitle', 'description')
  ON CONFLICT ON CONSTRAINT events_pkey DO NOTHING;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER document_to_event_birthday
  AFTER INSERT OR UPDATE ON documents
  FOR EACH ROW EXECUTE PROCEDURE document_to_event_birthday();

当我尝试插入文档时,它会在document_to_event_birthday函数中出错。

PutDocument('{"id": "ham", "test": "value", "birth": { "date": "2011-06-02" }}');

给我

ERROR:  insert or update on table "events" violates foreign key constraint "events_document_fkey"
DETAIL:  Key (document)=("ham") is not present in table "documents".
CONTEXT:  SQL statement "INSERT INTO events (document, type, eventDate, title, subtitle, description)
    VALUES(NEW.data->'id', 'BIRTH', to_date(NEW.data->'birth'->>'date', 'YYYY-MM-DD'), 'title', 'subtitle', 'description')
  ON CONFLICT ON CONSTRAINT events_pkey DO NOTHING"
PL/pgSQL function document_to_event_birthday() line 3 at SQL statement
SQL statement "INSERT INTO documents (id, parent, data) VALUES (in_data::JSONB->>'id',
      in_data::JSONB->>'parent', in_data::JSONB)
    ON CONFLICT (id) DO UPDATE SET data=in_data::JSONB RETURNING id"
PL/pgSQL function putdocument(json) line 5 at SQL statement

如果我在错误后查看表格,它们都是空的。因此,在文档表上插入/更新后,我的触发器不会发生。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

你在函数document_to_event_birthday()中输了一个拼写错误:在

INSERT INTO events (document, ...)
   VALUES (NEW.data->'id', ...)

你应该使用

NEW.data->>'id'

现在编码函数的方式,函数尝试插入jsonb值,该值隐式转换为text。但是后面的值是"ham"而不是ham带有额外的双引号,这违反了外键约束。