问题描述
我正在尝试将字段动态添加到表中。我创建了一个函数,并传递了我想创建的字段名称和数据类型:
> df_help_reprex <- df_help %>%
+ mutate(dim_1 = c(1,2,1,0))
> df_help
# A tibble: 10 x 8
symp_ams symp_nvd symp_pain symp_fever vitals_gcs vitals_rr_10_24 vitals_temp_38 vitals_hr_100
<fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct>
1 NO YES NO NO NO NO NO YES
2 NO NO NO NO NO NO NO NO
3 YES NO NO NO YES NO UNK YES
4 NO NO NO NO NO NO UNK YES
5 NO NO NO YES YES NO YES NO
6 NO NO NO NO NO NO NO NO
7 NO NO NO YES NO NO NO NO
8 NO YES NO NO NO NO NO NO
9 YES NO NO NO YES NO NO YES
10 NO NO NO YES NO YES YES YES
> dim_1
[1] "symp_ams" "symp_nvd" "symp_pain" "vitals_gcs"
> df_help_reprex
# A tibble: 10 x 9
symp_ams symp_nvd symp_pain symp_fever vitals_gcs vitals_rr_10_24 vitals_temp_38 vitals_hr_100 dim_1
<fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <dbl>
1 NO YES NO NO NO NO NO YES 1
2 NO NO NO NO NO NO NO NO 0
3 YES NO NO NO YES NO UNK YES 2
4 NO NO NO NO NO NO UNK YES 0
5 NO NO NO YES YES NO YES NO 0
6 NO NO NO NO NO NO NO NO 0
7 NO NO NO YES NO NO NO NO 0
8 NO YES NO NO NO NO NO NO 1
9 YES NO NO NO YES NO NO YES 2
10 NO NO NO YES NO YES YES YES 0
这总是创建一个名为“ _pname”的字段,而不管我传递的值如何。如何获得按值而不是按文字求值的函数?我尝试了CREATE OR REPLACE function "trustedforms2"."parametertest"("_pname" varchar)
AS $BODY$BEGIN
-- Routine body goes here...
ALTER TABLE byoung.formdata ADD COLUMN _pname varchar(255);
END$BODY$
LANGUAGE plpgsql
,"_pname"
,'_pname'
,但收到错误消息或名为“ _pname”的字段。
解决方法
使用动态SQL时,请确保引用/转义正确转换为代码的用户输入,以避免攻击向量进行SQL注入!基础:
- SQL injection in Postgres functions vs prepared queries
- Define table and column names as arguments in a plpgsql function?
- Table name as a PostgreSQL function parameter
此外,Postgres标识符仅在双引号时保留大写字母:
例程的基本安全版本:
CREATE OR REPLACE PROCEDURE trustedforms2.parametertest(_pname text)
LANGUAGE plpgsql AS
$proc$
BEGIN
EXECUTE format('ALTER TABLE byoung.formdata ADD COLUMN %I varchar(255)',_pname);
END
$proc$;
以这种方式保留大写。要强制使用小写名称,请改用lower(_pname)
。 (您仍然想正确地对标识符加上双引号!)
您可能想要或不希望首先检查该表是否存在以及该列是否不存在。如果这些假设不成立,则简单形式会引发异常。
您可以像在答案中选择的那样使用PROCEDURE
进行此操作,但请记住使用CALL
执行该操作:
CALL trustedforms2.parametertest('my_columns_name');
我可能会坚持使用(更常见的)功能。
在Postgres中,类型varchar(255)
通常是一种误解:
好,解决了
CREATE OR REPLACE PROCEDURE "trustedforms2"."parametertest"("_pname" varchar)
AS $BODY$BEGIN
EXECUTE 'ALTER TABLE byoung.formdata ADD COLUMN ' || _pname || ' varchar(255)' ;
END$BODY$
LANGUAGE plpgsql