Rails中与数据库无关的SQL字符串连接

我想在Rails查询中进行数据库端字符串连接,并以与数据库无关的方式进行。

SQL-92指定双栏( || )作为连接运算符。 不幸的是,它看起来像MS SQL Server不支持它; 它用+代替。

我猜测Rails的SQL语法抽象已经解决了特定于db的运算符问题。 如果确实存在,我该如何使用它?

我有同样的问题,从来没有想出任何内置在Rails中的东西。 所以我写了这个小方法。

 # Symbols should be used for field names, everything else will be quoted as a string def db_concat(*args) adapter = configurations[RAILS_ENV]['adapter'].to_sym args.map!{ |arg| arg.class==Symbol ? arg.to_s : "'#{arg}'" } case adapter when :mysql "CONCAT(#{args.join(',')})" when :sqlserver args.join('+') else args.join('||') end end 

我想有人应该真正编写某种SQL帮助程序插件,它可以使用当前适配器的正确函数或运算符自动格式化简单的SQL表达式。 也许我会自己写一个。

它还没有得到太多的使用,但我写了下面的代码似乎解决了这个问题。 这个猴子修补适配器有一个方法来支持它:

 module ActiveRecord module ConnectionAdapters class AbstractAdapter # Will return the given strings as a SQL concationation. By default # uses the SQL-92 syntax: # # concat('foo', 'bar') -> "foo || bar" def concat(*args) args * " || " end end class AbstractMysqlAdapter < AbstractAdapter # Will return the given strings as a SQL concationation. # Uses MySQL format: # # concat('foo', 'bar') -> "CONCAT(foo, bar)" def concat(*args) "CONCAT(#{args * ', '})" end end class SQLServerAdapter < AbstractAdapter # Will return the given strings as a SQL concationation. # Uses MS-SQL format: # # concat('foo', 'bar') -> foo + bar def concat(*args) args * ' + ' end end end end 

有了这个,你应该能够在你的代码中执行以下操作:

 class User < ActiveRecord::Base def self.find_by_name(name) where("#{connection.concat('first_name', 'last_name')} = ?", name) end end 

这将在SQL-92数据库(Oracle,SQLite,PostgreSQL)上输出以下SQL查询:

 SELECT * FROM users WHERE first_name || last_name = ? 

对于MySQL,它输出:

 SELECT * FROM users WHERE CONCAT(first_name, last_name) = ? 

对于SQL Server,它输出

 SELECT * FROM users WHERE first_name + last_name = ? 

显然,您可以将此概念扩展到其他数据库适配器。

如果你想要Rails中立的东西,你将需要返回你想要连接的值,并在数据传递到rails之后执行(或者在将它提供给数据库之前在rails中执行)。

看起来Mysql使用CONCAT(),Postgres ||,Oracle CONCAT()或||,T-SQL +。

任何相同的rails抽象必须在你可以使用常规Ruby进行连接的地方进行,或者我完全误解了这个问题。