如何在变量列名中设置值?

时间:2015-11-02 21:22:33

标签: sql postgresql plpgsql

如何在变量列名中设置值?对于某些上下文,我正在编写一个函数用作触发器,它将变量列设置为常量值。使用方法如下:

CREATE TRIGGER always_6_trigger
  BEFORE INSERT
  ON table
  FOR EACH ROW
  EXECUTE PROCEDURE always_6('col1');

以上将导致以下行的col1值均为6.例如:

INSERT INTO table (col1, col2) VALUES (6, 2), (null, 9), (null, 10), (7, 2);

会导致:

| col1 | col2 |
---------------
| 6    | 2    |
| 6    | 9    |
| 6    | 10   |
| 6    | 2    |

或者如果使用以下触发器:

CREATE TRIGGER always_6_trigger
  BEFORE INSERT
  ON table
  FOR EACH ROW
  EXECUTE PROCEDURE always_6('col2');

同样的插入:

INSERT INTO table (col1, col2) VALUES (6, 2), (null, 9), (null, 10), (7, 2);

表格如下:

| col1 | col2 |
---------------
| 6    | 6    |
| null | 6    |
| null | 6    |
| 7    | 6    |

我如何编写always_6函数?

编辑:为了更好地解释用例,常量值为current_setting('user_id')(或类似的东西)。列名称将是author_iduser_id之类的内容。想法是用户永远不会添加不属于他们自己的数据。

3 个答案:

答案 0 :(得分:3)

您可以定义要生成dynamically generated SQL的函数。

EXECUTE命令将一个字符串作为输入并将其作为SQL执行,因此它看起来像这样:

#primary_menu ul li ul {
    ...
    overflow: hidden;
}

这里我使用了FORMAT函数来准备一个字符串,其值EXECUTE FORMAT('UPDATE mytable SET %I='constantvalue' WHERE condition', colname); 替换为列名所在的位置。 colname将是一些有效的WHERE子句,用于选择要更新的记录。

如果condition的值可能来自外部源(即用户提供的数据),那么您必须非常小心地事先验证它,否则您可能会创建一个SQL注入向量。

答案 1 :(得分:0)

您可以使用动态查询来执行此操作,并将传递的参数值条件检查到存储过程的输入参数。

答案 2 :(得分:0)

我认为我根据初始描述过度简化了任务,但这样的工作会不会这样?你不能将参数传递给触发器函数,但你提到参数是另一个函数current_setting('user_id')的结果,所以是否可以将这两个概念一起滚动?

CREATE OR REPLACE FUNCTION always_6()
  RETURNS trigger AS
$BODY$
DECLARE
  current_user_id varchar;
BEGIN

  current_user_id := current_setting('user_id');

  if current_user_id = 'test1' then
    new.col_1 := 6;
  elsif current_user_id = 'test2' then
    new.col_2 := 6;
  end if;

  return NEW;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;