简体   繁体   中英

How to set a value in a variable column name?

How do I set a value in a variable column name? For some context, I am writing a function to be used as a trigger which sets a variable column to a constant value. To be used as follows:

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

The above would result in the following rows all having a col1 value of 6. So for example:

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

Would result in:

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

Or if using the following trigger:

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

And the same insert:

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

The table would look like:

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

How would I write the always_6 function?

Edit: To better explain the use case, the constant value would be current_setting('user_id') (or something alike). And the column name would be things like author_id and user_id . The thinking being that a user could never add for data which was not their own.

You can define your function to produce dynamically generated SQL .

The EXECUTE command takes a string as input and executes it as SQL, so it would look something like this:

EXECUTE FORMAT('UPDATE mytable SET %I='constantvalue' WHERE condition', colname);

Here I have used the FORMAT function to prepare a string with the value of colname substituted in where the column name would go. condition would be some valid WHERE clauses to select the record to update.

If the value of colname could come from an external source (ie. user supplied data) then you would have to be very careful to validate it beforehand, otherwise you might create an SQL injection vector.

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

I think I oversimplified the task based on the initial description, but would something like this work? You can't pass a parameter to a trigger function, but you mentioned the parameter was the result of another function current_setting('user_id') , so is it possible to roll the two concepts together like this?

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM