函数中 table 的子句条目中缺少 PostgreSQL

PostgreSQL missing from clause entry for table in function

我有以下函数处理插入或更新时的触发器:

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 table 有某种关系。我试过去掉那个位,然后用 WHERE d.date_key = NEW.ticket_dateFROM dw.DimDate,这给出了同样的错误。

SO 上有很多这类问题,但我还没有找到一个解决这个特定场景的问题,因为我觉得它与它在这个触发函数内部有关。

函数是从这里调用的:

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

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

对于那些将来可能碰巧 运行 的人,我的解决方案是向函数添加一个条件,并与更新分开处理插入:

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;