【问题标题】:SQL Query to Substitute value in the scanned results and update that field of TableSQL 查询以替换扫描结果中的值并更新表的该字段
【发布时间】:2017-10-02 20:17:28
【问题描述】:

我有一对多的组织:用户关系。 我想获取 Organization 的所有 User 模型的用户名,捕获该用户名的一部分并用新值附加/替换它。

这是我的做法:

  1. 形成原始 SQL 以获取匹配的用户名并将其替换为新值。

raw = "SELECT REGEXP_REPLACE($1::string[], '(^[a-z0-9]+)((\s[a-z0-9]+))*\@([a-z0-9]+)$', m.name[1] || '@' || $2) FROM (SELECT REGEXP_MATCHES($1::string[], '(^[a-z0-9]+)((\s[a-z0-9]+))*\@([a-z0-9]+)$') AS name) m"

  1. 获取匹配的用户名并将其替换为新值。 用户名:从可查询中检索到的用户名列表

Repo.query(raw, [usernames, a_string])

  1. 我遇到的错误

    SELECT REGEXP_REPLACE($1::string[], '(^[a-z0-9]+)(( [a-z0-9]+))@([a-z0-9]+ )$', m.name[1] || '@' || $2) FROM (SELECT REGEXP_MATCHES($1::string[], '(^[a-z0-9]+)(( [a-z0- 9]+))@([a-z0-9]+)$') AS 名称) m [["tradeboox@trdbx18"], "trdbx17"] {:错误, %Postgrex.Error{connection_id: 7222, message: nil, postgres:%{code::undefined_object,文件:“parse_type.c”,行:“257”, 消息:“类型\”字符串[]\“不存在”,pg_code:“42704”, 位置:“137”,例程:“typenameType”,严重性:“ERROR”, 未知:“错误”}}}

仅供参考:User 模型的 username 字段类型为 citext


  1. 获得替换值后,我想使用类似
  2. 的内容更新 User

update([u], set: [username: new_values])

关于如何进行此操作的任何想法?

`

【问题讨论】:

  • 投票结束时,请发表评论,以便读者清楚了解哪些内容。请参阅已接受的答案以进行澄清。

标签: sql postgresql elixir ecto


【解决方案1】:

PostgreSQL 中没有 string 类型。

函数regexp_matches 仅接受text 作为第一个参数,并且它不能是数组。所以你需要做的是首先将该类型更改为文本,然后unnest($1::text[]) 你的数组。使用这些正则表达式遍历结果行集。

raw = "SELECT REGEXP_REPLACE(m.item, '(^[a-z0-9]+)((\s[a-z0-9]+))*\@([a-z0-9]+)$', m.name[1] || '@' || $2)
         FROM (
               SELECT item, REGEXP_MATCHES(item, '(^[a-z0-9]+)((\s[a-z0-9]+))*\@([a-z0-9]+)$') AS name
                 FROM unnest($1::text[]) AS items(item)
              ) m"

如果我理解正确,您正在尝试用一些不同的字符串替换 @ 之后的所有内容 - 如果是这种情况,那么您的正则表达式会将空格键之后的任何内容放入匹配数组的第二个元素中。你会需要这个:((^[a-z0-9]+)(\s[a-z0-9]+)*)

如果上述情况属实,那么您可以通过以下方式轻松完成所有工作:

SELECT REGEXP_REPLACE(item, '((^[a-z0-9]+)(\s[a-z0-9]+)*)\@([a-z0-9]+)$', '\1' || $2) AS name
  FROM unnest($1::text[]) AS items(item)

然而,最佳做法是在 UPDATE 语句中简单地替换:

UPDATE "User" SET
  name = concat(split_part(name, '@', 1), '@', $2)
WHERE organization_id = $3
  AND name ~* '^[a-z0-9]+(\s[a-z0-9]+)*\@[a-z0-9]+$'

它将按@ 拆分名称,获取第一部分,然后附加@ 以及分配给$2 的任何内容(我猜是域名)。它只会更新与某个 id 匹配的 organization_id 并且名称与您的正则表达式匹配的行(如果您想更改组织中的所有名称,您可以省略正则表达式)。确保该表实际命名为 User,区分大小写,或删除双引号以具有不区分大小写的版本。

很遗憾,我不知道如何在您的 ORM 中执行此操作。

【讨论】:

  • 这是完美的。不,正则表达式是我所构想的。 SQL 部分是我无法理解字符串数据类型问题的地方。 SQL 完美运行。让我检查一下整个事情在我的 ORM 中是否有效
猜你喜欢
  • 2020-10-01
  • 2021-07-13
  • 1970-01-01
  • 2010-11-11
  • 2015-02-27
  • 2015-09-04
  • 2011-08-09
  • 1970-01-01
  • 2019-06-09
相关资源
最近更新 更多