TIL

2024.06.20 SQL๋ฌธ์œผ๋กœ ๊ธฐ์กด ๋ฐฐ์—ด์— ๋ฐ์ดํ„ฐ ๊ฐˆ์•„๋ผ์šฐ์ง€ ์•Š๊ณ  ์ถ”๊ฐ€ํ•˜๊ธฐ

inz1234 2024. 6. 22. 01:05

๐Ÿšจ  TroubleShotting

๋ฌธ์ œ ๋ฐœ์ƒ์˜ ๋ฐฐ๊ฒฝ - As Is

Supabase์— quiz_like๋ผ๋Š” ํ…Œ์ด๋ธ”์— users๋ผ๋Š” column์„ user_id์˜ ๋ฐฐ์—ด(text[])๋กœ ํƒ€์ž…์„ ์ •ํ•ด๋‘์—ˆ๋‹ค.

์ด users๋ผ๋Š” column์„ ํ•œ ๋ฒˆ์˜ ํ†ต์‹ ์œผ๋กœ updateํ•˜๊ณ  ์‹ถ์—ˆ์œผ๋‚˜,
๊ธฐ์กด supabase์˜ update ๋ฉ”์„œ๋“œ๋Š” ๊ธฐ์กด ๊ฑธ ๊ฐˆ์•„๋ฐ”๊พธ๋Š” ๋ฉ”์„œ๋“œ๋ผ์„œ 
๊ธฐ์กด์˜ ๊ฒƒ์„ select ํ•œ ๋’ค update ํ•˜๋Š” ์ด ๋‘ ๋ฒˆ์˜ ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์ด ๋ฐœ์ƒํ–ˆ๋‹ค.

๋‚ด๊ฐ€ ์›ํ•œ ๊ฒƒ์€ ํ•œ๋ฒˆ์˜ ํ†ต์‹ ์œผ๋กœ ๊ธฐ์กด ๊ฒƒ์— ์ถ”๊ฐ€๋˜๋„๋ก ํ•˜๊ณ  ์‹ถ์€ ์™€์ค‘์— ๊ตฌ๊ธ€์— ์ฐพ์•„๋ณด๋‹ˆ ์ด๋Ÿฐ ๊ธ€์ด ์žˆ์—ˆ๋‹ค.
https://github.com/orgs/supabase/discussions/1570

 

Is there any way to add values to an array column with UPDATE? · supabase · Discussion #1570

I want to add a value to an array column using update. [31] → [31,32]

github.com

 


How(๊ณผ์ •) ?

์‹œํ–‰์ฐฉ์˜ค 1

๊ทธ๋ž˜์„œ SQL์„ ์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•ด ๋ณด์•˜๋‹ค.

create function append_user_id_to_quiz_like (quiz_id uuid, user_id uuid) returns quiz_like as $$
begin
  update quiz_like
  set users = case
                when array_position(users, user_id) is null then array_append(coalesce(users, '{}'), user_id)
                else users
              end
  where quiz_id = append_user_id_to_quiz_like.quiz_id
  returning *;
end;
$$ language plpgsql;

๊ทธ๋Ÿฐ๋ฐ 
{code: "42702", details: "It could refer to either a PL/pgSQL variable or a table column.", hint: null,
message: "column reference \"quiz_id\" is ambiguous" }

๋ผ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.
ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ vs ํ…Œ์ด๋ธ”์˜ ์นผ๋Ÿผ ์ด๋ฆ„์œผ๋กœ ๋™์‹œ์— ์‚ฌ์šฉ๋˜์–ด ambiguous ํ•˜๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.


์‹œํ–‰์ฐฉ์˜ค 2

๊ทธ๋ž˜์„œ ์ด๋ ‡๊ฒŒ ๋ฐ”๊ฟจ๋‹ค.

create function append_user_id_to_quiz_like (quiz_id uuid, user_id uuid) returns quiz_like as $$
begin
  update quiz_like
  set users = case
                when array_position(users, user_id) is null then array_append(coalesce(users, '{}'), user_id)
                else users
              end
  where quiz_like.quiz_id = append_user_id_to_quiz_like.quiz_id
  returning *;
end;
$$ language plpgsql;

