【问题标题】:Changing all zeros (if any) across all columns (in a table) to... say 1将所有列(表中)的所有零(如果有)更改为...比如说 1
【发布时间】:2012-04-06 12:53:22
【问题描述】:

我有一个包含 18 列(所有整数)和 1040 行的表。如果任何值为零,我想将其更改为 1。我正在使用 Postgresql。做这个的最好方式是什么。我想不出一个简单的更新语句......而且我是数据库新手。

任何关于我应该看什么来学习如何实现这样的东西的指针......(我会认为某种脚本,如果 postgresql 存在这样的东西......我不知道)

谢谢

【问题讨论】:

  • 更新表 FOO SET column_1=1 where column_1=0 并执行 18 次?
  • 由于表很小,您也可以使用脚本语言(Perl、Python 等)获取数据,在读取数据时逐行执行变量替换,截断表,然后插入更新的数据(您可能希望将最后两个步骤放入事务中)。

标签: sql postgresql


【解决方案1】:

这个怎么样

UPDATE table SET columnA = 1 WHERE columnA = 0

但是您需要对每一列进行查询,或者

UPDATE table SET columnA = 
CASE WHEN columnA = 0 THEN 1
ELSE columnA
END,

columnB = 
CASE WHEN columnB = 0 THEN 1
ELSE columnB
END, ...

【讨论】:

  • 我正在寻找同时编辑所有 18 个(用于学习目的)。这将适用于 18 个单独的查询
  • 其实上面的方法只需要一个查询就可以了,只是一个大而乏味的查询。
  • @大卫。正确,我在他更新第二个案例之前发表了评论
【解决方案2】:

在匹配表的所有列中用新值替换给定值的工具

我改编了一个用于类似目的的 plpgsql 函数:

CREATE OR REPLACE FUNCTION f_update_all_cols(_sch text, _tbl text, _old int, _new int)
  RETURNS text AS
$func$
DECLARE
   _type   CONSTANT regtype[] := '{bigint,smallint,integer}';
   _toid   regclass;            -- table oid
   _msg    text := '';          -- report
   _ct     integer;             -- count of rows for report
BEGIN
  -- Loop over tables
FOR _toid IN
   SELECT c.oid
   FROM   pg_class c
   JOIN   pg_namespace nc ON nc.oid = c.relnamespace
   WHERE  c.relkind  = 'r'
   AND    nc.nspname = _sch
   AND    c.relname  LIKE (_tbl || '%')
   ORDER  BY c.relname
LOOP
   EXECUTE (
-- RAISE NOTICE '%', (
      SELECT format('UPDATE %s SET (%s) = (%s) WHERE $1 IN (%2$s)'
                , _toid
                , string_agg(quote_ident(attname), ', ' ORDER  BY a.attnum)
                , string_agg(format('CASE WHEN %1$I = $1 THEN $2 ELSE %1$I END', attname), ', ')
                )
      FROM   pg_attribute a
      WHERE  a.attrelid = _toid
      AND    a.attnum  >= 1      -- exclude neg. attnum - tableoid etc.
      AND    NOT a.attisdropped  -- exclude deleted columns
      AND    a.atttypid = ANY(_type)
      GROUP  BY _toid)
   USING  _old, _new;
-- );

   GET DIAGNOSTICS _ct = ROW_COUNT;
   _msg := _msg || _ct || ' row(s) in: ' || _toid || E'\n';
END LOOP;

RETURN _msg;

END
$func$  LANGUAGE plpgsql;

COMMENT ON FUNCTION f_update_all_cols(text, text, int, int) IS $$
Convert 0 to 1 in all integer type columns.
$1 .. _sch: schema
$2 .. _tbl: table-pattern: left anchored search pattern; default "%"
$3 .. _old: replace this ...
$4 .. _new: ... with this)   -- $$;

呼叫:

SELECT f_update_all_cols('myschema', '', 0, 1); -- all tables in schema
SELECT f_update_all_cols('myschema', 'foo', 0, 1); -- tables starting with foo

查看所有integer 类型的列并将给定的_old 值更改为给定的 _new 值。如果您想包含其他数据类型,请相应地编辑变量_type

注释 EXECUTEUSING 行并取消注释 RAISE NOTICE 和右括号,以便在执行之前检查生成的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-10
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    相关资源
    最近更新 更多