Как получить доступ к столбцу внутри хранимой процедуры, который будет использоваться в триггере? | PostgreSQL

Я пытаюсь получить доступ к столбцу таблицы tb_client_cdc внутри функции (= хранимой процедуры), которая будет вызываться триггером, чтобы сохранить последнее состояние операции (UPDATE, INSERT, DELETE), примененной к таблице. tb_client.

Если мы делаем INSERT в tb_client и строка существует в tb_client_cdc, нам не нужно вставлять другую строку, вместо этого мы должны ОБНОВИТЬ эту строку.

Итак, чтобы определить, существует ли строка, я использовал:

IF ((TG_OP = 'INSERT') AND (sale_cdc.tb_client_cdc.saleclient_code <> NEW.client_code)) THEN 

Я пытался поставить «sale_cdc.tb_client_cdc.saleclient_code» вместо sale_cdc.tb_client_cdc.saleclient_code , но это не решило мою проблему.

  • ТАБЛИЦЫ
CREATE TABLE sale.tb_client
(
client_code          CHAR(5) NOT NULL ,
client_name          CHARACTER VARYING(40) NOT NULL ,
address              CHARACTER VARYING(140) ,
city                 CHARACTER VARYING(25)  ,
country              CHARACTER VARYING(60) NOT NULL ,
contact_email        CHARACTER VARYING(100) ,
phone                CHARACTER VARYING(15) ,
parent_client_code   CHAR(5) ,
created_by_user      CHARACTER VARYING(10) NOT NULL DEFAULT 'OS_SYSTEM',
created_date         DATE ,
updated_date         DATE ,
CONSTRAINT pk_client PRIMARY KEY (client_code) ,
CONSTRAINT fk_client_parent FOREIGN KEY (parent_client_code) 
                   REFERENCES sale.tb_client (client_code)
);

CREATE TABLE sale_cdc.tb_client_cdc
(
client_code          CHAR(5) NOT NULL ,
client_name          CHARACTER VARYING(40) NOT NULL ,
address              CHARACTER VARYING(120) ,
city                 CHARACTER VARYING(25)  ,
country              CHARACTER VARYING(50) NOT NULL ,
contact_email        CHARACTER VARYING(100) ,
phone                CHARACTER VARYING(15) ,
parent_client_code   CHAR(5) ,
created_by_user      CHARACTER VARYING(10) NOT NULL DEFAULT 'OS_SYSTEM',
created_date         DATE ,
updated_date         DATE ,
operation            CHAR(1) NOT NULL ,
user_id              CHARACTER VARYING(10) NOT NULL ,
operation_timestamp  TIMESTAMP(6) WITHOUT TIME ZONE NOT NULL , --timestamp [ (p) ] [ without time zone ]
CONSTRAINT pk_client PRIMARY KEY (client_code) ,
CONSTRAINT fk_client_parent FOREIGN KEY (parent_client_code) 
               REFERENCES sale_cdc.tb_client_cdc (client_code)
);

  • ФУНКЦИЯ
CREATE OR REPLACE FUNCTION update_tb_client_cdc() RETURNS TRIGGER AS 
$$
    BEGIN
        IF ((TG_OP = 'INSERT') AND (sale_cdc.tb_client_cdc.saleclient_code <> NEW.client_code)) THEN
            INSERT INTO sale_cdc.tb_client_cdc VALUES(NEW.*, 'I', user, now());
            RETURN NEW;
        END IF;

    ELSIF ((TG_OP = 'INSERT') AND (sale_cdc.tb_client_cdc.client_code = NEW.client_code)) THEN
            UPDATE sale_cdc.tb_client_cdc
                SET client_name = NEW.client_name,
                address = NEW.address,
                city = NEW.city,
                country = NEW.country,
                contact_email = NEW.contact_email,
                phone = NEW.phone,
                parent_client_code = NEW.parent_client_code,
                created_by_user = NEW.created_by_user,
                created_date = NEW.created_date,
                updated_date = NEW.updated_date,
                operation = 'I',
                user_id = user,
                operation_timestamp = now()
            WHERE client_code = NEW.client_code;
        IF NOT FOUND THEN RETURN NULL; 
        END IF; 
            RETURN NEW; 
    END;
$$ LANGUAGE plpgsql;
  • ВЫЗЫВАТЬ
CREATE TRIGGER tr_client
AFTER INSERT OR UPDATE OR DELETE ON sale.tb_client
    FOR EACH ROW EXECUTE PROCEDURE update_tb_client_cdc();

Ошибка:

ERROR:  missing an entry for the table «tb_client_cdc» in the clause FROM
LINE 1: SELECT (((TG_OP = 'INSERT') AND (sale_cdc.tb_client_cdc.clie...
                                         ^

Или:

ERROR:  there is no column «sale_cdc.tb_client_cdc.client_code»
LINE 1: SELECT (((TG_OP = 'INSERT') AND ("sale_cdc.tb_client_cdc.cli...
                                         ^

Как может строка не существовать в таблице tb_client_cdc, если вы хотите вставить ее при вставке в tb_client? Кроме того, ваш первичный ключ на tb_client_cdc не имеет смысла, у вас может быть только одна строка для каждого клиента, и я предполагаю, что вы хотите, чтобы эта таблица была своего рода журналом операций.

MarcinJ 12.04.2019 00:06
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
1
70
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Объявите переменную, содержащую client_code, и проверьте, существует ли она в tb_client_cdc в начале, например так:

CREATE OR REPLACE FUNCTION update_tb_client_cdc() RETURNS TRIGGER AS
$$
DECLARE
    p_client_code tb_client.client_code%TYPE;
BEGIN
    SELECT client_code FROM tb_client_cdc WHERE client_code = NEW.client_code
    INTO p_client_code;


    IF TG_OP = 'INSERT' AND p_client_code IS NULL THEN
        INSERT INTO tb_client_cdc VALUES(NEW.*, 'I', user, now());
        RETURN NEW;
    ELSEIF TG_OP = 'INSERT' AND p_client_code IS NOT NULL THEN
       UPDATE tb_client_cdc
                SET client_name = NEW.client_name,
                address = NEW.address,
                city = NEW.city,
                country = NEW.country,
                contact_email = NEW.contact_email,
                phone = NEW.phone,
                parent_client_code = NEW.parent_client_code,
                created_by_user = NEW.created_by_user,
                created_date = NEW.created_date,
                updated_date = NEW.updated_date,
                operation = 'I',
                user_id = user,
                operation_timestamp = now()
            WHERE client_code = NEW.client_code;

    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Спасибо @MarcinJ !!!! <3 единственное, что мне нужно было сделать, это добавить имя схемы перед таблицей: ``` DECLARE p_client_code sale_cdc.tb_client_cdc.client_code%TYPE; НАЧНИТЕ ВЫБРАТЬ tb_client_cdc.client_code ИЗ sale_cdc.tb_client_cdc, ГДЕ tb_client_cdc.client_code = NEW.client_code В p_client_code; ```

Jon Ander Díez 12.04.2019 01:09

правильно, я не создавал схемы в своей базе данных, просто использовал public прямо, извините. Рад, что смог помочь!

MarcinJ 12.04.2019 01:10

Может кто-нибудь объяснить мне, можно ли то же самое сделать с оператором ": = " в postgreSQL? И если ответ да, можете ли вы показать мне, как?

Jon Ander Díez 12.04.2019 01:12

Другие вопросы по теме