【问题标题】:update multidimensional arrays in postgresql在 postgresql 中更新多维数组
【发布时间】:2020-04-06 01:28:13
【问题描述】:
  id        Weather

   1    {{KS,'S'},{MO,'S'},{CA,'S'}}

我正在尝试将所有 KS、MO、CA 的“S”更新为“W”。

我正在执行下面的查询,它给我一个错误

 UPDATE table
 SET Weather[][2] ='W' where id=1;

预期输出

  id        Weather

   1    {{KS,'W'},{MO,'W'},{CA,'W'}}

【问题讨论】:

  • 规范化您的数据模型将是一个更好的解决方案。或者至少切换到jsonb 列,这样可以更优雅地存储这种结构化信息
  • 除了规范化数据还有其他选择吗?

标签: arrays postgresql multidimensional-array


【解决方案1】:

我认为可以使用普通的UPDATE。 让我们尝试选择我们需要替换的项目:

-- first, second and third item from array and convert to string
SELECT array_to_string(weather[1:1], ',') AS KS,
       array_to_string(weather[2:2], ',') AS MO,
       array_to_string(weather[3:3], ',') AS CA
FROM test_tbl;

结果:"KS,'S'","MO,'S'","CA,'S'"

现在我们可以选择记录记录进行更新,只需将字符串与数组项(作为字符串)进行比较:

SELECT * FROM test_tbl
-- KS,'S'
WHERE array_to_string(weather[1:1], ',') = concat('KS,', quote_literal('S'))
-- MO,'S'
-- array_to_string(weather[2:2], ',') = concat('MO,', quote_literal('S'))
-- CA,'S'
-- array_to_string(weather[3:3], ',') = concat('CA,', quote_literal('S'))

好的。现在我们只需要将数组按部分与新项目合并。

UPDATE test_tbl
--  generate first item + other items
SET weather = string_to_array(concat('KS,', quote_literal('W')), ',')::varchar[] || weather[2:]
WHERE array_to_string(weather[1:1], ',') = concat('KS,', quote_literal('S'));

UPDATE test_tbl
-- first item + generate second + other items
SET weather = weather[1:1] || string_to_array(concat('MO,', quote_literal('W')), ',')::varchar[] || weather[3:]
WHERE array_to_string(weather[2:2], ',') = concat('MO,', quote_literal('S'));

UPDATE test_tbl
-- first + second items, generate third + other items
SET weather = weather[0:2] || string_to_array(concat('CA,', quote_literal('W')), ',')::varchar[] || weather[4:]
WHERE array_to_string(weather[3:3], ',') = concat('CA,', quote_literal('S'));

结果:{{KS,'W'},{MO,'W'},{CA,'W'}}。希望这会有所帮助

【讨论】:

    【解决方案2】:

    我相信标准化您的数据将是最好的解决方案,但如果它不适合您,请尝试此功能:

    CREATE OR REPLACE FUNCTION change_array(p TEXT[][]) RETURNS TEXT[][] AS $$
    DECLARE row record; res TEXT[][]; 
    DECLARE i INT :=0;
    BEGIN
       LOOP 
         EXIT WHEN i = array_length(p,1);
         i:=i+1;
           IF p[i:i][1:2] <@ ARRAY[['KS','S']] THEN
             res := res || ARRAY[['KS','W']];
           ELSEIF p[i:i][1:2] <@ ARRAY[['MO','S']] THEN
         res := res || ARRAY[['MO','W']];
           ELSEIF p[i:i][1:2] <@ ARRAY[['CA','S']] THEN
         res := res || ARRAY[['CA','W']];
           ELSE res := res || p[i:i];
           END IF;
       END LOOP;  
      RETURN res;
    END;
    $$ LANGUAGE plpgsql ;
    

    用你的例子测试..

    SELECT change_array(ARRAY[['KS','S'],['MO','S'],['CA','S'],['XX','S']]);
             change_array          
    -------------------------------
     {{KS,W},{MO,W},{CA,W},{XX,S}}
    
    (1 Zeile)
    

    【讨论】:

      猜你喜欢
      • 2016-03-28
      • 2015-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多