【问题标题】:Iterate each row and perform update accordingly迭代每一行并相应地执行更新
【发布时间】:2023-01-12 03:22:51
【问题描述】:

我有 PostgreSQL SQL,它应该在名为 source_username 的列中查找反斜杠,如果它找到反斜杠,它应该用相同的值替换 source_username 列的当前值,但反斜杠前没有字符。

例如:

在 source_username 之前:域\用户名

在 source_username 之后:用户名

with os_user as (
    select source_username from itpserver.managed_incidents mi;
),
osUserWithoutDomain as (
         select (
                        case when (select * from os_user) ilike '%\\%' and (select position('-' in (select * from os_user))>= 1) and (select length((select * from os_user)) != (select position('-' in (select * from os_user))) + 1)
    then (
select substring(

               (select * from os_user),(select position('\' in (select * from os_user)) + 1),(select length((select * from os_user)) - 1)
           ))
      else ((select * from os_user))

end
)
)




UPDATE itpserver.managed_incidents SET source_username  = replace(source_username, (select * from os_user), (select * from osUserWithoutDomain)),
                                       description  = replace(description , (select * from os_user), (select * from osUserWithoutDomain)),
                                       additional_info  = replace(additional_info , (select * from os_user), (select * from osUserWithoutDomain)),
                                       typical_behavior  = replace(typical_behavior , (select * from os_user), (select * from osUserWithoutDomain)),
                                       raw_description  = replace(raw_description , (select * from os_user), (select * from osUserWithoutDomain));

当表中只有一行时,此 SQL 工作正常。

如果我有多行,我需要通过添加 where id = <id> 来指定我想要使用的行

我希望迭代所有相关行(source_username 包含反斜杠的所有行)并在每一行上执行上面的 SQL。

我试着用 LOOP 来做到这一点:

create or replace function fetcher()
returns void as $$
declare 
emp record;
begin 
for emp in select * 
from itpserver.managed_incidents
order by id
limit 10
loop 
    
raise notice '%', emp.id;

<my sql> where id = emp.id

end loop;
end;
$$language plpgsql;


select fetcher();

但是,我收到一个错误,因为我认为它不喜欢“with”语句。

知道我该怎么做吗?

【问题讨论】:

  • 当我在表中只有一行时,此 SQL 工作正常....... 所以:这个想法是 case/when 使用一个值,而不是记录集。例如sql case when (select * from os_user) ilike '%\\%' 如果这个select返回多条记录,它已经是一个记录集。 case/when 不知道要取哪条记录,因为不止一条。所以它不再是标量。
  • 那将是单个 UPDATE 语句而不是循环。

标签: sql postgresql


【解决方案1】:

它远比那简单。您需要使用 SUBSTRSTRPOS 函数。看一下这个查询的结果。

https://dbfiddle.uk/9-yPKn6E

with os_user (source_username) as (
  select 'domainusername'
  union select 'mydomainjoe'
  union select 'janet'
)
select u.source_username
, strpos(u.source_username, '')
, substr(u.source_username, strpos(u.source_username, '') + 1)
from os_user u
source_username strpos substr
domainusername 7 username
janet 0 janet
mydomainjoe 9 joe

你需要的是:

UPDATE itpserver.managed_incidents
SET source_username  =                                             substr(source_username, strpos(source_username, '') + 1)
  , description      = replace(description      , source_username, substr(source_username, strpos(source_username, '') + 1))
  , additional_info  = replace(additional_info  , source_username, substr(source_username, strpos(source_username, '') + 1))
  , typical_behavior = replace(typical_behavior , source_username, substr(source_username, strpos(source_username, '') + 1))
  , raw_description  = replace(raw_description  , source_username, substr(source_username, strpos(source_username, '') + 1));

这是基于长期使用 SQL Server 的经验和对 Postgresql 的一些快速文档搜索。 UPDATE 语句可能不会像我预期的那样工作。

【讨论】:

    【解决方案2】:

    SQL 设计/默认适用于完整的数据集。因此,它从语言中完全消除了循环——不需要它们。 (嗯,不完全有递归查询)。您的任务是在一个带有简单正则表达式的更新语句中完成的。请参阅文档String Functions

    update managed_incidents
       set source_username = regexp_replace(source_username,'.*\(.*)','');
    

    Demo here

    主要带走:从您的 SQL 词汇表中删除过程逻辑术语(for、循环、if then...)。 (你选择替代品案件.)

    【讨论】:

      猜你喜欢
      • 2019-07-03
      • 1970-01-01
      • 2018-03-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 2018-12-27
      • 2021-07-09
      • 2017-07-17
      相关资源
      最近更新 更多