๋ชจํ˜ธํ•˜์ง€ ์•Š๊ฒŒ quiz_like ํ…Œ์ด๋ธ”์˜ quiz_id vs ํ•จ์ˆ˜์— ๋“ค์–ด์˜ฌ quiz_id
๋กœ ๋ฐ”๊ฟจ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ๊ทธ๋žฌ๋”๋‹ˆ ์ด๋ฒˆ์—๋Š” 

{code: "42601", details: null, hint: null, message: "query has no destination for result data"}

๋ผ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.
์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ, ๊ฒฐ๊ณผ๋ฅผ ์–ด๋””๋กœ ๋ฐ˜ํ™˜ํ• ์ง€ ๋ช…์‹œํ•˜์ง€ ์•Š์•˜๋‹ค๋Š” ๋œป์ด๋‹ค.


what(๊ฒฐ๊ณผ) - To Be

๊ทธ๋ž˜์„œ ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ•˜์ง€.. ํ•˜๋‹ค๊ฐ€ SQL๋ฌธ์„ ์ž˜ ๋ชจ๋ฅด๋Š” ๋‚œ chatGPT์— ๋ฌผ์–ด๋ดค๋‹ค.
chatGPT๊ฐ€ ๋‚ด ์ค€ ๊ฒฐ๊ณผ๋Š” ์ด๋Ÿฌํ–ˆ๋‹ค.

create function append_user_id_to_quiz_like (quiz_id uuid, user_id uuid) returns setof quiz_like as $$
begin
  return query
    update quiz_like
    set users = case
                  when array_position(users, user_id) is null then array_append(coalesce(users, '{}'), user_id)
                  else users
                end
    where quiz_like.quiz_id = append_user_id_to_quiz_like.quiz_id
    returning *;
end;
$$ language plpgsql;

์ด์ „ ํ•จ์ˆ˜์™€ ๋‹ค๋ฅธ ์ 
1. 'returns quiz_like' -> 'returns setof quiz_like'

๋‹จ์ผ ํ–‰์„ ๋ฐ˜ํ™˜ํ•˜๋ ค๊ณ  ํ•˜์ง€๋งŒ ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„์„ 
quiz_like์˜ ์—ฌ๋Ÿฌ ํ–‰์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค๊ณ  ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋ณ€๊ฒฝํ–ˆ๋‹ค.

2. update quiz_like -> return query + update quiz_like
ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•  ๋•Œ ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋ฌด์—‡์ผ์ง€๋ฅผ ๋ช…์‹œํ•ด์•ผ ํ•˜๋Š”๋ฐ
์ด์ „ SQL๋ฌธ์€ ์ •ํ™•ํžˆ ์–ด๋–ค ๊ฒฐ๊ณผ๋ฅผ return ํ•˜๋Š”์ง€ ํ•จ์ˆ˜๋ฅผ ์„ค๋ช…ํ•˜๋Š” begin ... end์— ์ž‘์„ฑํ•˜์ง€ ์•Š์•˜๋‹ค.
์ •ํ™•ํžˆ query๋ฅผ return ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ช…์‹œํ•ด์คฌ๋‹ค.

์ด๋ ‡๊ฒŒ ํ–ˆ๋”๋‹ˆ ์›ํ•˜๋Š” ๋Œ€๋กœ ๊ธฐ์กด ๋ฐฐ์—ด์— ์ถ”๊ฐ€๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.
๋งŒ๋“  ํ•จ์ˆ˜๋Š” ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•œ๋‹ค.

  const submitQuizLike = async (quiz_id: string, user_id: string) => {
    const supabase = clientSupabase();
    await supabase.rpc('append_user_id_to_quiz_like', { quiz_id, user_id });
  };

๐Ÿ’ก ์ƒˆ๋กญ๊ฒŒ ์•Œ๊ฒŒ๋œ ์ 

๋‹จ์ˆœํžˆ GPT์— ๋ฌผ์–ด๋ณด๊ณ  ๋๋‚˜๋ฉด ๋‚œ ๊ธฐ์ˆ ์— ์ ธ๋ฒ„๋ฆฐ ์ธ๊ฐ„.. ใ…‹ใ…‹
ํ•œ์ค„ํ•œ์ค„ ๋ถ„์„ํ•ด์„œ ๋ฐฐ์›Œ์•ผ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์— ์ •๋ฆฌํ–ˆ๋‹ค.

