postrges ВСТАВИТЬ ПРАВИЛО вместо ОБНОВЛЕНИЯ - PullRequest
0 голосов
/ 27 февраля 2019

У меня простая таблица состоит из трех столбцов;бигинт, булев и текст.как-то так:

CREATE SEQUENCE foo_seq;
CREATE TABLE foo (
    i_foo     BIGINT DEFAULT nextval('foo_seq'),
    isok      BOOLEAN DEFAULT TRUE,
    who       CHARACTER VARYING(32) NOT NULL
);
ALTER TABLE foo ADD CONSTRAINT foo_pkey PRIMARY KEY (i_foo);
CREATE RULE foo_insert AS ON INSERT TO foo DO (
    DELETE FROM foo
        WHERE ((foo.i_foo < NEW.i_foo) AND (NEW.who = foo.who))
);

Это довольно близко к обновлению.Я ожидаю, что после любой вставки таблица всегда имеет одну строку и просто увеличивает i_foo.

Когда я вставляю новый элемент вручную, он работает нормально, он удаляет последний элемент и вставляет новый.Другими словами, просто i_foo увеличится на единицу.

Но одна и та же команда не работает одинаково в скрипте Python.Все объекты, включая новую, будут удалены.и таблица будет пустой после любой вставки.

INSERT INTO foo (isok, who) VALUES (True, 'someone');

class adoerclass(threading.Thread):

    def __init__(self, db):
        self.db = db
        threading.Thread.__init__(self)
        self.setDaemon(True)
        self.start()

    def run(self):
        while True:
            isGood = True
            try:
                lock.acquire()
                self.db.execute("INSERT INTO foo (isok, who) "
                "VALUES (%s, %s)", [isGood, 'someone'])
                self.db.commit()
                lock.release()
            except:
                lock.release()
                print("exception!")
                time.sleep(RETRY_TIME)
                lock.release()

Я в замешательстве.

1 Ответ

0 голосов
/ 27 февраля 2019

Наконец я написал триггер для этого.Работает нормально

CREATE SEQUENCE foo_seq;
CREATE TABLE foo (
    i_foo     BIGINT DEFAULT nextval('foo_seq'),
    isok      BOOLEAN DEFAULT TRUE,
    who       CHARACTER VARYING(32) NOT NULL
);
ALTER TABLE foo ADD CONSTRAINT foo_pkey PRIMARY KEY (i_foo);
CREATE FUNCTION foo_insert_before() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
    DELETE FROM foo WHERE (( NEW.i_foo > foo.i_foo ) AND (NEW.who = foo.who));
    RETURN NEW;
END;
$$;

CREATE TRIGGER foo_insert BEFORE INSERT ON foo FOR EACH ROW EXECUTE PROCEDURE foo_insert_before();
...