用于删除反斜杠的 Postgres 命令在控制台中有效,但不适用于 ActiveRecord::Base.connection.execute

Postgres command to remove backslashes works in console, but not with ActiveRecord::Base.connection.execute

此 Postgres 命令在 psql 命令行 运行 时删除所有反斜杠:

UPDATE table SET column = REGEXP_REPLACE(column, '\B', '', 'g');

这个 Rails 命令不起作用(它 运行 没有错误,但没有删除反斜杠):

ActiveRecord::Base.connection.execute("UPDATE table SET column = REGEXP_REPLACE(column, '\B', '', 'g'))

看起来 Rails 更改了查询并 运行s 这个(我检查了 运行 在控制台中查询的输出):

UPDATE table SET column = REGEXP_REPLACE(column, 'B', '', 'g')

psql 命令行 运行 时,Postgres 命令也成功删除了反斜杠:

UPDATE table SET column = REGEXP_REPLACE(column, '\', '', 'g')

当 运行 和 Rails:

时,同样的 Postgres 命令出人意料地出错
ActiveRecord::Base.connection.execute("UPDATE table SET column = REGEXP_REPLACE(column, '\', '', 'g')")

这是错误:

PG::InvalidRegularExpression: ERROR: invalid regular expression: invalid escape \ sequence

这是我 Gemfile 中设置的 Postgres 版本:

gem 'pg', '>= 0.18', '< 2.0'

能否解释一下为什么我会收到此错误以及如何编写 Rails 代码来删除列中的所有反斜杠?这将是 运行 大型数据集,我需要一个快速的解决方案。

你想要做的事情很复杂,因为有很多东西想要以自己的方式解释 \

  1. \ 表示 Ruby 中双引号字符串中的内容。所以 "\B" 只是在 Ruby 中写 "B" 的一种误导和复杂的方式。您需要说 "\B" 才能获得包含两个字符 \B.

  2. 的字符串
  3. \ 表示 PostgreSQL 正则表达式中的内容。因此,\B 在 PostgreSQL 的正则表达式中的存在,这样当你在另一种语言中查看 \\ 之类的东西时,你不必计算 \,你d 只是有一些不那么丑的东西,比如 \B.

要解决你的问题,你可以正确地逃避你的转义:

ActiveRecord::Base.connection.execute("UPDATE table SET column = REGEXP_REPLACE(column, '\B', '', 'g')")

当数据库看到时,它会看到:

UPDATE table SET column = REGEXP_REPLACE(column, '\B', '', 'g')

因为 \ 在双引号 Ruby 字符串中表示 "give me just one \"。

我可能会进一步简化并使用 SQL replace function:

replace(string text, from text, to text)
Replace all occurrences in string of substring from with substring to.

与 Ruby 中的 %q{...} 字符串组合:

ActiveRecord::Base.connection.execute(%q{
  update table
  set column = replace(column, '\', '')
})

%q{...} 摆脱了一个转义问题,因为它的作用类似于 Ruby 中的 single-quoted 字符串,因此 \ 没有任何特殊意义。在 SQL 中使用 replace 摆脱了另一个转义问题,因为它只适用于普通的旧字符串(而不是字符串表示的正则表达式)所以 \ 再次没有任何意义。