create function append_user_id_to_quiz_like (quiz_id uuid, user_id uuid):
append_user_id_to_quiz_like ๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š”๋ฐ, ๊ทธ ์ธ์ž๋กœ๋Š” quiz_id์™€ user_id ๊ฐ€ ๋“ค์–ด๊ฐ€๊ณ  ๊ฐ๊ฐ์˜ type์ด uuid๋‹ค.

returns setof quiz_like:
์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋กœ quiz_like์˜ ์—ฌ๋Ÿฌ ํ–‰์„ ๋ฐ˜ํ™˜

as $$ ... $$ language plpgsql:
ํ•จ์ˆ˜ ๋ณธ๋ฌธ์€ $$ … $$ ์‚ฌ์ด์— ๋‘˜๋Ÿฌ์Œ“์—ฌ ์žˆ์œผ๋ฉฐ, ํ•จ์ˆ˜๋Š” PL/SQL ์–ธ์–ด๋กœ ์ž‘์„ฑ๋œ๋‹ค.

‘begin ... end;:
ํ•จ์ˆ˜ ๋ณธ๋ฌธ์˜ ์‹œ์ž‘๊ณผ ๋์„ ๋œปํ•œ๋‹ค.

return query:
ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ๋ฐ˜ํ™˜

‘update quiz_like:
quiz_like ํ…Œ์ด๋ธ”์„ ์—…๋ฐ์ดํŠธ

-  set users = case ... end:
‘users’ ์ปฌ๋Ÿผ์„ ์กฐ๊ฑด์— ๋”ฐ๋ผ ์—…๋ฐ์ดํŠธ ํ•  ๊ฒƒ์ด๋‹ค.

-  array_position(users, user_id) is null:
users
์ปฌ๋Ÿผ์—์„œ user_id๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ
๋งŒ์•ฝ ์—†์œผ๋ฉด (null ์ด๋ฉด)

-  array_append(coalesce(users, '{}'), user_id)
+) coalesce(users, ‘{}’) : ์ธ์ž๋“ค ์ค‘์— ์™ผ์ชฝ๋ถ€ํ„ฐ ๊ฐ€๋ฉด์„œ null์ด ์•„๋‹Œ ๊ฒƒ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
์ด๋ฒˆ์—๋Š” users ๋ฐฐ์—ด์ด null์ธ์ง€ ํ™•์ธ
null
์ด ์•„๋‹ˆ๋ฉด users๋ฅผ ๋ฐ˜ํ™˜, null ์ด๋ฉด ‘{}’์„ ๋ฐ˜ํ™˜ํ•ด์„œ ๊ฒฐ๊ณผ์ ์œผ๋กœ๋Š” ๋นˆ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ ํ›„,
Users๊ฐ€ null์ด ์•„๋‹ˆ๋ฉด ๊ธฐ์กด users์— user_id๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  null์ด๋ฉด ๋นˆ ๋ฐฐ์—ด์— user_id๋ฅผ ์ถ”๊ฐ€

-  else users:
๊ทผ๋ฐ ๋งŒ์•ฝ users ์ปฌ๋Ÿผ์— user_id๊ฐ€ ์žˆ์œผ๋ฉด ๊ธฐ์กด users ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜

-  where quiz_like.quiz_id = append_user_id_to_quiz_like.quiz_id:
quiz_like ํ…Œ์ด๋ธ”์˜ quiz_id๊ฐ€ ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋“ค์–ด์˜ค๋Š” quiz_id๋ž‘ ์ผ์น˜ํ•˜๋Š” ํ–‰์„ ์—…๋ฐ์ดํŠธ ํ•  ๋Œ€์ƒ์œผ๋กœ ํ•˜๊ฒ ๋‹ค.

-  returning *;:
์—…๋ฐ์ดํŠธ๋œ ํ–‰์„ ๋ฐ˜ํ™˜


๋น„๋ก.. GPT์— ์˜์กดํ•ด์„œ ์•Œ๊ฒŒ๋œ ์ง€์‹์ด์ง€๋งŒ..
๊ทธ๋ž˜๋„ ๋ชจ๋ฅด๋Š” ๊ฒƒ ๋ณด๋‹ค๋Š” ์ด๋ ‡๊ฒŒ๋ผ๋„ ์•„๋Š” ๊ฒŒ ์–ด๋”˜๊ฐ€!:))