我定义了下面的plpgsql函数(Before trigger)来更新数据,如果提供了一个列,我将从静态数据中获取另一个。但我想知道在给定的" columna"中获取静态数据的最佳方法是什么,我需要得到" columnb"来自static_tbl(更像是字典/地图datastrcuture)。目前我正在查询静态表上的Trigger函数。
我知道我也可以使用case语句而不是查询。请告诉我这里最适合的是什么。 添加测试数据 Say ColumnA包含' a'它将作为'字母A'传播到ColumnB。 否则ColumnB包含'字母A'它将被传播到ColumnA作为' a' 将用于转换columnA值的静态数据存储到columnB值的最佳方法是什么?
CREATE FUNCTION update_tblname_column_b () RETURNS TRIGGER AS $$
BEGIN
IF NEW IS NULL THEN
RAISE EXCEPTION 'this function cannot be installed with a DELETE trigger';
END IF;
IF NEW.column_b IS NOT NULL AND NEW.column_a IS NULL THEN
NEW.column_a = (select column_a from static_tbl where column_b = NEW.column_b);
ELSIF NEW.column_a IS NOT NULL AND NEW.column_b IS NULL THEN
NEW.column_b = (select column_b from static_tbl where column_b = NEW.column_a);
END IF;
RETURN NEW;
END;
$$ LANGUAGE PLPGSQL;
CREATE TRIGGER populate_column
BEFORE INSERT OR UPDATE ON creatives FOR each ROW
EXECUTE PROCEDURE update_tblname_column_b();
答案 0 :(得分:2)
如果column_a
在功能上依赖于column_b
(反之亦然),则最佳方式 不 < / strong>存储功能相关的值。即时查找。为方便起见,可能会创建一个视图(或物化视图)。可能通过FOREIGN KEY
约束确保参照完整性。将查找合并到输入逻辑中。然后你不需要触发器。
如果您确实需要列和触发器,请修复偷偷摸摸的错误:您声明变量 column_a
和column_b
,这些是可见的在功能体到处都是。如果您使用相同的列名称column_a
和column_b
而没有表格资格,则会产生命名冲突。相关:
您的案例中的解决方案很简单:不要声明变量开头,您没有用它们。一般解决方案是,如果可能存在冲突,始终表限定列名。我实施了两个:
CREATE OR REPLACE FUNCTION update_tblname_column_b()
RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'DELETE' THEN
RAISE EXCEPTION 'This function cannot be used for DELETE trigger.';
END IF;
IF NEW.column_b IS NOT NULL AND NEW.column_a IS NULL THEN
SELECT INTO NEW.column_a s.column_a
FROM static_tbl s
WHERE s.column_b = NEW.column_b;
ELSIF NEW.column_a IS NOT NULL AND NEW.column_b IS NULL THEN
SELECT INTO NEW.column_b s.column_b
FROM static_tbl s
WHERE s.column_a = NEW.column_a;
END IF;
RETURN NEW;
END
$$ LANGUAGE plpgsql;
另外,不要检查NULL以识别触发器类型,这可能是不正确的。请改为检查特殊变量TG_OP
:
存储查找值的另一种方法是enum
data type。但我不会将enum
用于更多选项,只有在它们几乎没有改变时才会使用Maven>Download Sources
。实际上,我更喜欢具有FK约束的查找表。
答案 1 :(得分:0)
我认为使用像这样的表结构创建字典的方法可行,尽管else子句对我来说没有意义。你的意思是“WHERE column_a = NEW.column_a”?无论如何,这可能会稍微简单一些:
CREATE FUNCTION update_tblname_column_b () RETURNS TRIGGER AS $$
DECLARE
column_a tblname.column_a%TYPE;
column_b tblname.column_b%TYPE;
BEGIN
IF NEW IS NULL THEN
RAISE EXCEPTION 'this function cannot be installed with a DELETE trigger';
END IF;
NEW.column_a = COALESCE(NEW.column_a, (SELECT column_a FROM static_tbl WHERE column_b = NEW.column_b));
NEW.column_b = COALESCE(NEW.column_b, (SELECT column_b FROM static_tbl WHERE column_a = NEW.column_a));
RETURN NEW;
END;
$$ LANGUAGE PLPGSQL;
CREATE TRIGGER populate_column
BEFORE INSERT OR UPDATE ON creatives FOR each ROW
EXECUTE PROCEDURE update_tblname_column_b();
COALESCE函数返回其列表中的第一个非null参数。如果所有参数都为NULL,则返回NULL。
根据您打算如何使用它,最好在postgres 9.3及更高版本中使用一些新的JSON功能。这将为您提供另一种创建键/值对的方法。