Rails 3 thực thi truy vấn sql tùy chỉnh mà không cần mô hình


105

Tôi cần viết một script ruby ​​độc lập để xử lý cơ sở dữ liệu. Tôi đã sử dụng mã được đưa ra bên dưới trong rails 3

@connection = ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "localhost",
:database => "siteconfig_development",
:username => "root",
:password => "root123"
)

results = @connection.execute("select * from users")
results.each do |row|
puts row[0]
end

nhưng gặp lỗi: -

`<main>': undefined method `execute' for #<ActiveRecord::ConnectionAdapters::ConnectionPool:0x00000002867548> (NoMethodError)

những gì tôi đang thiếu ở đây?

GIẢI PHÁP

Sau khi nhận được giải pháp từ denis-bu, tôi đã sử dụng nó theo cách và điều đó cũng hoạt động.

@connection = ActiveRecord::Base.establish_connection(
            :adapter => "mysql2",
            :host => "localhost",
            :database => "siteconfig_development",
            :username => "root",
            :password => "root123"
)

sql = "SELECT * from users"
@result = @connection.connection.execute(sql);
@result.each(:as => :hash) do |row| 
   puts row["email"] 
end

Câu trả lời:


168

Có thể thử cái này:

ActiveRecord::Base.establish_connection(...)
ActiveRecord::Base.connection.execute(...)

14
FWIW, Sử dụng các tham số rỗng không phải là ruby ​​thành ngữ. Vì vậy, làm connection.executehơnconnection().execute
radixhound

Cũng hoạt động trên Rails 4.
Leigh McCulloch

github.com/igorkasyanchuk/execute_sql mã ít hơn là cần thiết và bạn có thể làm điều đó trong bảng điều khiển trực tiếp rails
Igor Kasyanchuk

100
connection = ActiveRecord::Base.connection
connection.execute("SQL query") 

8
Trong trường hợp này, connection = ActiveRecord :: Base.connection; connect.execute ("Truy vấn SQL") sẽ hoạt động. Đánh máy ít hơn!
Watusimoto

16
Hoặc chỉ cầnActiveRecord::Base.connection.execute("SQL query")
Kasper Grubbe

3
Kết nối này có thể phải được trả lại nhóm kết nối sau đó để tránh các vấn đề về luồng: ActiveRecord::Base.connection_pool.checkin(connection) apidock.com/rails/ActiveRecord/ConnectionAdapters/…
lee

35

Tôi khuyên bạn nên sử dụng ActiveRecord::Base.connection.exec_querythay vì ActiveRecord::Base.connection.executenó trả vềActiveRecord::Result (có sẵn trong rails 3.1+) dễ làm việc hơn một chút.

Sau đó, bạn có thể truy cập vào nó trong nhiều kết quả trong nhiều cách khác nhau như .rows, .eachhoặc.to_hash

Từ các tài liệu :

result = ActiveRecord::Base.connection.exec_query('SELECT id, title, body FROM posts')
result # => #<ActiveRecord::Result:0xdeadbeef>


# Get the column names of the result:
result.columns
# => ["id", "title", "body"]

# Get the record values of the result:
result.rows
# => [[1, "title_1", "body_1"],
      [2, "title_2", "body_2"],
      ...
     ]

# Get an array of hashes representing the result (column => value):
result.to_hash
# => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
      {"id" => 2, "title" => "title_2", "body" => "body_2"},
      ...
     ]

# ActiveRecord::Result also includes Enumerable.
result.each do |row|
  puts row['title'] + " " + row['body']
end

lưu ý: đã sao chép câu trả lời của tôi từ đây


1
Như đã nêu, execute_query trả về kết quả thực - những gì tôi muốn, trong khi thực thi chỉ trả về thông tin trạng thái.
Paul Chernoch

24

Bạn cũng có thể sử dụng find_by_sql

# A simple SQL query spanning multiple tables
Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id"
> [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "first_name"=>"Quentin"}>, ...]

tập lệnh của tôi nằm ngoài ứng dụng rails nên tôi không nghĩ rằng find_by_sql sẽ hoạt động.
neeraj

4
bạn nói đúng, tôi đọc câu hỏi của bạn quá nhanh. Câu trả lời này có thể giúp những người khác đến trang này dựa trên tiêu đề câu hỏi của bạn.
montrealmike

làm thế nào để nhận được không phải là một mảng mà là quan hệ?
Малъ Скрылевъ

4

Còn cái này thì sao :

@client = TinyTds::Client.new(
      :adapter => 'mysql2',
      :host => 'host',
      :database => 'siteconfig_development',
      :username => 'username',
      :password => 'password'

sql = "SELECT * FROM users"

result = @client.execute(sql)

results.each do |row|
puts row[0]
end

Bạn cần cài đặt đá quý TinyTds, vì bạn không chỉ định nó trong câu hỏi của mình, tôi không sử dụng Active Record


1
Chắc chắn, TinyTds là toàn bộ đá quý khác .. Nó không phải là ActiveRecord. Để sử dụng nó, bạn nên cài đặt nó riêng biệt.
denis-bu

1
Tôi không muốn sử dụng bất kỳ GEM bổ sung nào miễn là mysql2 và bản ghi hoạt động có sẵn
neeraj

Tốt, bạn nên đề cập đến điều đó trong câu hỏi của mình (thẻ / tiêu đề)
kiến

2
TinyTDS hoạt động với MSSQL và Sybase, nó không hoạt động với MySQL. ant: Bạn nên đề cập đến điều đó trong câu trả lời của mình, và không cho rằng OP đang sử dụng cùng một DBMS thích hợp như bạn.
cliffordheath
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.