功能表中的子句条目缺少PostgreSQL

时间:2018-08-05 13:55:32

标签: postgresql database-trigger postgresql-9.6

我具有以下功能来处理插入或更新时的触发器:

CREATE OR REPLACE FUNCTION ticketChangeFunc() RETURNS TRIGGER AS $$
   BEGIN
        INSERT INTO dw.FactSalesHeader (DateKey, LocationKey, EmployeeKey, AppointmentTypeKey, TicketStatusTypeKey, TicketID,TotalAmount, IsNewPatient, IsActive)
        SELECT d.date_key, COALESCE(l.LocationKey, 0), COALESCE(e.EmployeeKey, 0), COALESCE(a.AppointmentTypeKey, 0), COALESCE(ts.TicketStatusTypeKey, 0), NEW.ticket_id,
        NEW.total_amount, NEW.is_new_patient, NEW.is_active
        FROM db1.tickets t
        JOIN dw.DimDate d on t.ticket_date = d.db_date
        LEFT JOIN dw.DimLocation l on NEW.location_id = l.LocationID
        LEFT JOIN dw.DimEmployee e on NEW.counselor_id = e.EmployeeID
        LEFT JOIN dw.DimAppointmentType a on NEW.office_visit_ind = a.AppointmentTypeFlagAttribute
        LEFT JOIN dw.DimTicketStatus ts on NEW.ticket2_status = ts.TicketStatusTypeID
        ON CONFLICT (TicketID)
        DO UPDATE
        SET DateKey = d.date_key, 
        LocationKey = COALESCE(l.LocationKey, 0), 
        EmployeeKey = COALESCE(e.EmployeeKey, 0), 
        AppointmentTypeKey = COALESCE(a.AppointmentTypeKey, 0), 
        TicketStatusTypeKey = COALESCE(ts.TicketStatusTypeKey, 0), 
        TotalAmount = NEW.total_amount, 
        IsNewPatient = NEW.is_new_patient, 
        IsActive = NEW.is_active;
      RETURN NEW;
   END;
$$ LANGUAGE plpgsql;

我收到错误消息:missing FROM-clause entry for table "d"

我认为也许与db1.tickets表有某种联系,但我在技术上并未在查询中使用该表。我试着去掉那一点,然后只用FROM dw.DimDateWHERE d.date_key = NEW.ticket_date,这会带来同样的错误。

关于SO的问题有很多,但是我还没有找到解决这种特殊情况的方法,因为我觉得它与触发函数有关。

该函数从此调用:

CREATE TRIGGER trg_tickets AFTER INSERT OR UPDATE ON db1.tickets
FOR EACH ROW EXECUTE PROCEDURE ticketChangeFunc();

我还想知道使用ON CONFLICT UPDATE子句是否在找到匹配项时更新每一行,而不管值是否不同?这会对性能产生影响吗?如果是,是否有方法检查每个字段的相等性,如果没有差异,则什么也不做?

1 个答案:

答案 0 :(得分:0)

对于那些将来可能碰到这种情况的人,我的解决方案是在函数中添加一个条件,并与更新分开处理插入:

CREATE OR REPLACE FUNCTION ticketChangeFunc() RETURNS TRIGGER AS $$
   BEGIN
        IF TG_OP = 'INSERT' THEN
            INSERT INTO dw.FactSalesHeader (DateKey, LocationKey, EmployeeKey, AppointmentTypeKey, TicketStatusTypeKey, TicketID, TotalAmount, IsNewPatient, IsActive)
            SELECT d.date_key, COALESCE(l.LocationKey, 0), COALESCE(e.EmployeeKey, 0), COALESCE(a.AppointmentTypeKey, 0), COALESCE(ts.TicketStatusTypeKey, 0), NEW.ticket_id, 
            NEW.total_amount, NEW.is_new_patient, NEW.is_active
            FROM db1.tickets t
            JOIN dw.DimDate d ON NEW.ticket_date = d.db_date
            LEFT JOIN dw.DimLocation l ON NEW.location_id = l.LocationID
            LEFT JOIN dw.DimEmployee e ON NEW.counselor_id = e.EmployeeID
            LEFT JOIN dw.DimAppointmentType a ON NEW.office_visit_ind = a.AppointmentTypeFlagAttribute
            LEFT JOIN dw.DimTicketStatus ts ON NEW.ticket2_status = ts.TicketStatusTypeID;        
        ELSE
            UPDATE dw.FactSalesHeader 
            SET DateKey = CAST(TO_CHAR(NEW.ticket_date, 'YYYYMMDD') as integer),
            LocationKey = COALESCE(l.LocationKey, 0), 
            EmployeeKey = COALESCE(e.EmployeeKey, 0),
            AppointmentTypeKey = COALESCE(a.AppointmentTypeKey, 0),
            TicketStatusTypeKey = COALESCE(ts.TicketStatusTypeKey, 0),
            TotalAmount = NEW.total_amount, 
            IsNewPatient = NEW.is_new_patient, 
            IsActive = NEW.is_active
            FROM dw.FactSalesHeader hdr
            LEFT JOIN dw.DimLocation l ON NEW.location_id = l.LocationID
            LEFT JOIN dw.DimEmployee e ON NEW.counselor_id = e.EmployeeID
            LEFT JOIN dw.DimAppointmentType a ON NEW.office_visit_ind = a.AppointmentTypeFlagAttribute
            LEFT JOIN dw.DimTicketStatus ts ON NEW.ticket2_status = ts.TicketStatusTypeID
            WHERE hdr.TicketID = NEW.ticket_id;
        END IF;        
    RETURN NULL;
   END;
$$ LANGUAGE plpgsql;