programing

Rails raw SQL

topblog 2023. 4. 18. 21:41
반응형

Rails raw SQL

이 코드를 raw sql로 변환하여 레일에서 사용하려면 어떻게 해야 합니까?왜냐하면 제가 이 코드를 heroku에 배치했을 때 요청 타임아웃 오류가 발생했기 때문입니다.raw sql을 사용하는 것이 더 빠를 것 같습니다.

@payments = PaymentDetail.joins(:project).order('payment_details.created_at desc')
@payment_errors = PaymentError.joins(:project).order('payment_errors.created_at desc')

@all_payments = (@payments + @payment_errors)

다음과 같이 할 수 있습니다.

sql = "Select * from ... your sql query here"
records_array = ActiveRecord::Base.connection.execute(sql)

records_array그러면 반복할 수 있는 배열 내의 SQL 쿼리의 결과가 됩니다.

오래된 거 알아요하지만 오늘도 같은 문제를 겪고 있었고 해결책을 찾았습니다.

Model.find_by_sql

결과를 인스턴스화하는 경우:

Client.find_by_sql("
  SELECT * FROM clients
  INNER JOIN orders ON clients.id = orders.client_id
  ORDER BY clients.created_at desc
")
# => [<Client id: 1, first_name: "Lucas" >, <Client id: 2, first_name: "Jan">...]

Model.connection.select_all('sql').to_hash

값의 해시만 원하는 경우:

Client.connection.select_all("SELECT first_name, created_at FROM clients
   WHERE id = '1'").to_hash
# => [
  {"first_name"=>"Rafael", "created_at"=>"2012-11-10 23:23:45.281189"},
  {"first_name"=>"Eileen", "created_at"=>"2013-12-09 11:22:35.221282"}
]

결과 개체:

select_alla를 반환하다result물건.이걸로 마술도 할 수 있어요.

result = Post.connection.select_all('SELECT id, title, body FROM posts')
# 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

출처:

  1. ActiveRecord - SQL에 의한 Findinig.
  2. Ruby on Rails - 활성 레코드 결과.

다음 방법으로 원시 쿼리를 실행할 수 있습니다.ActiveRecord그리고 SQL block을 사용하는 것이 좋습니다.

query = <<-SQL 
  SELECT * 
  FROM payment_details
  INNER JOIN projects 
          ON projects.id = payment_details.project_id
  ORDER BY payment_details.created_at DESC
SQL

result = ActiveRecord::Base.connection.execute(query)

직접 SQL을 실행하여 두 테이블에 대해 단일 쿼리를 가질 수 있습니다.이 예에서는 변수를 문자열 자체에 직접 삽입하지 않도록 하기 위해 sanitized 쿼리 예를 제공합니다(SQL 주입 위험).

@results = []
ActiveRecord::Base.connection.select_all(
  ActiveRecord::Base.send(:sanitize_sql_array, 
   ["... your SQL query goes here and ?, ?, ? are replaced...;", a, b, c])
).each do |record|
  # instead of an array of hashes, you could put in a custom object with attributes
  @results << {col_a_name: record["col_a_name"], col_b_name: record["col_b_name"], ...}
end

편집: Huy가 말한 것처럼 간단한 방법은ActiveRecord::Base.connection.execute("...")또 다른 방법은ActiveRecord::Base.connection.exec_query('...').rowsnative prepared 스테이트먼트를 사용할 수 있습니다.예를 들어 postgres를 사용하는 경우 raw_connection, prepared, exec_pared 스테이트먼트를 https://stackoverflow.com/a/13806512/178651에서 설명한 바와 같이 사용할 수 있습니다.

raw SQL fragment를 ActiveRecord 관계 쿼리(http://guides.rubyonrails.org/active_record_querying.html 및 관련성, 범위 등)에 넣을 수도 있습니다.ActiveRecord 관계 쿼리를 사용하여 동일한 SQL을 구축하고 Ernie가 http://erniemiller.org/2010/03/28/advanced-activerecord-3-queries-with-arel/에서 언급한 바와 같이 ARel을 사용하여 멋진 작업을 수행할 수 있습니다.물론 다른 ORM, 보석 등도 있습니다.

이것이 많이 사용되며 인덱스를 추가해도 다른 성능/리소스 문제가 발생하지 않을 경우 payment_details.created_at 및 payment_errors.created_at에 대한 인덱스를 DB에 추가하는 것을 고려해 보십시오.

모든 레코드가 동시에 표시되지 않고 많은 레코드가 표시될 필요가 있는 경우 페이지 번호 부여를 고려해 주십시오.

페이지 매김이 필요한 경우 먼저 payment_details 테이블과 payment_errors 테이블을 결합한 payment_records라는 DB에 뷰를 작성한 후 뷰 모델을 만듭니다(읽기 전용).일부 DB는 구체화된 보기를 지원하므로 성능을 향상시키는 데 좋은 방법이 될 수 있습니다.

또한 Rails 서버와 DB 서버의 하드웨어 또는 VM 사양, 구성, 디스크 공간, 네트워크 속도/레이텐시 등, 근접성 등을 고려하십시오.또한 DB를 Rails 앱과 다른 서버/VM에 설치하는 것도 고려해 보십시오.

exec_queryActiveRecord클래스: 오브젝트로 변환되는 쿼리의 매핑을 반환하기 때문에 서브젝트가 Raw SQL일 때 오브젝트를 반복하는 것이 매우 실용적이고 생산적이기 때문입니다.

예:

values = ActiveRecord::Base.connection.exec_query("select * from clients")
p values

다음 전체 쿼리를 반환합니다.

[{"id": 1, "name": "user 1"}, {"id": 2, "name": "user 2"}, {"id": 3, "name": "user 3"}]

값 리스트만 가져오려면

p values.rows

[[1, "user 1"], [2, "user 2"], [3, "user 3"]]

필드만 가져오려면 열

p values.columns

["id", "name"]

raw SQL을 ActiveRecord 조건과 혼재시킬 수도 있습니다.예를 들어 다음과 같은 조건의 함수를 호출하는 경우입니다.

my_instances = MyModel.where.not(attribute_a: nil)
  .where('crc32(attribute_b) = ?', slot)
  .select(:id)

언급URL : https://stackoverflow.com/questions/14824453/rails-raw-sql-example

반응형