Supabase RPC函数返回全部用户数据而非指定用户问题排查
问题排查与解决
问题根源
你的SQL RPC函数参数名user_id与user_roles表的列名重复,导致WHERE子句中的user_id被PostgreSQL优先解析为user_roles.user_id列,而非函数传入的参数。由于JOIN条件已经是ur.user_id = p.id,WHERE条件等价于p.id = ur.user_id,相当于没有过滤,因此返回所有关联用户的数据。
解决方法
有两种可行的修复方式:
方式1:使用位置参数引用函数参数
直接用$1(代表第一个函数参数)代替参数名,避免列名冲突:
CREATE OR REPLACE FUNCTION public.get_profile_with_role(user_id uuid) RETURNS TABLE( id uuid, username text, name text, website text, avatar_url text, welcome_email_sent boolean, has_accepted_privacy_policy boolean, country text, phone_number text, about_me text, gender text, city text, rut text, role_id integer ) LANGUAGE sql AS $func$ SELECT p.id, p.username, p.name, p.website, p.avatar_url, p.welcome_email_sent, p.has_accepted_privacy_policy, p.country, p.phone_number, p.about_me, p.city, p.rut, ur.role_id FROM profiles p JOIN user_roles ur ON ur.user_id = p.id WHERE p.id = $1 -- 用$1明确引用函数传入的第一个参数 $func$;
这种方式不需要修改前端代码,保持原调用逻辑即可。
方式2:修改函数参数名,避免与列名冲突
将函数参数名改为不与表列重复的名称,比如target_user_id,同时更新WHERE子句和前端调用的参数名:
修改后的RPC函数:
CREATE OR REPLACE FUNCTION public.get_profile_with_role(target_user_id uuid) RETURNS TABLE( id uuid, username text, name text, website text, avatar_url text, welcome_email_sent boolean, has_accepted_privacy_policy boolean, country text, phone_number text, about_me text, gender text, city text, rut text, role_id integer ) LANGUAGE sql AS $func$ SELECT p.id, p.username, p.name, p.website, p.avatar_url, p.welcome_email_sent, p.has_accepted_privacy_policy, p.country, p.phone_number, p.about_me, p.city, p.rut, ur.role_id FROM profiles p JOIN user_roles ur ON ur.user_id = p.id WHERE p.id = target_user_id $func$;
修改后的前端代码:
const getProfile = async() => { const user = supabase.auth.user(); let {data, error, status} = await supabase.rpc('get_profile_with_role', {target_user_id: user.id}); if(error) throw error; if(data && data.length > 0) { let cleanUserName = data[0].username ? data[0].username.replace(/['"]+/g, '') : ''; setUserInfo(data[0]); } }
内容的提问来源于stack exchange,提问作者Richi
相关产品推荐
相关产品推荐

