代码之家  ›  专栏  ›  技术社区  ›  Craig Walker

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

  •  13
  • Craig Walker  · 技术社区  · 16 年前

    我想在Rails查询中执行数据库端字符串连接,并以独立于数据库的方式执行。

    SQL-92指定双栏( || )作为连接运算符。不幸的是,看起来mssqlserver不支持它;它使用 + 相反。

    3 回复  |  直到 11 年前
        1
  •  10
  •   aNoble    16 年前

    我也有同样的问题,从来没有想出任何内置到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
    

        2
  •  6
  •   Eric Anderson    13 年前

    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 = ?
    

        3
  •  0
  •   LanceH    16 年前

    如果您想要一些与Rails无关的内容,则需要返回要连接的值,并在将数据传递到Rails之后执行此操作(或者在将数据传递到数据库之前在Rails中执行此操作)。

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

    任何rails抽象都必须发生在这样一个点上,即您可能只是在使用常规Ruby进行连接,否则我完全误解了这个问题。