Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails3: SQL execution with hash substitution like .where()

With a simple model like that

class Model < ActiveRecord::Base
   # ...
end

we can do queries like that

Model.where(["name = :name and updated_at >= :D", \
  { :D => (Date.today - 1.day).to_datetime, :name => "O'Connor" }])

Where the values in the hash will be substituted into the final SQL statement with proper escaping depending on the underlying database engine.

I would like to know a similar feature for SQL execution like:

ActiveRecord::Base.connection.execute( \
    ["update models set name = :name, hired_at = :D where id = :id;"], \
    { :id => 73465, :D => DateTime.now, :name => "O'My God" }] \
  ) # THIS CODE IS A FANTASY. NOT WORKING.

(Please do not solve the example with loading a Model object, modifying and then saving! The example is only an illustration for the feature I would like to have / know. Concentrate on the subject!)

The original problem is that I want to insert large amount (many thousand lines) of data into the database. I want to use some features of the SQL abstraction of the ActiveRecord framework but I don't want to use model objects based on ActiveRecord::Base because they are damn slow! (8 queries per second for my current problem.)

like image 467
Notinlist Avatar asked Jan 30 '26 22:01

Notinlist


2 Answers

query = ActiveRecord::Base.connection.raw_connection.prepare("INSERT INTO users (name) VALUES(:name)")
query.execute(:name => 'test_name')
query.close
like image 67
Vasiliy Ermolovich Avatar answered Feb 01 '26 15:02

Vasiliy Ermolovich


Extending the @peufeu solution with concrete code example for bulk insert:

users_places = []
users_values = []
timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S')
params[:users].each do |user|
    users_places << "(?,?,?,?)"
    users_values << user[:name] << user[:punch_line] << timestamp << timestamp
end

bulk_insert_users_sql_arr = ["INSERT INTO users (name, punch_line, created_at, updated_at) VALUES #{users_places.join(", ")}"] + users_values
begin
    sql = ActiveRecord::Base.send(:sanitize_sql_array, bulk_insert_users_sql_arr)
    ActiveRecord::Base.connection.execute(sql)
rescue
    "something went wrong with the bulk insert sql query"
end

Here is the reference to sanitize_sql_array method in ActiveRecord::Base, it generates the proper query string by escaping the single quotes in the strings. For example the punch_line "Don't let them get you down" will become "Don\'t let them get you down".

like image 22
Zeeshan Avatar answered Feb 01 '26 13:02

Zeeshan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!