SQL查询替换扫描结果中的值并更新表的该字段

时间:2017-10-01 13:39:27

标签: sql postgresql elixir ecto

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

以下是我的工作方式:

  1. 形成原始SQL以获取匹配的用户名并将其替换为新值。
  2. 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. 获取匹配的用户名并将其替换为新值。 usernames:从可查询中检索的用户名列表
    2. 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 [[&#34 ; tradeboox @ trdbx18"]," trdbx17"] {:错误,  %Postgrex.Error {connection_id:7222,message:nil,   postgres:%{code :: undefined_object,file:" parse_type.c",line:" 257",     消息:"键入\" string [] \"不存在",pg_code:" 42704",     位置:" 137",例程:" typenameType",severity:" ERROR",     未知:"错误"}}}

      2. 仅供参考:用户模型的username字段属于citext

        类型
        1. 获得替换后的值,我想用
        2. 更新用户

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

          有关如何处理此事的任何想法?

          `

1 个答案:

答案 0 :(得分: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"

如果我理解正确,你试图用@之后用一些不同的字符串替换所有内容 - 如果是这种情况,那么你的正则表达式会将空格键之后的任何东西放到matches数组的第二个元素中。您需要这样做:((^[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的任何内容(我猜的域名)。它将仅更新organization_id与某个id匹配且名称与正则表达式匹配的行(如果要更改组织中的所有名称,则可以省略regexp)。确保实际命名为User,区分大小写或删除双引号的表具有不区分大小写的版本。

我遗憾地不知道如何在你的ORM中做到这一点。