有这样一个数据库:
还有这样一个存储函数:
CREATE FUNCTION fetch_mentor(direction_type_list_in text, education_type_list_in text, name_in text, city_id_in integer) RETURNS json
LANGUAGE plpgsql
AS
$$
DECLARE
direction_type_list_inner INT[];
education_type_list_inner INT[];
BEGIN
direction_type_list_inner = STRING_TO_ARRAY(direction_type_list_in, ',');
education_type_list_inner = STRING_TO_ARRAY(education_type_list_in, ',');
RETURN (SELECT JSON_AGG(rows)
FROM (SELECT m.id AS "ID"
, FORMAT('%s %s', m.firstname, m.lastname) AS "fullName"
, m.photo_url AS "photoURL"
, m.video_url AS "videoURL"
, (SELECT JSON_AGG(mc.name)
FROM mentors.mentor_competence mc
WHERE mc.mentor_id = m.id) AS "competenceList"
, (SELECT JSON_AGG(el.name)
FROM mentors.mentor_employment me
INNER JOIN lists.employment_list el ON el.id = me.employment_id
WHERE me.mentor_id = m.id) AS "competenceList"
, m.certified AS "certified"
, cl.display_name AS "cityName"
, (SELECT JSON_AGG(dtl.display_name)
FROM mentors.mentor_direction_type mdt
INNER JOIN lists.direction_type_list dtl ON mdt.direction_type_id = dtl.id
WHERE mdt.mentor_id = m.id) "directionList"
, (SELECT JSON_AGG(etl.display_name)
FROM mentors.mentor_education_type met
INNER JOIN lists.education_type_list etl ON met.education_type_id = etl.id
WHERE met.mentor_id = m.id) "educationList"
FROM mentors.mentor m
LEFT JOIN lists.city_list cl ON m.city_id = cl.id
WHERE approved = TRUE
AND (direction_type_list_in ISNULL OR
m.id IN (SELECT m.id
FROM mentors.mentor_direction_type mdt
WHERE mdt.direction_type_id = ANY (direction_type_list_inner)))
AND (education_type_list_inner ISNULL OR
m.id IN (SELECT m.id
FROM mentors.mentor_education_type met
WHERE met.education_type_id = ANY (education_type_list_inner)))
AND (name_in ISNULL OR
(m.firstname LIKE FORMAT('%%%s%%', $3) OR m.lastname LIKE FORMAT('%%%s%%', $3)))
AND (city_id_in ISNULL OR m.city_id = city_id_in)
) rows);
END;
$$;
ALTER FUNCTION fetch_mentor(TEXT, TEXT, TEXT, INTEGER) OWNER TO postgres;
它返回这样一个json:
[
{
"ID": 3,
"fullName": "fsafd 413",
"photoURL": "sadf",
"videoURL": "dsa",
"competenceList": [
"a",
"s",
"f"
],
"employmentList": [
"a",
"b",
"c"
],
"certified": false,
"cityName": null,
"directionList": [
"x",
"z"
],
"educationList": [
"offline"
]
}
]
以下参数进入输入:
type FetchMentorsParams struct {
DirectionTypeList []int `json:"directionTypeList"`
EducationTypeList []int `json:"educationTypeList"`
MentorName *string `json:"mentorName"`
}
所有过滤器都是可选的。也就是说,如果没有过滤器,则输出所有记录。例如,如果 ,Direction Type List = [1,2]
则只应返回表中mentor_direction_type
的导师 ID 在 where 列中的那些记录direction_type_id = 1 or 2
。等等。但是有没有一种方法可以在没有存储函数的情况下形成一个查询来抵抗 SQL 注入?如果您执行类似的操作len(direction Type List) != 0
,然后在 for 循环中添加子查询,则该查询将容易受到 sql 注入的攻击。
总的来说,尝试在一个查询中完成所有事情有多好?我看到了一个选项:在主查询之前,查询 tomentor_direction_type
和 tomentor_education_type
然后做where mentor_id in (the result of querys)
.
进行诸如 - 之类的查询是正常的(SELECT JSON_AGG(el.name) FROM mentors.mentor_employment me INNER JOIN lists.employment_list el ON el.id = me.employment_id WHERE me.mentor_id = m.id) AS "competenceList"
,我不确定它是否已优化,但我没有看到任何其他选项。
我正在使用 Go、SQLX、PGX。