如何在 Postgresql 中将整数列结果转换为字符串?

How can I transform integer column results into strings in Postgresql?

提问人:Jenna J 提问时间:9/30/2023 最后编辑:Ergest BashaJenna J 更新时间:10/1/2023 访问量:111

问:

我需要编写一个函数来转换表中名为“store_id”的列的结果。我想将整数 1 转换为“存储 1”,将整数 2 转换为“存储 2”,但无论输入什么,我都会收到错误。

我试过了:

CREATE OR REPLACE FUNCTION transform_store_id()
RETURNS VOID AS $$
BEGIN
  UPDATE detailed_sales
  SET store_id = CASE store_id
                    WHEN 1 THEN 'store 1'
                    WHEN 2 THEN 'store 2'
                    ELSE store_id::text
                  END;
END;
$$
 LANGUAGE plpgsql;

但我明白了

“错误:列”store_id“是整数类型,但表达式是类型 文本”

因此,我尝试合并 CAST 和 TO_CHAR,但错误各不相同。

SQL PostgreSQL 函数

评论

2赞 Jonas Metzler 9/30/2023
似乎您的列是整数类型?当然,不允许将整数列更新为 varchar 或文本值。您需要先更改列类型。这个奇怪的想法的目的是什么?你真正想做什么?
0赞 Jenna J 10/6/2023
在这项任务中,我们必须编写一个函数来转换列。我正在尝试的任何东西都不起作用。

答:

0赞 nbk 9/30/2023 #1

您需要首先更改列类型

CREATE TABLE detailed_sales(store_id  int)
CREATE TABLE
INSERT INTO detailed_sales VALUEs (1),(2), (3)
INSERT 0 3
ALTER TABLE detailed_sales 
ALTER COLUMN  store_id TYPE   TEXT;
ALTER TABLE
  UPDATE detailed_sales
  SET store_id = CASE store_id
                    WHEN '1' THEN 'store 1'
                    WHEN '2' THEN 'store 2'
                    ELSE store_id::text
                  END;
UPDATE 3

小提琴

-1赞 Maimoona Abid 9/30/2023 #2

您可以添加具有文本数据类型的新列,并使用所需的值对其进行更新,以更改表中的“store_id”列。请尝试以下代码。在此代码中,将保留原始的“store_id”列,同时创建和更新新的“store_name”列。

CREATE OR REPLACE FUNCTION transform_store_id()
RETURNS VOID AS $$
BEGIN
  -- Add a new column called "store_name" with text data type
  ALTER TABLE detailed_sales ADD COLUMN store_name TEXT;
  
  -- Update the "store_name" column based on the "store_id" values
  UPDATE detailed_sales
  SET store_name = CASE store_id
                    WHEN 1 THEN 'Store 1'
                    WHEN 2 THEN 'Store 2'
                    ELSE store_id::text
                  END;
END;
$$
LANGUAGE plpgsql;

希望它能:)

评论

0赞 Jenna J 10/6/2023
这被拒绝了,因为我需要转换一列,而不仅仅是添加一列。我试图找出将其更改为更改列的代码,但这出现了错误。
0赞 Vérace 9/30/2023 #3

其他答案已经证明根本不需要函数。

另一种方法可能是使用 GENERATEDmanual) - aka ,也令人困惑的是 - 列(下面的所有代码都可以在这里找到)。COMPUTEDDERIVEDVIRTUAL

CREATE TABLE detailed_sales(store_id  int)

填充:

INSERT INTO detailed_sales VALUES (1),(2), (3)

添加我们的专栏:GENERATED

ALTER TABLE detailed_sales 
ADD COLUMN store TEXT 
GENERATED ALWAYS AS 
(
  CASE store_id
    WHEN 1 THEN 'store 1'
    WHEN 2 THEN 'store 2'
    ELSE store_id::TEXT
  END
) STORED;

而且,事不宜迟,我们运行:

SELECT 
   store_id,
   store,
   PG_TYPEOF(store_id),
   PG_TYPEOF(store)
FROM 
   detailed_sales;

结果:

store_id   store  pg_typeof  pg_typeof
       1 store 1    integer       text
       2 store 2    integer       text
       3       3    integer       text

而我们的 , , &c. “神奇地”出现了!store 1store 2

当然,PG_TYPEOF()(手动)功能不是必需的 - 仅用于演示目的!

请注意,关键字是必需的 - 大多数服务器都有两种列存储模式 - (在磁盘上)和(动态计算 - 即在请求时) - 因此关于调用列本身的评论令人困惑。STOREDGENERATEDSTOREDVIRTUALVIRTUAL

0赞 Adrian Klaver 10/1/2023 #4

注意:以下假设您要更改字段类型。请参阅下面的更多注意事项。

CREATE TABLE store_test(id integer, store_id integer);

\d store_test 
              Table "public.store_test"
  Column  |  Type   | Collation | Nullable | Default 
----------+---------+-----------+----------+---------
 id       | integer |           |          | 
 store_id | integer |           |  

INSERT INTO store_test VALUES (1, 2), (2, 1), (3, 1), (4, 2);


ALTER TABLE store_test
    ALTER COLUMN store_id TYPE varchar
    USING
        CASE WHEN store_id::varchar = '1' THEN
            'store1'
        WHEN store_id::varchar = '2' THEN
            'store2'
        ELSE
           store_id::varchar
        END;

\d store_test 
                   Table "public.store_test"
  Column  |       Type        | Collation | Nullable | Default 
----------+-------------------+-----------+----------+---------
 id       | integer           |           |          | 
 store_id | character varying |     

SELECT * FROM store_test ;

 id | store_id 
----+----------
  1 | store2
  2 | store1
  3 | store1
  4 | store2

如果这是一个大表,则可能需要一些时间。您还需要确保表上没有依赖于旧列类型的触发器。对于此列可能属于的任何 FOREIGN KEY 关系,也是如此。

-1赞 Nnaemeka Daniel John 10/1/2023 #5

您应该将转换后的值分配给新的 TEXT 列,而不是更新现有的“store_id”列。

CREATE OR REPLACE FUNCTION transform_store_id()
RETURNS VOID AS $$
BEGIN
  ALTER TABLE detailed_sales ADD COLUMN transformed_store_id TEXT;

  UPDATE detailed_sales
  SET transformed_store_id = CASE store_id
                               WHEN 1 THEN 'store 1'
                               WHEN 2 THEN 'store 2'
                               ELSE store_id::text
                             END;
END;
$$
LANGUAGE plpgsql;

评论

0赞 Jenna J 10/1/2023
成功了!!谢谢!!我已经被困在这个问题上几个小时了。
0赞 Adrian Klaver 10/1/2023
仅供参考,您不必创建新列即可执行此操作。您可以就地更改列。
0赞 Ergest Basha 10/1/2023 #6

首先将列数据类型从整数更改为文本,然后进行简单的更新就可以了。在更新中,我们使用所请求的 store_id-s 的连接。store_id上的索引将加快查询速度。

第 1 步

ALTER TABLE detailed_sales ALTER COLUMN store_id TYPE TEXT;

步骤 2

update detailed_sales 
  set store_id = 'Store ' || store_id 
where  store_id in ('1','2');

查看示例


我建议您保持store_id原样,您可以在检索数据时(在选择期间)添加关键字“存储”

评论

1赞 Luuk 10/1/2023
为什么不做:set store_id = 'Store ' || store_id >>
1赞 Ergest Basha 10/1/2023
@Luuk对了,我不知道为什么我把串联复杂化了,谢谢你的洞察力