我具有以下功能来处理插入或更新时的触发器:
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.DimDate
做WHERE 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
子句是否在找到匹配项时更新每一行,而不管值是否不同?这会对性能产生影响吗?如果是,是否有方法检查每个字段的相等性,如果没有差异,则什么也不做?
答案 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;